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/IDwellModule.cs37
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInterregionComms.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs27
-rw-r--r--OpenSim/Region/Framework/ModuleLoader.cs3
-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/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs15
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs45
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs139
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs131
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs766
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs161
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs738
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs885
19 files changed, 2245 insertions, 879 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/IDwellModule.cs b/OpenSim/Region/Framework/Interfaces/IDwellModule.cs
new file mode 100644
index 0000000..db50439
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IDwellModule.cs
@@ -0,0 +1,37 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using OpenMetaverse;
29using OpenSim.Framework;
30
31namespace OpenSim.Region.Framework.Interfaces
32{
33 public interface IDwellModule
34 {
35 int GetDwell(UUID parcelID);
36 }
37}
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/IInterregionComms.cs b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
index 2d6287f..67a500f 100644
--- a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
@@ -68,6 +68,14 @@ namespace OpenSim.Region.Framework.Interfaces
68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri); 68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri);
69 69
70 /// <summary> 70 /// <summary>
71 /// Close chid agent.
72 /// </summary>
73 /// <param name="regionHandle"></param>
74 /// <param name="id"></param>
75 /// <returns></returns>
76 bool SendCloseChildAgent(ulong regionHandle, UUID id);
77
78 /// <summary>
71 /// Close agent. 79 /// Close agent.
72 /// </summary> 80 /// </summary>
73 /// <param name="regionHandle"></param> 81 /// <param name="regionHandle"></param>
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/ModuleLoader.cs b/OpenSim/Region/Framework/ModuleLoader.cs
index 23be9c2..69ba2042 100644
--- a/OpenSim/Region/Framework/ModuleLoader.cs
+++ b/OpenSim/Region/Framework/ModuleLoader.cs
@@ -226,7 +226,8 @@ namespace OpenSim.Region.Framework
226 "[MODULES]: Could not load types for [{0}]. Exception {1}", pluginAssembly.FullName, e); 226 "[MODULES]: Could not load types for [{0}]. Exception {1}", pluginAssembly.FullName, e);
227 227
228 // justincc: Right now this is fatal to really get the user's attention 228 // justincc: Right now this is fatal to really get the user's attention
229 throw e; 229 // TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to?
230 //throw e;
230 } 231 }
231 } 232 }
232 233
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/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index ef125cd..0c9759d 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -55,8 +55,12 @@ namespace OpenSim.Region.Framework.Scenes
55 55
56 public delegate void OnTerrainTickDelegate(); 56 public delegate void OnTerrainTickDelegate();
57 57
58 public delegate void OnTerrainUpdateDelegate();
59
58 public event OnTerrainTickDelegate OnTerrainTick; 60 public event OnTerrainTickDelegate OnTerrainTick;
59 61
62 public event OnTerrainUpdateDelegate OnTerrainUpdate;
63
60 public delegate void OnBackupDelegate(IRegionDataStore datastore, bool forceBackup); 64 public delegate void OnBackupDelegate(IRegionDataStore datastore, bool forceBackup);
61 65
62 public event OnBackupDelegate OnBackup; 66 public event OnBackupDelegate OnBackup;
@@ -716,6 +720,26 @@ namespace OpenSim.Region.Framework.Scenes
716 } 720 }
717 } 721 }
718 } 722 }
723 public void TriggerTerrainUpdate()
724 {
725 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
726 if (handlerTerrainUpdate != null)
727 {
728 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
729 {
730 try
731 {
732 d();
733 }
734 catch (Exception e)
735 {
736 m_log.ErrorFormat(
737 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
738 e.Message, e.StackTrace);
739 }
740 }
741 }
742 }
719 743
720 public void TriggerTerrainTick() 744 public void TriggerTerrainTick()
721 { 745 {
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index de3c360..8cd0160 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -211,12 +211,19 @@ namespace OpenSim.Region.Framework.Scenes
211 211
212 if (entity is SceneObjectPart) 212 if (entity is SceneObjectPart)
213 { 213 {
214 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
215 if (physActor == null || !physActor.IsPhysical)
216 priority += 100;
217
218 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) 214 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
215 {
219 priority = 1.0; 216 priority = 1.0;
217 }
218 else
219 {
220 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
221 if (physActor == null || !physActor.IsPhysical)
222 priority += 100;
223 }
224
225 if (((SceneObjectPart)entity).ParentGroup.RootPart != (SceneObjectPart)entity)
226 priority +=1;
220 } 227 }
221 return priority; 228 return priority;
222 } 229 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 750b1f7..55c1575 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -94,6 +94,22 @@ namespace OpenSim.Region.Framework.Scenes
94 94
95 public void AddInventoryItem(UUID AgentID, InventoryItemBase item) 95 public void AddInventoryItem(UUID AgentID, InventoryItemBase item)
96 { 96 {
97 InventoryFolderBase folder;
98
99 if (item.Folder == UUID.Zero)
100 {
101 folder = InventoryService.GetFolderForType(AgentID, (AssetType)item.AssetType);
102 if (folder == null)
103 {
104 folder = InventoryService.GetRootFolder(AgentID);
105
106 if (folder == null)
107 return;
108 }
109
110 item.Folder = folder.ID;
111 }
112
97 if (InventoryService.AddItem(item)) 113 if (InventoryService.AddItem(item))
98 { 114 {
99 int userlevel = 0; 115 int userlevel = 0;
@@ -214,8 +230,7 @@ namespace OpenSim.Region.Framework.Scenes
214 { 230 {
215 // Needs to determine which engine was running it and use that 231 // Needs to determine which engine was running it and use that
216 // 232 //
217 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 233 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
218 errors = part.Inventory.GetScriptErrors(item.ItemID);
219 } 234 }
220 else 235 else
221 { 236 {
@@ -836,8 +851,12 @@ namespace OpenSim.Region.Framework.Scenes
836 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 851 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
837 { 852 {
838 SceneObjectPart part = GetSceneObjectPart(localID); 853 SceneObjectPart part = GetSceneObjectPart(localID);
839 SceneObjectGroup group = part.ParentGroup; 854 SceneObjectGroup group = null;
840 if (group != null) 855 if (part != null)
856 {
857 group = part.ParentGroup;
858 }
859 if (part != null && group != null)
841 { 860 {
842 TaskInventoryItem item = group.GetInventoryItem(localID, itemID); 861 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
843 if (item == null) 862 if (item == null)
@@ -1572,19 +1591,21 @@ namespace OpenSim.Region.Framework.Scenes
1572 // So that we know the database is upto date, 1591 // So that we know the database is upto date,
1573 // for when deleting the object from it 1592 // for when deleting the object from it
1574 ForceSceneObjectBackup(grp); 1593 ForceSceneObjectBackup(grp);
1594 if (remoteClient != null)
1595 {
1596 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1597 permissionToTakeCopy = false;
1598 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1599 permissionToTake = false;
1575 1600
1576 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1601 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1577 permissionToTakeCopy = false; 1602 permissionToDelete = false;
1578 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1579 permissionToTake = false;
1580
1581 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1582 permissionToDelete = false;
1583 1603
1604 }
1584 } 1605 }
1585 1606
1586 // Handle god perms 1607 // Handle god perms
1587 if (Permissions.IsGod(remoteClient.AgentId)) 1608 if (remoteClient != null && Permissions.IsGod(remoteClient.AgentId))
1588 { 1609 {
1589 permissionToTake = true; 1610 permissionToTake = true;
1590 permissionToTakeCopy = true; 1611 permissionToTakeCopy = true;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index e2ab643..c5fb198 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -149,6 +149,20 @@ namespace OpenSim.Region.Framework.Scenes
149 149
150 public IXfer XferManager; 150 public IXfer XferManager;
151 151
152 protected ISnmpModule m_snmpService = null;
153 public ISnmpModule SnmpService
154 {
155 get
156 {
157 if (m_snmpService == null)
158 {
159 m_snmpService = RequestModuleInterface<ISnmpModule>();
160 }
161
162 return m_snmpService;
163 }
164 }
165
152 protected IAssetService m_AssetService; 166 protected IAssetService m_AssetService;
153 protected IAuthorizationService m_AuthorizationService; 167 protected IAuthorizationService m_AuthorizationService;
154 168
@@ -609,6 +623,8 @@ namespace OpenSim.Region.Framework.Scenes
609 623
610 // Load region settings 624 // Load region settings
611 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID); 625 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID);
626 m_regInfo.WindlightSettings = m_storageManager.DataStore.LoadRegionWindlightSettings(m_regInfo.RegionID);
627
612 if (m_storageManager.EstateDataStore != null) 628 if (m_storageManager.EstateDataStore != null)
613 { 629 {
614 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID, false); 630 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 {
@@ -1025,6 +1041,15 @@ namespace OpenSim.Region.Framework.Scenes
1025 /// <param name="seconds">float indicating duration before restart.</param> 1041 /// <param name="seconds">float indicating duration before restart.</param>
1026 public virtual void Restart(float seconds) 1042 public virtual void Restart(float seconds)
1027 { 1043 {
1044 Restart(seconds, true);
1045 }
1046
1047 /// <summary>
1048 /// Given float seconds, this will restart the region. showDialog will optionally alert the users.
1049 /// </summary>
1050 /// <param name="seconds">float indicating duration before restart.</param>
1051 public virtual void Restart(float seconds, bool showDialog)
1052 {
1028 // notifications are done in 15 second increments 1053 // notifications are done in 15 second increments
1029 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request 1054 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request
1030 // It's a 'Cancel restart' request. 1055 // It's a 'Cancel restart' request.
@@ -1045,8 +1070,11 @@ namespace OpenSim.Region.Framework.Scenes
1045 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed); 1070 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed);
1046 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes"); 1071 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes");
1047 m_restartTimer.Start(); 1072 m_restartTimer.Start();
1048 m_dialogModule.SendNotificationToUsersInRegion( 1073 if (showDialog)
1074 {
1075 m_dialogModule.SendNotificationToUsersInRegion(
1049 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0))); 1076 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0)));
1077 }
1050 } 1078 }
1051 } 1079 }
1052 1080
@@ -1404,16 +1432,16 @@ namespace OpenSim.Region.Framework.Scenes
1404 // Check if any objects have reached their targets 1432 // Check if any objects have reached their targets
1405 CheckAtTargets(); 1433 CheckAtTargets();
1406 1434
1407 // Update SceneObjectGroups that have scheduled themselves for updates
1408 // Objects queue their updates onto all scene presences
1409 if (m_frame % m_update_objects == 0)
1410 m_sceneGraph.UpdateObjectGroups();
1411
1412 // Run through all ScenePresences looking for updates 1435 // Run through all ScenePresences looking for updates
1413 // Presence updates and queued object updates for each presence are sent to clients 1436 // Presence updates and queued object updates for each presence are sent to clients
1414 if (m_frame % m_update_presences == 0) 1437 if (m_frame % m_update_presences == 0)
1415 m_sceneGraph.UpdatePresences(); 1438 m_sceneGraph.UpdatePresences();
1416 1439
1440 // Update SceneObjectGroups that have scheduled themselves for updates
1441 // Objects queue their updates onto all scene presences
1442 if (m_frame % m_update_objects == 0)
1443 m_sceneGraph.UpdateObjectGroups();
1444
1417 if (m_frame % m_update_coarse_locations == 0) 1445 if (m_frame % m_update_coarse_locations == 0)
1418 { 1446 {
1419 List<Vector3> coarseLocations; 1447 List<Vector3> coarseLocations;
@@ -1742,6 +1770,7 @@ namespace OpenSim.Region.Framework.Scenes
1742 public void StoreWindlightProfile(RegionLightShareData wl) 1770 public void StoreWindlightProfile(RegionLightShareData wl)
1743 { 1771 {
1744 m_regInfo.WindlightSettings = wl; 1772 m_regInfo.WindlightSettings = wl;
1773 wl.Save();
1745 m_storageManager.DataStore.StoreRegionWindlightSettings(wl); 1774 m_storageManager.DataStore.StoreRegionWindlightSettings(wl);
1746 m_eventManager.TriggerOnSaveNewWindlightProfile(); 1775 m_eventManager.TriggerOnSaveNewWindlightProfile();
1747 } 1776 }
@@ -1920,14 +1949,24 @@ namespace OpenSim.Region.Framework.Scenes
1920 /// <returns></returns> 1949 /// <returns></returns>
1921 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1950 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1922 { 1951 {
1952
1953 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1954 Vector3 wpos = Vector3.Zero;
1955 // Check for water surface intersection from above
1956 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1957 {
1958 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1959 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1960 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1961 wpos.Z = wheight;
1962 }
1963
1923 Vector3 pos = Vector3.Zero; 1964 Vector3 pos = Vector3.Zero;
1924 if (RayEndIsIntersection == (byte)1) 1965 if (RayEndIsIntersection == (byte)1)
1925 { 1966 {
1926 pos = RayEnd; 1967 pos = RayEnd;
1927 return pos;
1928 } 1968 }
1929 1969 else if (RayTargetID != UUID.Zero)
1930 if (RayTargetID != UUID.Zero)
1931 { 1970 {
1932 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1971 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1933 1972
@@ -1949,7 +1988,7 @@ namespace OpenSim.Region.Framework.Scenes
1949 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1988 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1950 1989
1951 // Un-comment out the following line to Get Raytrace results printed to the console. 1990 // Un-comment out the following line to Get Raytrace results printed to the console.
1952 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1991 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1953 float ScaleOffset = 0.5f; 1992 float ScaleOffset = 0.5f;
1954 1993
1955 // If we hit something 1994 // If we hit something
@@ -1972,13 +2011,10 @@ namespace OpenSim.Region.Framework.Scenes
1972 //pos.Z -= 0.25F; 2011 //pos.Z -= 0.25F;
1973 2012
1974 } 2013 }
1975
1976 return pos;
1977 } 2014 }
1978 else 2015 else
1979 { 2016 {
1980 // We don't have a target here, so we're going to raytrace all the objects in the scene. 2017 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1981
1982 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 2018 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1983 2019
1984 // Un-comment the following line to print the raytrace results to the console. 2020 // Un-comment the following line to print the raytrace results to the console.
@@ -1987,13 +2023,12 @@ namespace OpenSim.Region.Framework.Scenes
1987 if (ei.HitTF) 2023 if (ei.HitTF)
1988 { 2024 {
1989 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 2025 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1990 } else 2026 }
2027 else
1991 { 2028 {
1992 // fall back to our stupid functionality 2029 // fall back to our stupid functionality
1993 pos = RayEnd; 2030 pos = RayEnd;
1994 } 2031 }
1995
1996 return pos;
1997 } 2032 }
1998 } 2033 }
1999 else 2034 else
@@ -2004,8 +2039,12 @@ namespace OpenSim.Region.Framework.Scenes
2004 //increase height so its above the ground. 2039 //increase height so its above the ground.
2005 //should be getting the normal of the ground at the rez point and using that? 2040 //should be getting the normal of the ground at the rez point and using that?
2006 pos.Z += scale.Z / 2f; 2041 pos.Z += scale.Z / 2f;
2007 return pos; 2042// return pos;
2008 } 2043 }
2044
2045 // check against posible water intercept
2046 if (wpos.Z > pos.Z) pos = wpos;
2047 return pos;
2009 } 2048 }
2010 2049
2011 2050
@@ -2138,13 +2177,22 @@ namespace OpenSim.Region.Framework.Scenes
2138 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 2177 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
2139 { 2178 {
2140 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); 2179 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates);
2141 } 2180 }
2142 2181
2143 /// <summary> 2182 /// <summary>
2144 /// Delete every object from the scene. This does not include attachments worn by avatars. 2183 /// Delete every object from the scene. This does not include attachments worn by avatars.
2145 /// </summary> 2184 /// </summary>
2146 public void DeleteAllSceneObjects() 2185 public void DeleteAllSceneObjects()
2147 { 2186 {
2187 DeleteAllSceneObjects(false);
2188 }
2189
2190 /// <summary>
2191 /// Delete every object from the scene. This does not include attachments worn by avatars.
2192 /// </summary>
2193 public void DeleteAllSceneObjects(bool exceptNoCopy)
2194 {
2195 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2148 lock (Entities) 2196 lock (Entities)
2149 { 2197 {
2150 ICollection<EntityBase> entities = new List<EntityBase>(Entities); 2198 ICollection<EntityBase> entities = new List<EntityBase>(Entities);
@@ -2154,11 +2202,24 @@ namespace OpenSim.Region.Framework.Scenes
2154 if (e is SceneObjectGroup) 2202 if (e is SceneObjectGroup)
2155 { 2203 {
2156 SceneObjectGroup sog = (SceneObjectGroup)e; 2204 SceneObjectGroup sog = (SceneObjectGroup)e;
2157 if (!sog.IsAttachment) 2205 if (sog != null && !sog.IsAttachment)
2158 DeleteSceneObject((SceneObjectGroup)e, false); 2206 {
2207 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2208 {
2209 DeleteSceneObject((SceneObjectGroup)e, false);
2210 }
2211 else
2212 {
2213 toReturn.Add((SceneObjectGroup)e);
2214 }
2215 }
2159 } 2216 }
2160 } 2217 }
2161 } 2218 }
2219 if (toReturn.Count > 0)
2220 {
2221 returnObjects(toReturn.ToArray(), UUID.Zero);
2222 }
2162 } 2223 }
2163 2224
2164 /// <summary> 2225 /// <summary>
@@ -3197,6 +3258,16 @@ namespace OpenSim.Region.Framework.Scenes
3197 /// <param name="flags"></param> 3258 /// <param name="flags"></param>
3198 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3259 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3199 { 3260 {
3261 //Add half the avatar's height so that the user doesn't fall through prims
3262 ScenePresence presence;
3263 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3264 {
3265 if (presence.Appearance != null)
3266 {
3267 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3268 }
3269 }
3270
3200 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3271 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3201 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3272 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3202 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3273 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3584,6 +3655,8 @@ namespace OpenSim.Region.Framework.Scenes
3584 } 3655 }
3585 } 3656 }
3586 // Honor parcel landing type and position. 3657 // Honor parcel landing type and position.
3658 /*
3659 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3587 if (land != null) 3660 if (land != null)
3588 { 3661 {
3589 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3662 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3591,6 +3664,7 @@ namespace OpenSim.Region.Framework.Scenes
3591 agent.startpos = land.LandData.UserLocation; 3664 agent.startpos = land.LandData.UserLocation;
3592 } 3665 }
3593 } 3666 }
3667 */// This is now handled properly in ScenePresence.MakeRootAgent
3594 } 3668 }
3595 3669
3596 return true; 3670 return true;
@@ -3953,12 +4027,22 @@ namespace OpenSim.Region.Framework.Scenes
3953 return false; 4027 return false;
3954 } 4028 }
3955 4029
4030 public bool IncomingCloseAgent(UUID agentID)
4031 {
4032 return IncomingCloseAgent(agentID, false);
4033 }
4034
4035 public bool IncomingCloseChildAgent(UUID agentID)
4036 {
4037 return IncomingCloseAgent(agentID, true);
4038 }
4039
3956 /// <summary> 4040 /// <summary>
3957 /// Tell a single agent to disconnect from the region. 4041 /// Tell a single agent to disconnect from the region.
3958 /// </summary> 4042 /// </summary>
3959 /// <param name="regionHandle"></param>
3960 /// <param name="agentID"></param> 4043 /// <param name="agentID"></param>
3961 public bool IncomingCloseAgent(UUID agentID) 4044 /// <param name="childOnly"></param>
4045 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3962 { 4046 {
3963 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4047 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3964 4048
@@ -3970,7 +4054,7 @@ namespace OpenSim.Region.Framework.Scenes
3970 { 4054 {
3971 m_sceneGraph.removeUserCount(false); 4055 m_sceneGraph.removeUserCount(false);
3972 } 4056 }
3973 else 4057 else if (!childOnly)
3974 { 4058 {
3975 m_sceneGraph.removeUserCount(true); 4059 m_sceneGraph.removeUserCount(true);
3976 } 4060 }
@@ -3986,9 +4070,12 @@ namespace OpenSim.Region.Framework.Scenes
3986 } 4070 }
3987 else 4071 else
3988 presence.ControllingClient.SendShutdownConnectionNotice(); 4072 presence.ControllingClient.SendShutdownConnectionNotice();
4073 presence.ControllingClient.Close(false);
4074 }
4075 else if (!childOnly)
4076 {
4077 presence.ControllingClient.Close(true);
3989 } 4078 }
3990
3991 presence.ControllingClient.Close();
3992 return true; 4079 return true;
3993 } 4080 }
3994 4081
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index c675322..a9ecde8 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -274,7 +274,7 @@ namespace OpenSim.Region.Framework.Scenes
274 uint x = 0, y = 0; 274 uint x = 0, y = 0;
275 Utils.LongToUInts(regionHandle, out x, out y); 275 Utils.LongToUInts(regionHandle, out x, out y);
276 GridRegion destination = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y); 276 GridRegion destination = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
277 m_scene.SimulationService.CloseAgent(destination, agentID); 277 m_scene.SimulationService.CloseChildAgent(destination, agentID);
278 } 278 }
279 279
280 private void SendCloseChildAgentCompleted(IAsyncResult iar) 280 private void SendCloseChildAgentCompleted(IAsyncResult iar)
@@ -293,7 +293,7 @@ namespace OpenSim.Region.Framework.Scenes
293 d); 293 d);
294 } 294 }
295 } 295 }
296 296
297 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 297 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
298 { 298 {
299 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 299 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 240c688..81ef54f 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -43,6 +43,12 @@ namespace OpenSim.Region.Framework.Scenes
43 43
44 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone); 44 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone);
45 45
46 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
49
50 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
51
46 public delegate void ObjectCreateDelegate(EntityBase obj); 52 public delegate void ObjectCreateDelegate(EntityBase obj);
47 53
48 public delegate void ObjectDeleteDelegate(EntityBase obj); 54 public delegate void ObjectDeleteDelegate(EntityBase obj);
@@ -61,6 +67,9 @@ namespace OpenSim.Region.Framework.Scenes
61 private PhysicsCrash handlerPhysicsCrash = null; 67 private PhysicsCrash handlerPhysicsCrash = null;
62 68
63 public event ObjectDuplicateDelegate OnObjectDuplicate; 69 public event ObjectDuplicateDelegate OnObjectDuplicate;
70 public event AttachToBackupDelegate OnAttachToBackup;
71 public event DetachFromBackupDelegate OnDetachFromBackup;
72 public event ChangedBackupDelegate OnChangeBackup;
64 public event ObjectCreateDelegate OnObjectCreate; 73 public event ObjectCreateDelegate OnObjectCreate;
65 public event ObjectDeleteDelegate OnObjectRemove; 74 public event ObjectDeleteDelegate OnObjectRemove;
66 75
@@ -68,7 +77,7 @@ namespace OpenSim.Region.Framework.Scenes
68 77
69 #region Fields 78 #region Fields
70 79
71 protected object m_presenceLock = new object(); 80 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 81 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 82 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
74 83
@@ -133,13 +142,18 @@ namespace OpenSim.Region.Framework.Scenes
133 142
134 protected internal void Close() 143 protected internal void Close()
135 { 144 {
136 lock (m_presenceLock) 145 m_scenePresencesLock.EnterWriteLock();
146 try
137 { 147 {
138 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 148 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
139 List<ScenePresence> newlist = new List<ScenePresence>(); 149 List<ScenePresence> newlist = new List<ScenePresence>();
140 m_scenePresenceMap = newmap; 150 m_scenePresenceMap = newmap;
141 m_scenePresenceArray = newlist; 151 m_scenePresenceArray = newlist;
142 } 152 }
153 finally
154 {
155 m_scenePresencesLock.ExitWriteLock();
156 }
143 157
144 lock (m_dictionary_lock) 158 lock (m_dictionary_lock)
145 { 159 {
@@ -269,6 +283,30 @@ namespace OpenSim.Region.Framework.Scenes
269 protected internal bool AddRestoredSceneObject( 283 protected internal bool AddRestoredSceneObject(
270 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 284 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
271 { 285 {
286 // KF: Check for out-of-region, move inside and make static.
287 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
288 sceneObject.RootPart.GroupPosition.Y,
289 sceneObject.RootPart.GroupPosition.Z);
290 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 ||
291 npos.X > Constants.RegionSize ||
292 npos.Y > Constants.RegionSize))
293 {
294 if (npos.X < 0.0) npos.X = 1.0f;
295 if (npos.Y < 0.0) npos.Y = 1.0f;
296 if (npos.Z < 0.0) npos.Z = 0.0f;
297 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
298 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
299
300 foreach (SceneObjectPart part in sceneObject.Children.Values)
301 {
302 part.GroupPosition = npos;
303 }
304 sceneObject.RootPart.Velocity = Vector3.Zero;
305 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
306 sceneObject.RootPart.Acceleration = Vector3.Zero;
307 sceneObject.RootPart.Velocity = Vector3.Zero;
308 }
309
272 if (!alreadyPersisted) 310 if (!alreadyPersisted)
273 { 311 {
274 sceneObject.ForceInventoryPersistence(); 312 sceneObject.ForceInventoryPersistence();
@@ -359,10 +397,14 @@ namespace OpenSim.Region.Framework.Scenes
359 m_numPrim += sceneObject.Children.Count; 397 m_numPrim += sceneObject.Children.Count;
360 398
361 if (attachToBackup) 399 if (attachToBackup)
400 {
362 sceneObject.AttachToBackup(); 401 sceneObject.AttachToBackup();
402 }
363 403
364 if (OnObjectCreate != null) 404 if (OnObjectCreate != null)
405 {
365 OnObjectCreate(sceneObject); 406 OnObjectCreate(sceneObject);
407 }
366 408
367 lock (m_dictionary_lock) 409 lock (m_dictionary_lock)
368 { 410 {
@@ -429,6 +471,30 @@ namespace OpenSim.Region.Framework.Scenes
429 } 471 }
430 } 472 }
431 473
474 public void FireAttachToBackup(SceneObjectGroup obj)
475 {
476 if (OnAttachToBackup != null)
477 {
478 OnAttachToBackup(obj);
479 }
480 }
481
482 public void FireDetachFromBackup(SceneObjectGroup obj)
483 {
484 if (OnDetachFromBackup != null)
485 {
486 OnDetachFromBackup(obj);
487 }
488 }
489
490 public void FireChangeBackup(SceneObjectGroup obj)
491 {
492 if (OnChangeBackup != null)
493 {
494 OnChangeBackup(obj);
495 }
496 }
497
432 /// <summary> 498 /// <summary>
433 /// Process all pending updates 499 /// Process all pending updates
434 /// </summary> 500 /// </summary>
@@ -565,7 +631,8 @@ namespace OpenSim.Region.Framework.Scenes
565 631
566 Entities[presence.UUID] = presence; 632 Entities[presence.UUID] = presence;
567 633
568 lock (m_presenceLock) 634 m_scenePresencesLock.EnterWriteLock();
635 try
569 { 636 {
570 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 637 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
571 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 638 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -589,6 +656,10 @@ namespace OpenSim.Region.Framework.Scenes
589 m_scenePresenceMap = newmap; 656 m_scenePresenceMap = newmap;
590 m_scenePresenceArray = newlist; 657 m_scenePresenceArray = newlist;
591 } 658 }
659 finally
660 {
661 m_scenePresencesLock.ExitWriteLock();
662 }
592 } 663 }
593 664
594 /// <summary> 665 /// <summary>
@@ -603,7 +674,8 @@ namespace OpenSim.Region.Framework.Scenes
603 agentID); 674 agentID);
604 } 675 }
605 676
606 lock (m_presenceLock) 677 m_scenePresencesLock.EnterWriteLock();
678 try
607 { 679 {
608 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 680 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
609 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 681 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -625,6 +697,10 @@ namespace OpenSim.Region.Framework.Scenes
625 m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 697 m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
626 } 698 }
627 } 699 }
700 finally
701 {
702 m_scenePresencesLock.ExitWriteLock();
703 }
628 } 704 }
629 705
630 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 706 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1502,10 +1578,13 @@ namespace OpenSim.Region.Framework.Scenes
1502 /// <param name="childPrims"></param> 1578 /// <param name="childPrims"></param>
1503 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1579 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1504 { 1580 {
1581 SceneObjectGroup parentGroup = root.ParentGroup;
1582 if (parentGroup == null) return;
1505 Monitor.Enter(m_updateLock); 1583 Monitor.Enter(m_updateLock);
1584
1506 try 1585 try
1507 { 1586 {
1508 SceneObjectGroup parentGroup = root.ParentGroup; 1587 parentGroup.areUpdatesSuspended = true;
1509 1588
1510 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1589 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1511 if (parentGroup != null) 1590 if (parentGroup != null)
@@ -1544,12 +1623,12 @@ namespace OpenSim.Region.Framework.Scenes
1544 // occur on link to invoke this elsewhere (such as object selection) 1623 // occur on link to invoke this elsewhere (such as object selection)
1545 parentGroup.RootPart.CreateSelected = true; 1624 parentGroup.RootPart.CreateSelected = true;
1546 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1625 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1547 parentGroup.HasGroupChanged = true;
1548 parentGroup.ScheduleGroupForFullUpdate();
1549
1550 } 1626 }
1551 finally 1627 finally
1552 { 1628 {
1629 parentGroup.areUpdatesSuspended = false;
1630 parentGroup.HasGroupChanged = true;
1631 parentGroup.ScheduleGroupForFullUpdate();
1553 Monitor.Exit(m_updateLock); 1632 Monitor.Exit(m_updateLock);
1554 } 1633 }
1555 } 1634 }
@@ -1586,11 +1665,22 @@ namespace OpenSim.Region.Framework.Scenes
1586 } 1665 }
1587 } 1666 }
1588 1667
1589 foreach (SceneObjectPart child in childParts) 1668 if (childParts.Count > 0)
1590 { 1669 {
1591 // Unlink all child parts from their groups 1670 try
1592 // 1671 {
1593 child.ParentGroup.DelinkFromGroup(child, true); 1672 childParts[0].ParentGroup.areUpdatesSuspended = true;
1673 foreach (SceneObjectPart child in childParts)
1674 {
1675 // Unlink all child parts from their groups
1676 //
1677 child.ParentGroup.DelinkFromGroup(child, true);
1678 }
1679 }
1680 finally
1681 {
1682 childParts[0].ParentGroup.areUpdatesSuspended = false;
1683 }
1594 } 1684 }
1595 1685
1596 foreach (SceneObjectPart root in rootParts) 1686 foreach (SceneObjectPart root in rootParts)
@@ -1614,10 +1704,21 @@ namespace OpenSim.Region.Framework.Scenes
1614 if (numChildren > 1) 1704 if (numChildren > 1)
1615 sendEventsToRemainder = false; 1705 sendEventsToRemainder = false;
1616 1706
1617 foreach (SceneObjectPart p in newSet) 1707 if (newSet.Count > 0)
1618 { 1708 {
1619 if (p != group.RootPart) 1709 try
1620 group.DelinkFromGroup(p, sendEventsToRemainder); 1710 {
1711 newSet[0].ParentGroup.areUpdatesSuspended = true;
1712 foreach (SceneObjectPart p in newSet)
1713 {
1714 if (p != group.RootPart)
1715 group.DelinkFromGroup(p, sendEventsToRemainder);
1716 }
1717 }
1718 finally
1719 {
1720 newSet[0].ParentGroup.areUpdatesSuspended = false;
1721 }
1621 } 1722 }
1622 1723
1623 // If there is more than one prim remaining, we 1724 // If there is more than one prim remaining, we
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index f7e46af..1149a20 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -46,12 +46,12 @@ namespace OpenSim.Region.Framework.Scenes
46 /// </summary> 46 /// </summary>
47 public void ForceInventoryPersistence() 47 public void ForceInventoryPersistence()
48 { 48 {
49 lock (m_parts) 49 lockPartsForRead(true);
50 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
51 lockPartsForRead(false);
52 foreach (SceneObjectPart part in values)
50 { 53 {
51 foreach (SceneObjectPart part in m_parts.Values) 54 part.Inventory.ForceInventoryPersistence();
52 {
53 part.Inventory.ForceInventoryPersistence();
54 }
55 } 55 }
56 } 56 }
57 57
@@ -74,19 +74,17 @@ namespace OpenSim.Region.Framework.Scenes
74 /// <summary> 74 /// <summary>
75 /// Stop the scripts contained in all the prims in this group 75 /// Stop the scripts contained in all the prims in this group
76 /// </summary> 76 /// </summary>
77 /// <param name="sceneObjectBeingDeleted">
78 /// Should be true if these scripts are being removed because the scene
79 /// object is being deleted. This will prevent spurious updates to the client.
80 /// </param>
81 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 77 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
82 { 78 {
83 lock (m_parts) 79 lockPartsForRead(true);
80 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
81 lockPartsForRead(false);
82
83 foreach (SceneObjectPart part in values)
84 { 84 {
85 foreach (SceneObjectPart part in m_parts.Values) 85 part.Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
86 {
87 part.Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
88 }
89 } 86 }
87
90 } 88 }
91 89
92 /// <summary> 90 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index e23f39f..7081ced 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -104,8 +104,95 @@ namespace OpenSim.Region.Framework.Scenes
104 /// since the group's last persistent backup 104 /// since the group's last persistent backup
105 /// </summary> 105 /// </summary>
106 private bool m_hasGroupChanged = false; 106 private bool m_hasGroupChanged = false;
107 private long timeFirstChanged; 107 private long timeFirstChanged = 0;
108 private long timeLastChanged; 108 private long timeLastChanged = 0;
109 private long m_maxPersistTime = 0;
110 private long m_minPersistTime = 0;
111 private Random m_rand;
112 private bool m_suspendUpdates;
113 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
114 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
115
116 public bool areUpdatesSuspended
117 {
118 get
119 {
120 return m_suspendUpdates;
121 }
122 set
123 {
124 m_suspendUpdates = value;
125 if (!value)
126 {
127 QueueForUpdateCheck();
128 }
129 }
130 }
131
132 public void lockPartsForRead(bool locked)
133 {
134 if (locked)
135 {
136 if (m_partsLock.RecursiveReadCount > 0)
137 {
138 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
139 m_partsLock.ExitReadLock();
140 }
141 if (m_partsLock.RecursiveWriteCount > 0)
142 {
143 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested (write lock exists on this thread). This should not happen and means something needs to be fixed.");
144 m_partsLock.ExitWriteLock();
145 }
146
147 while (!m_partsLock.TryEnterReadLock(60000))
148 {
149 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire READ lock of m_parts in SceneObjectGroup. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
150 if (m_partsLock.IsWriteLockHeld)
151 {
152 m_partsLock = new System.Threading.ReaderWriterLockSlim();
153 }
154 }
155 }
156 else
157 {
158 if (m_partsLock.RecursiveReadCount > 0)
159 {
160 m_partsLock.ExitReadLock();
161 }
162 }
163 }
164 public void lockPartsForWrite(bool locked)
165 {
166 if (locked)
167 {
168 if (m_partsLock.RecursiveReadCount > 0)
169 {
170 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
171 m_partsLock.ExitReadLock();
172 }
173 if (m_partsLock.RecursiveWriteCount > 0)
174 {
175 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
176 m_partsLock.ExitWriteLock();
177 }
178
179 while (!m_partsLock.TryEnterWriteLock(60000))
180 {
181 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
182 if (m_partsLock.IsWriteLockHeld)
183 {
184 m_partsLock = new System.Threading.ReaderWriterLockSlim();
185 }
186 }
187 }
188 else
189 {
190 if (m_partsLock.RecursiveWriteCount > 0)
191 {
192 m_partsLock.ExitWriteLock();
193 }
194 }
195 }
109 196
110 public bool HasGroupChanged 197 public bool HasGroupChanged
111 { 198 {
@@ -113,9 +200,39 @@ namespace OpenSim.Region.Framework.Scenes
113 { 200 {
114 if (value) 201 if (value)
115 { 202 {
203 if (m_isBackedUp)
204 {
205 m_scene.SceneGraph.FireChangeBackup(this);
206 }
116 timeLastChanged = DateTime.Now.Ticks; 207 timeLastChanged = DateTime.Now.Ticks;
117 if (!m_hasGroupChanged) 208 if (!m_hasGroupChanged)
118 timeFirstChanged = DateTime.Now.Ticks; 209 timeFirstChanged = DateTime.Now.Ticks;
210 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
211 {
212 if (m_rand == null)
213 {
214 byte[] val = new byte[16];
215 m_rootPart.UUID.ToBytes(val, 0);
216 m_rand = new Random(BitConverter.ToInt32(val, 0));
217 }
218
219 if (m_scene.GetRootAgentCount() == 0)
220 {
221 //If the region is empty, this change has been made by an automated process
222 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
223
224 float factor = 1.5f + (float)(m_rand.NextDouble());
225 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
226 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
227 }
228 else
229 {
230 //If the region is not empty, we want to obey the minimum and maximum persist times
231 //but add a random factor so we stagger the object persistance a little
232 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
233 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
234 }
235 }
119 } 236 }
120 m_hasGroupChanged = value; 237 m_hasGroupChanged = value;
121 } 238 }
@@ -131,8 +248,19 @@ namespace OpenSim.Region.Framework.Scenes
131 return false; 248 return false;
132 if (m_scene.ShuttingDown) 249 if (m_scene.ShuttingDown)
133 return true; 250 return true;
251
252 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
253 {
254 m_maxPersistTime = m_scene.m_persistAfter;
255 m_minPersistTime = m_scene.m_dontPersistBefore;
256 }
257
134 long currentTime = DateTime.Now.Ticks; 258 long currentTime = DateTime.Now.Ticks;
135 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 259
260 if (timeLastChanged == 0) timeLastChanged = currentTime;
261 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
262
263 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
136 return true; 264 return true;
137 return false; 265 return false;
138 } 266 }
@@ -258,13 +386,16 @@ namespace OpenSim.Region.Framework.Scenes
258 set 386 set
259 { 387 {
260 m_regionHandle = value; 388 m_regionHandle = value;
261 lock (m_parts) 389 lockPartsForRead(true);
262 { 390 {
263 foreach (SceneObjectPart part in m_parts.Values) 391 foreach (SceneObjectPart part in m_parts.Values)
264 { 392 {
393
265 part.RegionHandle = m_regionHandle; 394 part.RegionHandle = m_regionHandle;
395
266 } 396 }
267 } 397 }
398 lockPartsForRead(false);
268 } 399 }
269 } 400 }
270 401
@@ -298,6 +429,9 @@ namespace OpenSim.Region.Framework.Scenes
298 { 429 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 430 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 431 }
432
433 lockPartsForRead(true);
434
301 if (RootPart.GetStatusSandbox()) 435 if (RootPart.GetStatusSandbox())
302 { 436 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 437 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -305,17 +439,18 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 439 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 440 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 441 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
442 lockPartsForRead(false);
308 return; 443 return;
309 } 444 }
310 } 445 }
311 lock (m_parts) 446
447 foreach (SceneObjectPart part in m_parts.Values)
312 { 448 {
313 foreach (SceneObjectPart part in m_parts.Values) 449 part.GroupPosition = val;
314 {
315 part.GroupPosition = val;
316 }
317 } 450 }
318 451
452 lockPartsForRead(false);
453
319 //if (m_rootPart.PhysActor != null) 454 //if (m_rootPart.PhysActor != null)
320 //{ 455 //{
321 //m_rootPart.PhysActor.Position = 456 //m_rootPart.PhysActor.Position =
@@ -457,6 +592,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 592 /// </summary>
458 public SceneObjectGroup() 593 public SceneObjectGroup()
459 { 594 {
595
460 } 596 }
461 597
462 /// <summary> 598 /// <summary>
@@ -473,7 +609,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 609 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 610 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 611 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 612 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 613 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 614 }
479 615
@@ -504,13 +640,16 @@ namespace OpenSim.Region.Framework.Scenes
504 640
505 public void SetFromItemID(UUID AssetId) 641 public void SetFromItemID(UUID AssetId)
506 { 642 {
507 lock (m_parts) 643 lockPartsForRead(true);
508 { 644 {
509 foreach (SceneObjectPart part in m_parts.Values) 645 foreach (SceneObjectPart part in m_parts.Values)
510 { 646 {
647
511 part.FromItemID = AssetId; 648 part.FromItemID = AssetId;
649
512 } 650 }
513 } 651 }
652 lockPartsForRead(false);
514 } 653 }
515 654
516 public UUID GetFromItemID() 655 public UUID GetFromItemID()
@@ -523,6 +662,8 @@ namespace OpenSim.Region.Framework.Scenes
523 /// </summary> 662 /// </summary>
524 public virtual void AttachToBackup() 663 public virtual void AttachToBackup()
525 { 664 {
665 m_scene.SceneGraph.FireAttachToBackup(this);
666
526 if (InSceneBackup) 667 if (InSceneBackup)
527 { 668 {
528 //m_log.DebugFormat( 669 //m_log.DebugFormat(
@@ -579,10 +720,11 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 720 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 721 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 722
582 lock (m_parts) 723 lockPartsForRead(true);
583 { 724 {
584 foreach (SceneObjectPart part in m_parts.Values) 725 foreach (SceneObjectPart part in m_parts.Values)
585 { 726 {
727
586 Vector3 partscale = part.Scale; 728 Vector3 partscale = part.Scale;
587 Vector3 partoffset = part.OffsetPosition; 729 Vector3 partoffset = part.OffsetPosition;
588 730
@@ -593,8 +735,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 735 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; 736 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; 737 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
738
596 } 739 }
597 } 740 }
741 lockPartsForRead(false);
742
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 743 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 744 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 745 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +755,11 @@ namespace OpenSim.Region.Framework.Scenes
610 755
611 EntityIntersection result = new EntityIntersection(); 756 EntityIntersection result = new EntityIntersection();
612 757
613 lock (m_parts) 758 lockPartsForRead(true);
614 { 759 {
615 foreach (SceneObjectPart part in m_parts.Values) 760 foreach (SceneObjectPart part in m_parts.Values)
616 { 761 {
762
617 // Temporary commented to stop compiler warning 763 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 764 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 765 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +787,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 787 result.distance = inter.distance;
642 } 788 }
643 } 789 }
790
644 } 791 }
645 } 792 }
793 lockPartsForRead(false);
646 return result; 794 return result;
647 } 795 }
648 796
@@ -661,10 +809,11 @@ namespace OpenSim.Region.Framework.Scenes
661 minY = 256f; 809 minY = 256f;
662 minZ = 8192f; 810 minZ = 8192f;
663 811
664 lock(m_parts); 812 lockPartsForRead(true);
665 { 813 {
666 foreach (SceneObjectPart part in m_parts.Values) 814 foreach (SceneObjectPart part in m_parts.Values)
667 { 815 {
816
668 Vector3 worldPos = part.GetWorldPosition(); 817 Vector3 worldPos = part.GetWorldPosition();
669 Vector3 offset = worldPos - AbsolutePosition; 818 Vector3 offset = worldPos - AbsolutePosition;
670 Quaternion worldRot; 819 Quaternion worldRot;
@@ -723,6 +872,8 @@ namespace OpenSim.Region.Framework.Scenes
723 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 872 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
724 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 873 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
725 874
875
876
726 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 877 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
727 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 878 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
728 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 879 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -894,6 +1045,7 @@ namespace OpenSim.Region.Framework.Scenes
894 minZ = backBottomLeft.Z; 1045 minZ = backBottomLeft.Z;
895 } 1046 }
896 } 1047 }
1048 lockPartsForRead(false);
897 } 1049 }
898 1050
899 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 1051 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
@@ -929,21 +1081,29 @@ namespace OpenSim.Region.Framework.Scenes
929 1081
930 public void SaveScriptedState(XmlTextWriter writer) 1082 public void SaveScriptedState(XmlTextWriter writer)
931 { 1083 {
1084 SaveScriptedState(writer, false);
1085 }
1086
1087 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1088 {
932 XmlDocument doc = new XmlDocument(); 1089 XmlDocument doc = new XmlDocument();
933 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1090 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
934 1091
935 // Capture script state while holding the lock 1092 // Capture script state while holding the lock
936 lock (m_parts) 1093 lockPartsForRead(true);
937 { 1094 {
938 foreach (SceneObjectPart part in m_parts.Values) 1095 foreach (SceneObjectPart part in m_parts.Values)
939 { 1096 {
940 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1097
1098 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs);
941 foreach (UUID itemid in pstates.Keys) 1099 foreach (UUID itemid in pstates.Keys)
942 { 1100 {
943 states.Add(itemid, pstates[itemid]); 1101 states.Add(itemid, pstates[itemid]);
944 } 1102 }
1103
945 } 1104 }
946 } 1105 }
1106 lockPartsForRead(false);
947 1107
948 if (states.Count > 0) 1108 if (states.Count > 0)
949 { 1109 {
@@ -962,6 +1122,47 @@ namespace OpenSim.Region.Framework.Scenes
962 } 1122 }
963 1123
964 /// <summary> 1124 /// <summary>
1125 /// Add the avatar to this linkset (avatar is sat).
1126 /// </summary>
1127 /// <param name="agentID"></param>
1128 public void AddAvatar(UUID agentID)
1129 {
1130 ScenePresence presence;
1131 if (m_scene.TryGetScenePresence(agentID, out presence))
1132 {
1133 if (!m_linkedAvatars.Contains(presence))
1134 {
1135 m_linkedAvatars.Add(presence);
1136 }
1137 }
1138 }
1139
1140 /// <summary>
1141 /// Delete the avatar from this linkset (avatar is unsat).
1142 /// </summary>
1143 /// <param name="agentID"></param>
1144 public void DeleteAvatar(UUID agentID)
1145 {
1146 ScenePresence presence;
1147 if (m_scene.TryGetScenePresence(agentID, out presence))
1148 {
1149 if (m_linkedAvatars.Contains(presence))
1150 {
1151 m_linkedAvatars.Remove(presence);
1152 }
1153 }
1154 }
1155
1156 /// <summary>
1157 /// Returns the list of linked presences (avatars sat on this group)
1158 /// </summary>
1159 /// <param name="agentID"></param>
1160 public List<ScenePresence> GetLinkedAvatars()
1161 {
1162 return m_linkedAvatars;
1163 }
1164
1165 /// <summary>
965 /// Attach this scene object to the given avatar. 1166 /// Attach this scene object to the given avatar.
966 /// </summary> 1167 /// </summary>
967 /// <param name="agentID"></param> 1168 /// <param name="agentID"></param>
@@ -1112,13 +1313,16 @@ namespace OpenSim.Region.Framework.Scenes
1112 1313
1113 public override void UpdateMovement() 1314 public override void UpdateMovement()
1114 { 1315 {
1115 lock (m_parts) 1316 lockPartsForRead(true);
1116 { 1317 {
1117 foreach (SceneObjectPart part in m_parts.Values) 1318 foreach (SceneObjectPart part in m_parts.Values)
1118 { 1319 {
1320
1119 part.UpdateMovement(); 1321 part.UpdateMovement();
1322
1120 } 1323 }
1121 } 1324 }
1325 lockPartsForRead(false);
1122 } 1326 }
1123 1327
1124 public ushort GetTimeDilation() 1328 public ushort GetTimeDilation()
@@ -1162,7 +1366,7 @@ namespace OpenSim.Region.Framework.Scenes
1162 /// <param name="part"></param> 1366 /// <param name="part"></param>
1163 public void AddPart(SceneObjectPart part) 1367 public void AddPart(SceneObjectPart part)
1164 { 1368 {
1165 lock (m_parts) 1369 lockPartsForWrite(true);
1166 { 1370 {
1167 part.SetParent(this); 1371 part.SetParent(this);
1168 m_parts.Add(part.UUID, part); 1372 m_parts.Add(part.UUID, part);
@@ -1172,6 +1376,7 @@ namespace OpenSim.Region.Framework.Scenes
1172 if (part.LinkNum == 2 && RootPart != null) 1376 if (part.LinkNum == 2 && RootPart != null)
1173 RootPart.LinkNum = 1; 1377 RootPart.LinkNum = 1;
1174 } 1378 }
1379 lockPartsForWrite(false);
1175 } 1380 }
1176 1381
1177 /// <summary> 1382 /// <summary>
@@ -1179,28 +1384,33 @@ namespace OpenSim.Region.Framework.Scenes
1179 /// </summary> 1384 /// </summary>
1180 private void UpdateParentIDs() 1385 private void UpdateParentIDs()
1181 { 1386 {
1182 lock (m_parts) 1387 lockPartsForRead(true);
1183 { 1388 {
1184 foreach (SceneObjectPart part in m_parts.Values) 1389 foreach (SceneObjectPart part in m_parts.Values)
1185 { 1390 {
1391
1186 if (part.UUID != m_rootPart.UUID) 1392 if (part.UUID != m_rootPart.UUID)
1187 { 1393 {
1188 part.ParentID = m_rootPart.LocalId; 1394 part.ParentID = m_rootPart.LocalId;
1189 } 1395 }
1396
1190 } 1397 }
1191 } 1398 }
1399 lockPartsForRead(false);
1192 } 1400 }
1193 1401
1194 public void RegenerateFullIDs() 1402 public void RegenerateFullIDs()
1195 { 1403 {
1196 lock (m_parts) 1404 lockPartsForRead(true);
1197 { 1405 {
1198 foreach (SceneObjectPart part in m_parts.Values) 1406 foreach (SceneObjectPart part in m_parts.Values)
1199 { 1407 {
1408
1200 part.UUID = UUID.Random(); 1409 part.UUID = UUID.Random();
1201 1410
1202 } 1411 }
1203 } 1412 }
1413 lockPartsForRead(false);
1204 } 1414 }
1205 1415
1206 // helper provided for parts. 1416 // helper provided for parts.
@@ -1281,27 +1491,32 @@ namespace OpenSim.Region.Framework.Scenes
1281 1491
1282 DetachFromBackup(); 1492 DetachFromBackup();
1283 1493
1284 lock (m_parts) 1494 lockPartsForRead(true);
1495 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1496 lockPartsForRead(false);
1497
1498 foreach (SceneObjectPart part in values)
1285 { 1499 {
1286 foreach (SceneObjectPart part in m_parts.Values)
1287 {
1288// part.Inventory.RemoveScriptInstances(); 1500// part.Inventory.RemoveScriptInstances();
1289 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1501
1502 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1503 {
1504 if (sp.ParentID == LocalId)
1290 { 1505 {
1291 if (avatar.ParentID == LocalId) 1506 sp.StandUp();
1292 { 1507 }
1293 avatar.StandUp();
1294 }
1295 1508
1296 if (!silent) 1509 if (!silent)
1297 { 1510 {
1298 part.UpdateFlag = 0; 1511 part.UpdateFlag = 0;
1299 if (part == m_rootPart) 1512 if (part == m_rootPart)
1300 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1513 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1301 } 1514 }
1302 }); 1515 });
1303 } 1516
1304 } 1517 }
1518
1519
1305 } 1520 }
1306 1521
1307 public void AddScriptLPS(int count) 1522 public void AddScriptLPS(int count)
@@ -1326,17 +1541,20 @@ namespace OpenSim.Region.Framework.Scenes
1326 1541
1327 scriptEvents aggregateScriptEvents=0; 1542 scriptEvents aggregateScriptEvents=0;
1328 1543
1329 lock (m_parts) 1544 lockPartsForRead(true);
1330 { 1545 {
1331 foreach (SceneObjectPart part in m_parts.Values) 1546 foreach (SceneObjectPart part in m_parts.Values)
1332 { 1547 {
1548
1333 if (part == null) 1549 if (part == null)
1334 continue; 1550 continue;
1335 if (part != RootPart) 1551 if (part != RootPart)
1336 part.ObjectFlags = objectflagupdate; 1552 part.ObjectFlags = objectflagupdate;
1337 aggregateScriptEvents |= part.AggregateScriptEvents; 1553 aggregateScriptEvents |= part.AggregateScriptEvents;
1554
1338 } 1555 }
1339 } 1556 }
1557 lockPartsForRead(false);
1340 1558
1341 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1559 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1342 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1560 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1378,42 +1596,52 @@ namespace OpenSim.Region.Framework.Scenes
1378 /// <param name="m_physicalPrim"></param> 1596 /// <param name="m_physicalPrim"></param>
1379 public void ApplyPhysics(bool m_physicalPrim) 1597 public void ApplyPhysics(bool m_physicalPrim)
1380 { 1598 {
1381 lock (m_parts) 1599 lockPartsForRead(true);
1600
1601 if (m_parts.Count > 1)
1382 { 1602 {
1383 if (m_parts.Count > 1) 1603 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1604 lockPartsForRead(false);
1605 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1606 foreach (SceneObjectPart part in values)
1384 { 1607 {
1385 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1608
1386 foreach (SceneObjectPart part in m_parts.Values) 1609 if (part.LocalId != m_rootPart.LocalId)
1387 { 1610 {
1388 if (part.LocalId != m_rootPart.LocalId) 1611 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1389 {
1390 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1391 }
1392 } 1612 }
1393 1613
1394 // Hack to get the physics scene geometries in the right spot
1395 ResetChildPrimPhysicsPositions();
1396 }
1397 else
1398 {
1399 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1400 } 1614 }
1615 // Hack to get the physics scene geometries in the right spot
1616 ResetChildPrimPhysicsPositions();
1617 }
1618 else
1619 {
1620 lockPartsForRead(false);
1621 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1401 } 1622 }
1402 } 1623 }
1403 1624
1404 public void SetOwnerId(UUID userId) 1625 public void SetOwnerId(UUID userId)
1405 { 1626 {
1406 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1627 ForEachPart(delegate(SceneObjectPart part)
1628 {
1629
1630 part.OwnerID = userId;
1631
1632 });
1407 } 1633 }
1408 1634
1409 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1635 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1410 { 1636 {
1411 lock (m_parts) 1637 lockPartsForRead(true);
1638 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1639 lockPartsForRead(false);
1640 foreach (SceneObjectPart part in values)
1412 { 1641 {
1413 foreach (SceneObjectPart part in m_parts.Values) 1642
1414 { 1643 whatToDo(part);
1415 whatToDo(part); 1644
1416 }
1417 } 1645 }
1418 } 1646 }
1419 1647
@@ -1511,15 +1739,17 @@ namespace OpenSim.Region.Framework.Scenes
1511 RootPart.SendFullUpdate( 1739 RootPart.SendFullUpdate(
1512 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1740 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1513 1741
1514 lock (m_parts) 1742 lockPartsForRead(true);
1515 { 1743 {
1516 foreach (SceneObjectPart part in m_parts.Values) 1744 foreach (SceneObjectPart part in m_parts.Values)
1517 { 1745 {
1746
1518 if (part != RootPart) 1747 if (part != RootPart)
1519 part.SendFullUpdate( 1748 part.SendFullUpdate(
1520 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1749 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1521 } 1750 }
1522 } 1751 }
1752 lockPartsForRead(false);
1523 } 1753 }
1524 1754
1525 #region Copying 1755 #region Copying
@@ -1588,10 +1818,11 @@ namespace OpenSim.Region.Framework.Scenes
1588 1818
1589 List<SceneObjectPart> partList; 1819 List<SceneObjectPart> partList;
1590 1820
1591 lock (m_parts) 1821 lockPartsForRead(true);
1592 { 1822
1593 partList = new List<SceneObjectPart>(m_parts.Values); 1823 partList = new List<SceneObjectPart>(m_parts.Values);
1594 } 1824
1825 lockPartsForRead(false);
1595 1826
1596 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1827 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1597 { 1828 {
@@ -1814,13 +2045,40 @@ namespace OpenSim.Region.Framework.Scenes
1814 } 2045 }
1815 } 2046 }
1816 2047
2048 public void rotLookAt(Quaternion target, float strength, float damping)
2049 {
2050 SceneObjectPart rootpart = m_rootPart;
2051 if (rootpart != null)
2052 {
2053 if (IsAttachment)
2054 {
2055 /*
2056 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2057 if (avatar != null)
2058 {
2059 Rotate the Av?
2060 } */
2061 }
2062 else
2063 {
2064 if (rootpart.PhysActor != null)
2065 { // APID must be implemented in your physics system for this to function.
2066 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2067 rootpart.PhysActor.APIDStrength = strength;
2068 rootpart.PhysActor.APIDDamping = damping;
2069 rootpart.PhysActor.APIDActive = true;
2070 }
2071 }
2072 }
2073 }
2074
1817 public void stopLookAt() 2075 public void stopLookAt()
1818 { 2076 {
1819 SceneObjectPart rootpart = m_rootPart; 2077 SceneObjectPart rootpart = m_rootPart;
1820 if (rootpart != null) 2078 if (rootpart != null)
1821 { 2079 {
1822 if (rootpart.PhysActor != null) 2080 if (rootpart.PhysActor != null)
1823 { 2081 { // APID must be implemented in your physics system for this to function.
1824 rootpart.PhysActor.APIDActive = false; 2082 rootpart.PhysActor.APIDActive = false;
1825 } 2083 }
1826 } 2084 }
@@ -1888,10 +2146,11 @@ namespace OpenSim.Region.Framework.Scenes
1888 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2146 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1889 newPart.SetParent(this); 2147 newPart.SetParent(this);
1890 2148
1891 lock (m_parts) 2149 lockPartsForWrite(true);
1892 { 2150 {
1893 m_parts.Add(newPart.UUID, newPart); 2151 m_parts.Add(newPart.UUID, newPart);
1894 } 2152 }
2153 lockPartsForWrite(false);
1895 2154
1896 SetPartAsNonRoot(newPart); 2155 SetPartAsNonRoot(newPart);
1897 2156
@@ -1954,7 +2213,7 @@ namespace OpenSim.Region.Framework.Scenes
1954 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2213 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1955 // return; 2214 // return;
1956 2215
1957 lock (m_parts) 2216 lockPartsForRead(true);
1958 { 2217 {
1959 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2218 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1960 2219
@@ -1974,9 +2233,12 @@ namespace OpenSim.Region.Framework.Scenes
1974 { 2233 {
1975 if (!IsSelected) 2234 if (!IsSelected)
1976 part.UpdateLookAt(); 2235 part.UpdateLookAt();
2236
1977 part.SendScheduledUpdates(); 2237 part.SendScheduledUpdates();
2238
1978 } 2239 }
1979 } 2240 }
2241 lockPartsForRead(false);
1980 } 2242 }
1981 2243
1982 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2244 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1985,27 +2247,29 @@ namespace OpenSim.Region.Framework.Scenes
1985 2247
1986 RootPart.AddFullUpdateToAvatar(presence); 2248 RootPart.AddFullUpdateToAvatar(presence);
1987 2249
1988 lock (m_parts) 2250 lockPartsForRead(true);
1989 { 2251 {
1990 foreach (SceneObjectPart part in m_parts.Values) 2252 foreach (SceneObjectPart part in m_parts.Values)
1991 { 2253 {
2254
1992 if (part != RootPart) 2255 if (part != RootPart)
1993 part.AddFullUpdateToAvatar(presence); 2256 part.AddFullUpdateToAvatar(presence);
2257
1994 } 2258 }
1995 } 2259 }
2260 lockPartsForRead(false);
1996 } 2261 }
1997 2262
1998 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2263 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1999 { 2264 {
2000// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2265 lockPartsForRead(true);
2001 2266
2002 lock (m_parts) 2267 foreach (SceneObjectPart part in m_parts.Values)
2003 { 2268 {
2004 foreach (SceneObjectPart part in m_parts.Values) 2269 part.AddTerseUpdateToAvatar(presence);
2005 {
2006 part.AddTerseUpdateToAvatar(presence);
2007 }
2008 } 2270 }
2271
2272 lockPartsForRead(false);
2009 } 2273 }
2010 2274
2011 /// <summary> 2275 /// <summary>
@@ -2013,20 +2277,23 @@ namespace OpenSim.Region.Framework.Scenes
2013 /// </summary> 2277 /// </summary>
2014 public void ScheduleGroupForFullUpdate() 2278 public void ScheduleGroupForFullUpdate()
2015 { 2279 {
2016 if (IsAttachment) 2280 //if (IsAttachment)
2017 m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); 2281 // m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
2018 2282
2019 checkAtTargets(); 2283 checkAtTargets();
2020 RootPart.ScheduleFullUpdate(); 2284 RootPart.ScheduleFullUpdate();
2021 2285
2022 lock (m_parts) 2286 lockPartsForRead(true);
2023 { 2287 {
2024 foreach (SceneObjectPart part in m_parts.Values) 2288 foreach (SceneObjectPart part in m_parts.Values)
2025 { 2289 {
2290
2026 if (part != RootPart) 2291 if (part != RootPart)
2027 part.ScheduleFullUpdate(); 2292 part.ScheduleFullUpdate();
2293
2028 } 2294 }
2029 } 2295 }
2296 lockPartsForRead(false);
2030 } 2297 }
2031 2298
2032 /// <summary> 2299 /// <summary>
@@ -2034,37 +2301,38 @@ namespace OpenSim.Region.Framework.Scenes
2034 /// </summary> 2301 /// </summary>
2035 public void ScheduleGroupForTerseUpdate() 2302 public void ScheduleGroupForTerseUpdate()
2036 { 2303 {
2037// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2304 lockPartsForRead(true);
2038 2305 foreach (SceneObjectPart part in m_parts.Values)
2039 lock (m_parts)
2040 { 2306 {
2041 foreach (SceneObjectPart part in m_parts.Values) 2307 part.ScheduleTerseUpdate();
2042 {
2043 part.ScheduleTerseUpdate();
2044 }
2045 } 2308 }
2309
2310 lockPartsForRead(false);
2046 } 2311 }
2047 2312
2048 /// <summary> 2313 /// <summary>
2049 /// Immediately send a full update for this scene object. 2314 /// Immediately send a full update for this scene object.
2050 /// </summary> 2315 /// </summary>
2051 public void SendGroupFullUpdate() 2316 public void SendGroupFullUpdate()
2052 { 2317 {
2053 if (IsDeleted) 2318 if (IsDeleted)
2054 return; 2319 return;
2055 2320
2056// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2321// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2057 2322
2058 RootPart.SendFullUpdateToAllClients(); 2323 RootPart.SendFullUpdateToAllClients();
2059 2324
2060 lock (m_parts) 2325 lockPartsForRead(true);
2061 { 2326 {
2062 foreach (SceneObjectPart part in m_parts.Values) 2327 foreach (SceneObjectPart part in m_parts.Values)
2063 { 2328 {
2329
2064 if (part != RootPart) 2330 if (part != RootPart)
2065 part.SendFullUpdateToAllClients(); 2331 part.SendFullUpdateToAllClients();
2332
2066 } 2333 }
2067 } 2334 }
2335 lockPartsForRead(false);
2068 } 2336 }
2069 2337
2070 /// <summary> 2338 /// <summary>
@@ -2096,14 +2364,15 @@ namespace OpenSim.Region.Framework.Scenes
2096 { 2364 {
2097 if (IsDeleted) 2365 if (IsDeleted)
2098 return; 2366 return;
2099 2367
2100 lock (m_parts) 2368 lockPartsForRead(true);
2101 { 2369 {
2102 foreach (SceneObjectPart part in m_parts.Values) 2370 foreach (SceneObjectPart part in m_parts.Values)
2103 { 2371 {
2104 part.SendTerseUpdateToAllClients(); 2372 part.SendTerseUpdateToAllClients();
2105 } 2373 }
2106 } 2374 }
2375 lockPartsForRead(false);
2107 } 2376 }
2108 2377
2109 #endregion 2378 #endregion
@@ -2117,16 +2386,18 @@ namespace OpenSim.Region.Framework.Scenes
2117 /// <returns>null if no child part with that linknum or child part</returns> 2386 /// <returns>null if no child part with that linknum or child part</returns>
2118 public SceneObjectPart GetLinkNumPart(int linknum) 2387 public SceneObjectPart GetLinkNumPart(int linknum)
2119 { 2388 {
2120 lock (m_parts) 2389 lockPartsForRead(true);
2121 { 2390 {
2122 foreach (SceneObjectPart part in m_parts.Values) 2391 foreach (SceneObjectPart part in m_parts.Values)
2123 { 2392 {
2124 if (part.LinkNum == linknum) 2393 if (part.LinkNum == linknum)
2125 { 2394 {
2395 lockPartsForRead(false);
2126 return part; 2396 return part;
2127 } 2397 }
2128 } 2398 }
2129 } 2399 }
2400 lockPartsForRead(false);
2130 2401
2131 return null; 2402 return null;
2132 } 2403 }
@@ -2154,17 +2425,19 @@ namespace OpenSim.Region.Framework.Scenes
2154 public SceneObjectPart GetChildPart(uint localID) 2425 public SceneObjectPart GetChildPart(uint localID)
2155 { 2426 {
2156 //m_log.DebugFormat("Entered looking for {0}", localID); 2427 //m_log.DebugFormat("Entered looking for {0}", localID);
2157 lock (m_parts) 2428 lockPartsForRead(true);
2158 { 2429 {
2159 foreach (SceneObjectPart part in m_parts.Values) 2430 foreach (SceneObjectPart part in m_parts.Values)
2160 { 2431 {
2161 //m_log.DebugFormat("Found {0}", part.LocalId); 2432 //m_log.DebugFormat("Found {0}", part.LocalId);
2162 if (part.LocalId == localID) 2433 if (part.LocalId == localID)
2163 { 2434 {
2435 lockPartsForRead(false);
2164 return part; 2436 return part;
2165 } 2437 }
2166 } 2438 }
2167 } 2439 }
2440 lockPartsForRead(false);
2168 2441
2169 return null; 2442 return null;
2170 } 2443 }
@@ -2194,17 +2467,19 @@ namespace OpenSim.Region.Framework.Scenes
2194 public bool HasChildPrim(uint localID) 2467 public bool HasChildPrim(uint localID)
2195 { 2468 {
2196 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2469 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2197 lock (m_parts) 2470 lockPartsForRead(true);
2198 { 2471 {
2199 foreach (SceneObjectPart part in m_parts.Values) 2472 foreach (SceneObjectPart part in m_parts.Values)
2200 { 2473 {
2201 //m_log.DebugFormat("Found {0}", part.LocalId); 2474 //m_log.DebugFormat("Found {0}", part.LocalId);
2202 if (part.LocalId == localID) 2475 if (part.LocalId == localID)
2203 { 2476 {
2477 lockPartsForRead(false);
2204 return true; 2478 return true;
2205 } 2479 }
2206 } 2480 }
2207 } 2481 }
2482 lockPartsForRead(false);
2208 2483
2209 return false; 2484 return false;
2210 } 2485 }
@@ -2254,53 +2529,57 @@ namespace OpenSim.Region.Framework.Scenes
2254 if (m_rootPart.LinkNum == 0) 2529 if (m_rootPart.LinkNum == 0)
2255 m_rootPart.LinkNum = 1; 2530 m_rootPart.LinkNum = 1;
2256 2531
2257 lock (m_parts) 2532 lockPartsForWrite(true);
2258 { 2533
2259 m_parts.Add(linkPart.UUID, linkPart); 2534 m_parts.Add(linkPart.UUID, linkPart);
2535
2536 lockPartsForWrite(false);
2260 2537
2261 // Insert in terms of link numbers, the new links 2538 // Insert in terms of link numbers, the new links
2262 // before the current ones (with the exception of 2539 // before the current ones (with the exception of
2263 // the root prim. Shuffle the old ones up 2540 // the root prim. Shuffle the old ones up
2264 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2541 lockPartsForRead(true);
2542 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2543 {
2544 if (kvp.Value.LinkNum != 1)
2265 { 2545 {
2266 if (kvp.Value.LinkNum != 1) 2546 // Don't update root prim link number
2267 { 2547 kvp.Value.LinkNum += objectGroup.PrimCount;
2268 // Don't update root prim link number
2269 kvp.Value.LinkNum += objectGroup.PrimCount;
2270 }
2271 } 2548 }
2549 }
2550 lockPartsForRead(false);
2272 2551
2273 linkPart.LinkNum = 2; 2552 linkPart.LinkNum = 2;
2274 2553
2275 linkPart.SetParent(this); 2554 linkPart.SetParent(this);
2276 linkPart.CreateSelected = true; 2555 linkPart.CreateSelected = true;
2277 2556
2278 //if (linkPart.PhysActor != null) 2557 //if (linkPart.PhysActor != null)
2279 //{ 2558 //{
2280 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2559 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2281 2560
2282 //linkPart.PhysActor = null; 2561 //linkPart.PhysActor = null;
2283 //} 2562 //}
2284 2563
2285 //TODO: rest of parts 2564 //TODO: rest of parts
2286 int linkNum = 3; 2565 int linkNum = 3;
2287 foreach (SceneObjectPart part in objectGroup.Children.Values) 2566 foreach (SceneObjectPart part in objectGroup.Children.Values)
2567 {
2568 if (part.UUID != objectGroup.m_rootPart.UUID)
2288 { 2569 {
2289 if (part.UUID != objectGroup.m_rootPart.UUID) 2570 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2290 {
2291 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2292 }
2293 part.ClearUndoState();
2294 } 2571 }
2572 part.ClearUndoState();
2295 } 2573 }
2296 2574
2297 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2575 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2298 objectGroup.m_isDeleted = true; 2576 objectGroup.m_isDeleted = true;
2577
2578 objectGroup.lockPartsForWrite(true);
2299 2579
2300 lock (objectGroup.m_parts) 2580 objectGroup.m_parts.Clear();
2301 { 2581
2302 objectGroup.m_parts.Clear(); 2582 objectGroup.lockPartsForWrite(false);
2303 }
2304 2583
2305 // Can't do this yet since backup still makes use of the root part without any synchronization 2584 // Can't do this yet since backup still makes use of the root part without any synchronization
2306// objectGroup.m_rootPart = null; 2585// objectGroup.m_rootPart = null;
@@ -2370,11 +2649,12 @@ namespace OpenSim.Region.Framework.Scenes
2370 Quaternion worldRot = linkPart.GetWorldRotation(); 2649 Quaternion worldRot = linkPart.GetWorldRotation();
2371 2650
2372 // Remove the part from this object 2651 // Remove the part from this object
2373 lock (m_parts) 2652 lockPartsForWrite(true);
2374 { 2653 {
2375 m_parts.Remove(linkPart.UUID); 2654 m_parts.Remove(linkPart.UUID);
2376 } 2655 }
2377 2656 lockPartsForWrite(false);
2657 lockPartsForRead(true);
2378 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2658 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2379 RootPart.LinkNum = 0; 2659 RootPart.LinkNum = 0;
2380 else 2660 else
@@ -2385,6 +2665,7 @@ namespace OpenSim.Region.Framework.Scenes
2385 p.LinkNum--; 2665 p.LinkNum--;
2386 } 2666 }
2387 } 2667 }
2668 lockPartsForRead(false);
2388 2669
2389 linkPart.ParentID = 0; 2670 linkPart.ParentID = 0;
2390 linkPart.LinkNum = 0; 2671 linkPart.LinkNum = 0;
@@ -2428,6 +2709,8 @@ namespace OpenSim.Region.Framework.Scenes
2428 /// <param name="objectGroup"></param> 2709 /// <param name="objectGroup"></param>
2429 public virtual void DetachFromBackup() 2710 public virtual void DetachFromBackup()
2430 { 2711 {
2712 m_scene.SceneGraph.FireDetachFromBackup(this);
2713
2431 if (m_isBackedUp) 2714 if (m_isBackedUp)
2432 m_scene.EventManager.OnBackup -= ProcessBackup; 2715 m_scene.EventManager.OnBackup -= ProcessBackup;
2433 2716
@@ -2706,9 +2989,12 @@ namespace OpenSim.Region.Framework.Scenes
2706 2989
2707 if (selectionPart != null) 2990 if (selectionPart != null)
2708 { 2991 {
2709 lock (m_parts) 2992 lockPartsForRead(true);
2993 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2994 lockPartsForRead(false);
2995 foreach (SceneObjectPart part in parts)
2710 { 2996 {
2711 foreach (SceneObjectPart part in m_parts.Values) 2997 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2712 { 2998 {
2713 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2999 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2714 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 3000 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2718,12 +3004,13 @@ namespace OpenSim.Region.Framework.Scenes
2718 break; 3004 break;
2719 } 3005 }
2720 } 3006 }
3007 }
2721 3008
2722 foreach (SceneObjectPart part in m_parts.Values) 3009 foreach (SceneObjectPart part in parts)
2723 { 3010 {
2724 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3011 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2725 }
2726 } 3012 }
3013
2727 } 3014 }
2728 } 3015 }
2729 3016
@@ -2736,6 +3023,17 @@ namespace OpenSim.Region.Framework.Scenes
2736 } 3023 }
2737 } 3024 }
2738 3025
3026
3027
3028 /// <summary>
3029 /// Gets the number of parts
3030 /// </summary>
3031 /// <returns></returns>
3032 public int GetPartCount()
3033 {
3034 return Children.Count;
3035 }
3036
2739 /// <summary> 3037 /// <summary>
2740 /// Get the parts of this scene object 3038 /// Get the parts of this scene object
2741 /// </summary> 3039 /// </summary>
@@ -2809,11 +3107,9 @@ namespace OpenSim.Region.Framework.Scenes
2809 scale.Y = m_scene.m_maxNonphys; 3107 scale.Y = m_scene.m_maxNonphys;
2810 if (scale.Z > m_scene.m_maxNonphys) 3108 if (scale.Z > m_scene.m_maxNonphys)
2811 scale.Z = m_scene.m_maxNonphys; 3109 scale.Z = m_scene.m_maxNonphys;
2812
2813 SceneObjectPart part = GetChildPart(localID); 3110 SceneObjectPart part = GetChildPart(localID);
2814 if (part != null) 3111 if (part != null)
2815 { 3112 {
2816 part.Resize(scale);
2817 if (part.PhysActor != null) 3113 if (part.PhysActor != null)
2818 { 3114 {
2819 if (part.PhysActor.IsPhysical) 3115 if (part.PhysActor.IsPhysical)
@@ -2828,7 +3124,7 @@ namespace OpenSim.Region.Framework.Scenes
2828 part.PhysActor.Size = scale; 3124 part.PhysActor.Size = scale;
2829 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3125 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2830 } 3126 }
2831 //if (part.UUID != m_rootPart.UUID) 3127 part.Resize(scale);
2832 3128
2833 HasGroupChanged = true; 3129 HasGroupChanged = true;
2834 ScheduleGroupForFullUpdate(); 3130 ScheduleGroupForFullUpdate();
@@ -2870,73 +3166,71 @@ namespace OpenSim.Region.Framework.Scenes
2870 float y = (scale.Y / part.Scale.Y); 3166 float y = (scale.Y / part.Scale.Y);
2871 float z = (scale.Z / part.Scale.Z); 3167 float z = (scale.Z / part.Scale.Z);
2872 3168
2873 lock (m_parts) 3169 lockPartsForRead(true);
3170 if (x > 1.0f || y > 1.0f || z > 1.0f)
2874 { 3171 {
2875 if (x > 1.0f || y > 1.0f || z > 1.0f) 3172 foreach (SceneObjectPart obPart in m_parts.Values)
2876 { 3173 {
2877 foreach (SceneObjectPart obPart in m_parts.Values) 3174 if (obPart.UUID != m_rootPart.UUID)
2878 { 3175 {
2879 if (obPart.UUID != m_rootPart.UUID) 3176 Vector3 oldSize = new Vector3(obPart.Scale);
2880 { 3177 obPart.IgnoreUndoUpdate = true;
2881 obPart.IgnoreUndoUpdate = true;
2882 Vector3 oldSize = new Vector3(obPart.Scale);
2883 3178
2884 float f = 1.0f; 3179 float f = 1.0f;
2885 float a = 1.0f; 3180 float a = 1.0f;
2886 3181
2887 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3182 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3183 {
3184 if (oldSize.X*x > m_scene.m_maxPhys)
2888 { 3185 {
2889 if (oldSize.X*x > m_scene.m_maxPhys) 3186 f = m_scene.m_maxPhys / oldSize.X;
2890 { 3187 a = f / x;
2891 f = m_scene.m_maxPhys / oldSize.X; 3188 x *= a;
2892 a = f / x; 3189 y *= a;
2893 x *= a; 3190 z *= a;
2894 y *= a;
2895 z *= a;
2896 }
2897 if (oldSize.Y*y > m_scene.m_maxPhys)
2898 {
2899 f = m_scene.m_maxPhys / oldSize.Y;
2900 a = f / y;
2901 x *= a;
2902 y *= a;
2903 z *= a;
2904 }
2905 if (oldSize.Z*z > m_scene.m_maxPhys)
2906 {
2907 f = m_scene.m_maxPhys / oldSize.Z;
2908 a = f / z;
2909 x *= a;
2910 y *= a;
2911 z *= a;
2912 }
2913 } 3191 }
2914 else 3192 if (oldSize.Y*y > m_scene.m_maxPhys)
2915 { 3193 {
2916 if (oldSize.X*x > m_scene.m_maxNonphys) 3194 f = m_scene.m_maxPhys / oldSize.Y;
2917 { 3195 a = f / y;
2918 f = m_scene.m_maxNonphys / oldSize.X; 3196 x *= a;
2919 a = f / x; 3197 y *= a;
2920 x *= a; 3198 z *= a;
2921 y *= a; 3199 }
2922 z *= a; 3200 if (oldSize.Z*z > m_scene.m_maxPhys)
2923 } 3201 {
2924 if (oldSize.Y*y > m_scene.m_maxNonphys) 3202 f = m_scene.m_maxPhys / oldSize.Z;
2925 { 3203 a = f / z;
2926 f = m_scene.m_maxNonphys / oldSize.Y; 3204 x *= a;
2927 a = f / y; 3205 y *= a;
2928 x *= a; 3206 z *= a;
2929 y *= a; 3207 }
2930 z *= a; 3208 }
2931 } 3209 else
2932 if (oldSize.Z*z > m_scene.m_maxNonphys) 3210 {
2933 { 3211 if (oldSize.X*x > m_scene.m_maxNonphys)
2934 f = m_scene.m_maxNonphys / oldSize.Z; 3212 {
2935 a = f / z; 3213 f = m_scene.m_maxNonphys / oldSize.X;
2936 x *= a; 3214 a = f / x;
2937 y *= a; 3215 x *= a;
2938 z *= a; 3216 y *= a;
2939 } 3217 z *= a;
3218 }
3219 if (oldSize.Y*y > m_scene.m_maxNonphys)
3220 {
3221 f = m_scene.m_maxNonphys / oldSize.Y;
3222 a = f / y;
3223 x *= a;
3224 y *= a;
3225 z *= a;
3226 }
3227 if (oldSize.Z*z > m_scene.m_maxNonphys)
3228 {
3229 f = m_scene.m_maxNonphys / oldSize.Z;
3230 a = f / z;
3231 x *= a;
3232 y *= a;
3233 z *= a;
2940 } 3234 }
2941 obPart.IgnoreUndoUpdate = false; 3235 obPart.IgnoreUndoUpdate = false;
2942 obPart.StoreUndoState(); 3236 obPart.StoreUndoState();
@@ -2944,6 +3238,7 @@ namespace OpenSim.Region.Framework.Scenes
2944 } 3238 }
2945 } 3239 }
2946 } 3240 }
3241 lockPartsForRead(false);
2947 3242
2948 Vector3 prevScale = part.Scale; 3243 Vector3 prevScale = part.Scale;
2949 prevScale.X *= x; 3244 prevScale.X *= x;
@@ -2951,7 +3246,7 @@ namespace OpenSim.Region.Framework.Scenes
2951 prevScale.Z *= z; 3246 prevScale.Z *= z;
2952 part.Resize(prevScale); 3247 part.Resize(prevScale);
2953 3248
2954 lock (m_parts) 3249 lockPartsForRead(true);
2955 { 3250 {
2956 foreach (SceneObjectPart obPart in m_parts.Values) 3251 foreach (SceneObjectPart obPart in m_parts.Values)
2957 { 3252 {
@@ -2973,6 +3268,7 @@ namespace OpenSim.Region.Framework.Scenes
2973 obPart.StoreUndoState(); 3268 obPart.StoreUndoState();
2974 } 3269 }
2975 } 3270 }
3271 lockPartsForRead(false);
2976 3272
2977 if (part.PhysActor != null) 3273 if (part.PhysActor != null)
2978 { 3274 {
@@ -3075,7 +3371,7 @@ namespace OpenSim.Region.Framework.Scenes
3075 axDiff *= Quaternion.Inverse(partRotation); 3371 axDiff *= Quaternion.Inverse(partRotation);
3076 diff = axDiff; 3372 diff = axDiff;
3077 3373
3078 lock (m_parts) 3374 lockPartsForRead(true);
3079 { 3375 {
3080 foreach (SceneObjectPart obPart in m_parts.Values) 3376 foreach (SceneObjectPart obPart in m_parts.Values)
3081 { 3377 {
@@ -3085,6 +3381,7 @@ namespace OpenSim.Region.Framework.Scenes
3085 } 3381 }
3086 } 3382 }
3087 } 3383 }
3384 lockPartsForRead(false);
3088 3385
3089 AbsolutePosition = newPos; 3386 AbsolutePosition = newPos;
3090 3387
@@ -3218,25 +3515,25 @@ namespace OpenSim.Region.Framework.Scenes
3218 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3515 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3219 } 3516 }
3220 3517
3221 lock (m_parts) 3518 lockPartsForRead(true);
3519
3520 foreach (SceneObjectPart prim in m_parts.Values)
3222 { 3521 {
3223 foreach (SceneObjectPart prim in m_parts.Values) 3522 if (prim.UUID != m_rootPart.UUID)
3224 { 3523 {
3225 if (prim.UUID != m_rootPart.UUID) 3524 prim.IgnoreUndoUpdate = true;
3226 { 3525 Vector3 axPos = prim.OffsetPosition;
3227 prim.IgnoreUndoUpdate = true; 3526 axPos *= oldParentRot;
3228 Vector3 axPos = prim.OffsetPosition; 3527 axPos *= Quaternion.Inverse(axRot);
3229 axPos *= oldParentRot; 3528 prim.OffsetPosition = axPos;
3230 axPos *= Quaternion.Inverse(axRot); 3529 Quaternion primsRot = prim.RotationOffset;
3231 prim.OffsetPosition = axPos; 3530 Quaternion newRot = primsRot * oldParentRot;
3232 Quaternion primsRot = prim.RotationOffset; 3531 newRot *= Quaternion.Inverse(axRot);
3233 Quaternion newRot = primsRot * oldParentRot; 3532 prim.RotationOffset = newRot;
3234 newRot *= Quaternion.Inverse(axRot); 3533 prim.ScheduleTerseUpdate();
3235 prim.RotationOffset = newRot;
3236 prim.ScheduleTerseUpdate();
3237 }
3238 } 3534 }
3239 } 3535 }
3536
3240 foreach (SceneObjectPart childpart in Children.Values) 3537 foreach (SceneObjectPart childpart in Children.Values)
3241 { 3538 {
3242 if (childpart != m_rootPart) 3539 if (childpart != m_rootPart)
@@ -3245,6 +3542,9 @@ namespace OpenSim.Region.Framework.Scenes
3245 childpart.StoreUndoState(); 3542 childpart.StoreUndoState();
3246 } 3543 }
3247 } 3544 }
3545
3546 lockPartsForRead(false);
3547
3248 m_rootPart.ScheduleTerseUpdate(); 3548 m_rootPart.ScheduleTerseUpdate();
3249 } 3549 }
3250 3550
@@ -3366,7 +3666,7 @@ namespace OpenSim.Region.Framework.Scenes
3366 if (atTargets.Count > 0) 3666 if (atTargets.Count > 0)
3367 { 3667 {
3368 uint[] localids = new uint[0]; 3668 uint[] localids = new uint[0];
3369 lock (m_parts) 3669 lockPartsForRead(true);
3370 { 3670 {
3371 localids = new uint[m_parts.Count]; 3671 localids = new uint[m_parts.Count];
3372 int cntr = 0; 3672 int cntr = 0;
@@ -3376,6 +3676,7 @@ namespace OpenSim.Region.Framework.Scenes
3376 cntr++; 3676 cntr++;
3377 } 3677 }
3378 } 3678 }
3679 lockPartsForRead(false);
3379 3680
3380 for (int ctr = 0; ctr < localids.Length; ctr++) 3681 for (int ctr = 0; ctr < localids.Length; ctr++)
3381 { 3682 {
@@ -3394,7 +3695,7 @@ namespace OpenSim.Region.Framework.Scenes
3394 { 3695 {
3395 //trigger not_at_target 3696 //trigger not_at_target
3396 uint[] localids = new uint[0]; 3697 uint[] localids = new uint[0];
3397 lock (m_parts) 3698 lockPartsForRead(true);
3398 { 3699 {
3399 localids = new uint[m_parts.Count]; 3700 localids = new uint[m_parts.Count];
3400 int cntr = 0; 3701 int cntr = 0;
@@ -3404,7 +3705,8 @@ namespace OpenSim.Region.Framework.Scenes
3404 cntr++; 3705 cntr++;
3405 } 3706 }
3406 } 3707 }
3407 3708 lockPartsForRead(false);
3709
3408 for (int ctr = 0; ctr < localids.Length; ctr++) 3710 for (int ctr = 0; ctr < localids.Length; ctr++)
3409 { 3711 {
3410 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3712 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3445,7 +3747,8 @@ namespace OpenSim.Region.Framework.Scenes
3445 if (atRotTargets.Count > 0) 3747 if (atRotTargets.Count > 0)
3446 { 3748 {
3447 uint[] localids = new uint[0]; 3749 uint[] localids = new uint[0];
3448 lock (m_parts) 3750 lockPartsForRead(true);
3751 try
3449 { 3752 {
3450 localids = new uint[m_parts.Count]; 3753 localids = new uint[m_parts.Count];
3451 int cntr = 0; 3754 int cntr = 0;
@@ -3455,6 +3758,10 @@ namespace OpenSim.Region.Framework.Scenes
3455 cntr++; 3758 cntr++;
3456 } 3759 }
3457 } 3760 }
3761 finally
3762 {
3763 lockPartsForRead(false);
3764 }
3458 3765
3459 for (int ctr = 0; ctr < localids.Length; ctr++) 3766 for (int ctr = 0; ctr < localids.Length; ctr++)
3460 { 3767 {
@@ -3473,7 +3780,8 @@ namespace OpenSim.Region.Framework.Scenes
3473 { 3780 {
3474 //trigger not_at_target 3781 //trigger not_at_target
3475 uint[] localids = new uint[0]; 3782 uint[] localids = new uint[0];
3476 lock (m_parts) 3783 lockPartsForRead(true);
3784 try
3477 { 3785 {
3478 localids = new uint[m_parts.Count]; 3786 localids = new uint[m_parts.Count];
3479 int cntr = 0; 3787 int cntr = 0;
@@ -3483,6 +3791,10 @@ namespace OpenSim.Region.Framework.Scenes
3483 cntr++; 3791 cntr++;
3484 } 3792 }
3485 } 3793 }
3794 finally
3795 {
3796 lockPartsForRead(false);
3797 }
3486 3798
3487 for (int ctr = 0; ctr < localids.Length; ctr++) 3799 for (int ctr = 0; ctr < localids.Length; ctr++)
3488 { 3800 {
@@ -3496,19 +3808,20 @@ namespace OpenSim.Region.Framework.Scenes
3496 public float GetMass() 3808 public float GetMass()
3497 { 3809 {
3498 float retmass = 0f; 3810 float retmass = 0f;
3499 lock (m_parts) 3811 lockPartsForRead(true);
3500 { 3812 {
3501 foreach (SceneObjectPart part in m_parts.Values) 3813 foreach (SceneObjectPart part in m_parts.Values)
3502 { 3814 {
3503 retmass += part.GetMass(); 3815 retmass += part.GetMass();
3504 } 3816 }
3505 } 3817 }
3818 lockPartsForRead(false);
3506 return retmass; 3819 return retmass;
3507 } 3820 }
3508 3821
3509 public void CheckSculptAndLoad() 3822 public void CheckSculptAndLoad()
3510 { 3823 {
3511 lock (m_parts) 3824 lockPartsForRead(true);
3512 { 3825 {
3513 if (!IsDeleted) 3826 if (!IsDeleted)
3514 { 3827 {
@@ -3533,6 +3846,7 @@ namespace OpenSim.Region.Framework.Scenes
3533 } 3846 }
3534 } 3847 }
3535 } 3848 }
3849 lockPartsForRead(false);
3536 } 3850 }
3537 3851
3538 protected void AssetReceived(string id, Object sender, AssetBase asset) 3852 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3553,7 +3867,7 @@ namespace OpenSim.Region.Framework.Scenes
3553 /// <param name="client"></param> 3867 /// <param name="client"></param>
3554 public void SetGroup(UUID GroupID, IClientAPI client) 3868 public void SetGroup(UUID GroupID, IClientAPI client)
3555 { 3869 {
3556 lock (m_parts) 3870 lockPartsForRead(true);
3557 { 3871 {
3558 foreach (SceneObjectPart part in m_parts.Values) 3872 foreach (SceneObjectPart part in m_parts.Values)
3559 { 3873 {
@@ -3563,6 +3877,7 @@ namespace OpenSim.Region.Framework.Scenes
3563 3877
3564 HasGroupChanged = true; 3878 HasGroupChanged = true;
3565 } 3879 }
3880 lockPartsForRead(false);
3566 3881
3567 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3882 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3568 // for the same object with very different properties. The caller must schedule the update. 3883 // for the same object with very different properties. The caller must schedule the update.
@@ -3584,11 +3899,12 @@ namespace OpenSim.Region.Framework.Scenes
3584 3899
3585 public void SetAttachmentPoint(byte point) 3900 public void SetAttachmentPoint(byte point)
3586 { 3901 {
3587 lock (m_parts) 3902 lockPartsForRead(true);
3588 { 3903 {
3589 foreach (SceneObjectPart part in m_parts.Values) 3904 foreach (SceneObjectPart part in m_parts.Values)
3590 part.SetAttachmentPoint(point); 3905 part.SetAttachmentPoint(point);
3591 } 3906 }
3907 lockPartsForRead(false);
3592 } 3908 }
3593 3909
3594 #region ISceneObject 3910 #region ISceneObject
@@ -3622,6 +3938,14 @@ namespace OpenSim.Region.Framework.Scenes
3622 SetFromItemID(uuid); 3938 SetFromItemID(uuid);
3623 } 3939 }
3624 3940
3941 public void ResetOwnerChangeFlag()
3942 {
3943 ForEachPart(delegate(SceneObjectPart part)
3944 {
3945 part.ResetOwnerChangeFlag();
3946 });
3947 }
3948
3625 #endregion 3949 #endregion
3626 } 3950 }
3627} 3951}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 59fd805..09c945b 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -147,7 +147,7 @@ namespace OpenSim.Region.Framework.Scenes
147 147
148 // TODO: This needs to be persisted in next XML version update! 148 // TODO: This needs to be persisted in next XML version update!
149 [XmlIgnore] 149 [XmlIgnore]
150 public readonly int[] PayPrice = {-2,-2,-2,-2,-2}; 150 public int[] PayPrice = {-2,-2,-2,-2,-2};
151 [XmlIgnore] 151 [XmlIgnore]
152 public PhysicsActor PhysActor; 152 public PhysicsActor PhysActor;
153 153
@@ -274,6 +274,7 @@ namespace OpenSim.Region.Framework.Scenes
274 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 274 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
275 private Vector3 m_sitTargetPosition; 275 private Vector3 m_sitTargetPosition;
276 private string m_sitAnimation = "SIT"; 276 private string m_sitAnimation = "SIT";
277 private bool m_occupied; // KF if any av is sitting on this prim
277 private string m_text = String.Empty; 278 private string m_text = String.Empty;
278 private string m_touchName = String.Empty; 279 private string m_touchName = String.Empty;
279 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 280 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
@@ -453,12 +454,16 @@ namespace OpenSim.Region.Framework.Scenes
453 } 454 }
454 455
455 /// <value> 456 /// <value>
456 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 457 /// Get the inventory list
457 /// </value> 458 /// </value>
458 public TaskInventoryDictionary TaskInventory 459 public TaskInventoryDictionary TaskInventory
459 { 460 {
460 get { return m_inventory.Items; } 461 get {
461 set { m_inventory.Items = value; } 462 return m_inventory.Items;
463 }
464 set {
465 m_inventory.Items = value;
466 }
462 } 467 }
463 468
464 public uint ObjectFlags 469 public uint ObjectFlags
@@ -587,14 +592,12 @@ namespace OpenSim.Region.Framework.Scenes
587 set { m_LoopSoundSlavePrims = value; } 592 set { m_LoopSoundSlavePrims = value; }
588 } 593 }
589 594
590 [XmlIgnore]
591 public Byte[] TextureAnimation 595 public Byte[] TextureAnimation
592 { 596 {
593 get { return m_TextureAnimation; } 597 get { return m_TextureAnimation; }
594 set { m_TextureAnimation = value; } 598 set { m_TextureAnimation = value; }
595 } 599 }
596 600
597 [XmlIgnore]
598 public Byte[] ParticleSystem 601 public Byte[] ParticleSystem
599 { 602 {
600 get { return m_particleSystem; } 603 get { return m_particleSystem; }
@@ -648,7 +651,6 @@ namespace OpenSim.Region.Framework.Scenes
648 set 651 set
649 { 652 {
650 m_groupPosition = value; 653 m_groupPosition = value;
651
652 PhysicsActor actor = PhysActor; 654 PhysicsActor actor = PhysActor;
653 if (actor != null) 655 if (actor != null)
654 { 656 {
@@ -709,6 +711,12 @@ namespace OpenSim.Region.Framework.Scenes
709 // Tell the physics engines that this prim changed. 711 // Tell the physics engines that this prim changed.
710 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 712 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
711 } 713 }
714
715 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
716 foreach (ScenePresence av in avs)
717 {
718 av.SendFullUpdateToAllClients();
719 }
712 } 720 }
713 } 721 }
714 } 722 }
@@ -835,7 +843,16 @@ namespace OpenSim.Region.Framework.Scenes
835 /// <summary></summary> 843 /// <summary></summary>
836 public Vector3 Acceleration 844 public Vector3 Acceleration
837 { 845 {
838 get { return m_acceleration; } 846 get
847 {
848 PhysicsActor actor = PhysActor;
849 if (actor != null)
850 {
851 m_acceleration = actor.Acceleration;
852 }
853 return m_acceleration;
854 }
855
839 set { m_acceleration = value; } 856 set { m_acceleration = value; }
840 } 857 }
841 858
@@ -986,7 +1003,8 @@ namespace OpenSim.Region.Framework.Scenes
986 if (IsAttachment) 1003 if (IsAttachment)
987 return GroupPosition; 1004 return GroupPosition;
988 1005
989 return m_offsetPosition + m_groupPosition; } 1006// return m_offsetPosition + m_groupPosition; }
1007 return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored!
990 } 1008 }
991 1009
992 public SceneObjectGroup ParentGroup 1010 public SceneObjectGroup ParentGroup
@@ -1137,6 +1155,13 @@ namespace OpenSim.Region.Framework.Scenes
1137 get { return _flags; } 1155 get { return _flags; }
1138 set { _flags = value; } 1156 set { _flags = value; }
1139 } 1157 }
1158
1159 [XmlIgnore]
1160 public bool IsOccupied // KF If an av is sittingon this prim
1161 {
1162 get { return m_occupied; }
1163 set { m_occupied = value; }
1164 }
1140 1165
1141 [XmlIgnore] 1166 [XmlIgnore]
1142 public UUID SitTargetAvatar 1167 public UUID SitTargetAvatar
@@ -1212,14 +1237,6 @@ namespace OpenSim.Region.Framework.Scenes
1212 } 1237 }
1213 } 1238 }
1214 1239
1215 /// <summary>
1216 /// Clear all pending updates of parts to clients
1217 /// </summary>
1218 private void ClearUpdateSchedule()
1219 {
1220 m_updateFlag = 0;
1221 }
1222
1223 private void SendObjectPropertiesToClient(UUID AgentID) 1240 private void SendObjectPropertiesToClient(UUID AgentID)
1224 { 1241 {
1225 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1242 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1731,7 +1748,7 @@ namespace OpenSim.Region.Framework.Scenes
1731 // which stops client-side interpolation of deactivated joint proxy objects. 1748 // which stops client-side interpolation of deactivated joint proxy objects.
1732 } 1749 }
1733 1750
1734 if (!UsePhysics && !isNew) 1751 if (!UsePhysics)
1735 { 1752 {
1736 // reset velocity to 0 on physics switch-off. Without that, the client thinks the 1753 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
1737 // prim still has velocity and continues to interpolate its position along the old 1754 // prim still has velocity and continues to interpolate its position along the old
@@ -1966,12 +1983,17 @@ namespace OpenSim.Region.Framework.Scenes
1966 public Vector3 GetWorldPosition() 1983 public Vector3 GetWorldPosition()
1967 { 1984 {
1968 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 1985 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1969
1970 Vector3 axPos = OffsetPosition; 1986 Vector3 axPos = OffsetPosition;
1971
1972 axPos *= parentRot; 1987 axPos *= parentRot;
1973 Vector3 translationOffsetPosition = axPos; 1988 Vector3 translationOffsetPosition = axPos;
1974 return GroupPosition + translationOffsetPosition; 1989 if(_parentID == 0)
1990 {
1991 return GroupPosition;
1992 }
1993 else
1994 {
1995 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
1996 }
1975 } 1997 }
1976 1998
1977 /// <summary> 1999 /// <summary>
@@ -1982,7 +2004,7 @@ namespace OpenSim.Region.Framework.Scenes
1982 { 2004 {
1983 Quaternion newRot; 2005 Quaternion newRot;
1984 2006
1985 if (this.LinkNum == 0) 2007 if (this.LinkNum < 2) //KF Single or root prim
1986 { 2008 {
1987 newRot = RotationOffset; 2009 newRot = RotationOffset;
1988 } 2010 }
@@ -2628,17 +2650,18 @@ namespace OpenSim.Region.Framework.Scenes
2628 //Trys to fetch sound id from prim's inventory. 2650 //Trys to fetch sound id from prim's inventory.
2629 //Prim's inventory doesn't support non script items yet 2651 //Prim's inventory doesn't support non script items yet
2630 2652
2631 lock (TaskInventory) 2653 TaskInventory.LockItemsForRead(true);
2654
2655 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2632 { 2656 {
2633 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2657 if (item.Value.Name == sound)
2634 { 2658 {
2635 if (item.Value.Name == sound) 2659 soundID = item.Value.ItemID;
2636 { 2660 break;
2637 soundID = item.Value.ItemID;
2638 break;
2639 }
2640 } 2661 }
2641 } 2662 }
2663
2664 TaskInventory.LockItemsForRead(false);
2642 } 2665 }
2643 2666
2644 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2667 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2707,38 +2730,7 @@ namespace OpenSim.Region.Framework.Scenes
2707 2730
2708 public void RotLookAt(Quaternion target, float strength, float damping) 2731 public void RotLookAt(Quaternion target, float strength, float damping)
2709 { 2732 {
2710 rotLookAt(target, strength, damping); 2733 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2711 }
2712
2713 public void rotLookAt(Quaternion target, float strength, float damping)
2714 {
2715 if (IsAttachment)
2716 {
2717 /*
2718 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2719 if (avatar != null)
2720 {
2721 Rotate the Av?
2722 } */
2723 }
2724 else
2725 {
2726 APIDDamp = damping;
2727 APIDStrength = strength;
2728 APIDTarget = target;
2729 }
2730 }
2731
2732 public void startLookAt(Quaternion rot, float damp, float strength)
2733 {
2734 APIDDamp = damp;
2735 APIDStrength = strength;
2736 APIDTarget = rot;
2737 }
2738
2739 public void stopLookAt()
2740 {
2741 APIDTarget = Quaternion.Identity;
2742 } 2734 }
2743 2735
2744 /// <summary> 2736 /// <summary>
@@ -2750,7 +2742,10 @@ namespace OpenSim.Region.Framework.Scenes
2750 2742
2751 if (m_parentGroup != null) 2743 if (m_parentGroup != null)
2752 { 2744 {
2753 m_parentGroup.QueueForUpdateCheck(); 2745 if (!m_parentGroup.areUpdatesSuspended)
2746 {
2747 m_parentGroup.QueueForUpdateCheck();
2748 }
2754 } 2749 }
2755 2750
2756 int timeNow = Util.UnixTimeSinceEpoch(); 2751 int timeNow = Util.UnixTimeSinceEpoch();
@@ -2967,8 +2962,8 @@ namespace OpenSim.Region.Framework.Scenes
2967 { 2962 {
2968 const float ROTATION_TOLERANCE = 0.01f; 2963 const float ROTATION_TOLERANCE = 0.01f;
2969 const float VELOCITY_TOLERANCE = 0.001f; 2964 const float VELOCITY_TOLERANCE = 0.001f;
2970 const float POSITION_TOLERANCE = 0.05f; 2965 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2971 const int TIME_MS_TOLERANCE = 3000; 2966 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2972 2967
2973 if (m_updateFlag == 1) 2968 if (m_updateFlag == 1)
2974 { 2969 {
@@ -2982,7 +2977,7 @@ namespace OpenSim.Region.Framework.Scenes
2982 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 2977 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
2983 { 2978 {
2984 AddTerseUpdateToAllAvatars(); 2979 AddTerseUpdateToAllAvatars();
2985 ClearUpdateSchedule(); 2980
2986 2981
2987 // This causes the Scene to 'poll' physical objects every couple of frames 2982 // This causes the Scene to 'poll' physical objects every couple of frames
2988 // bad, so it's been replaced by an event driven method. 2983 // bad, so it's been replaced by an event driven method.
@@ -3000,16 +2995,18 @@ namespace OpenSim.Region.Framework.Scenes
3000 m_lastAngularVelocity = AngularVelocity; 2995 m_lastAngularVelocity = AngularVelocity;
3001 m_lastTerseSent = Environment.TickCount; 2996 m_lastTerseSent = Environment.TickCount;
3002 } 2997 }
2998 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
2999 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
3003 } 3000 }
3004 else 3001 else
3005 { 3002 {
3006 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 3003 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3007 { 3004 {
3008 AddFullUpdateToAllAvatars(); 3005 AddFullUpdateToAllAvatars();
3009 ClearUpdateSchedule(); 3006 m_updateFlag = 0; //Same here
3010 } 3007 }
3011 } 3008 }
3012 ClearUpdateSchedule(); 3009 m_updateFlag = 0;
3013 } 3010 }
3014 3011
3015 /// <summary> 3012 /// <summary>
@@ -3036,17 +3033,16 @@ namespace OpenSim.Region.Framework.Scenes
3036 if (!UUID.TryParse(sound, out soundID)) 3033 if (!UUID.TryParse(sound, out soundID))
3037 { 3034 {
3038 // search sound file from inventory 3035 // search sound file from inventory
3039 lock (TaskInventory) 3036 TaskInventory.LockItemsForRead(true);
3037 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3040 { 3038 {
3041 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3039 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3042 { 3040 {
3043 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3041 soundID = item.Value.ItemID;
3044 { 3042 break;
3045 soundID = item.Value.ItemID;
3046 break;
3047 }
3048 } 3043 }
3049 } 3044 }
3045 TaskInventory.LockItemsForRead(false);
3050 } 3046 }
3051 3047
3052 if (soundID == UUID.Zero) 3048 if (soundID == UUID.Zero)
@@ -3481,7 +3477,7 @@ namespace OpenSim.Region.Framework.Scenes
3481 3477
3482 public void StopLookAt() 3478 public void StopLookAt()
3483 { 3479 {
3484 m_parentGroup.stopLookAt(); 3480 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3485 3481
3486 m_parentGroup.ScheduleGroupForTerseUpdate(); 3482 m_parentGroup.ScheduleGroupForTerseUpdate();
3487 } 3483 }
@@ -4475,8 +4471,9 @@ namespace OpenSim.Region.Framework.Scenes
4475 { 4471 {
4476 m_shape.TextureEntry = textureEntry; 4472 m_shape.TextureEntry = textureEntry;
4477 TriggerScriptChangedEvent(Changed.TEXTURE); 4473 TriggerScriptChangedEvent(Changed.TEXTURE);
4478 4474 m_updateFlag = 1;
4479 ParentGroup.HasGroupChanged = true; 4475 ParentGroup.HasGroupChanged = true;
4476
4480 //This is madness.. 4477 //This is madness..
4481 //ParentGroup.ScheduleGroupForFullUpdate(); 4478 //ParentGroup.ScheduleGroupForFullUpdate();
4482 //This is sparta 4479 //This is sparta
@@ -4721,5 +4718,17 @@ namespace OpenSim.Region.Framework.Scenes
4721 Color color = Color; 4718 Color color = Color;
4722 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4719 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4723 } 4720 }
4721
4722 public void ResetOwnerChangeFlag()
4723 {
4724 List<UUID> inv = Inventory.GetInventoryList();
4725
4726 foreach (UUID itemID in inv)
4727 {
4728 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4729 item.OwnerChanged = false;
4730 Inventory.UpdateInventoryItem(item);
4731 }
4732 }
4724 } 4733 }
4725} 4734}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 3a8f168..2cde8f3 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -46,6 +46,8 @@ namespace OpenSim.Region.Framework.Scenes
46 46
47 private string m_inventoryFileName = String.Empty; 47 private string m_inventoryFileName = String.Empty;
48 private int m_inventoryFileNameSerial = 0; 48 private int m_inventoryFileNameSerial = 0;
49
50 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
49 51
50 /// <value> 52 /// <value>
51 /// The part to which the inventory belongs. 53 /// The part to which the inventory belongs.
@@ -82,7 +84,9 @@ namespace OpenSim.Region.Framework.Scenes
82 /// </value> 84 /// </value>
83 protected internal TaskInventoryDictionary Items 85 protected internal TaskInventoryDictionary Items
84 { 86 {
85 get { return m_items; } 87 get {
88 return m_items;
89 }
86 set 90 set
87 { 91 {
88 m_items = value; 92 m_items = value;
@@ -118,22 +122,25 @@ namespace OpenSim.Region.Framework.Scenes
118 /// <param name="linkNum">Link number for the part</param> 122 /// <param name="linkNum">Link number for the part</param>
119 public void ResetInventoryIDs() 123 public void ResetInventoryIDs()
120 { 124 {
121 lock (Items) 125 m_items.LockItemsForWrite(true);
126
127 if (0 == Items.Count)
122 { 128 {
123 if (0 == Items.Count) 129 m_items.LockItemsForWrite(false);
124 return; 130 return;
131 }
125 132
126 HasInventoryChanged = true; 133 HasInventoryChanged = true;
127 m_part.ParentGroup.HasGroupChanged = true; 134 m_part.ParentGroup.HasGroupChanged = true;
128 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 135 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
129 Items.Clear(); 136 Items.Clear();
130 137
131 foreach (TaskInventoryItem item in items) 138 foreach (TaskInventoryItem item in items)
132 { 139 {
133 item.ResetIDs(m_part.UUID); 140 item.ResetIDs(m_part.UUID);
134 Items.Add(item.ItemID, item); 141 Items.Add(item.ItemID, item);
135 }
136 } 142 }
143 m_items.LockItemsForWrite(false);
137 } 144 }
138 145
139 /// <summary> 146 /// <summary>
@@ -142,25 +149,25 @@ namespace OpenSim.Region.Framework.Scenes
142 /// <param name="ownerId"></param> 149 /// <param name="ownerId"></param>
143 public void ChangeInventoryOwner(UUID ownerId) 150 public void ChangeInventoryOwner(UUID ownerId)
144 { 151 {
145 lock (Items) 152 m_items.LockItemsForWrite(true);
153 if (0 == Items.Count)
146 { 154 {
147 if (0 == Items.Count) 155 m_items.LockItemsForWrite(false);
148 { 156 return;
149 return; 157 }
150 }
151 158
152 HasInventoryChanged = true; 159 HasInventoryChanged = true;
153 m_part.ParentGroup.HasGroupChanged = true; 160 m_part.ParentGroup.HasGroupChanged = true;
154 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 161 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
155 foreach (TaskInventoryItem item in items) 162 foreach (TaskInventoryItem item in items)
163 {
164 if (ownerId != item.OwnerID)
156 { 165 {
157 if (ownerId != item.OwnerID) 166 item.LastOwnerID = item.OwnerID;
158 { 167 item.OwnerID = ownerId;
159 item.LastOwnerID = item.OwnerID;
160 item.OwnerID = ownerId;
161 }
162 } 168 }
163 } 169 }
170 m_items.LockItemsForWrite(false);
164 } 171 }
165 172
166 /// <summary> 173 /// <summary>
@@ -169,24 +176,24 @@ namespace OpenSim.Region.Framework.Scenes
169 /// <param name="groupID"></param> 176 /// <param name="groupID"></param>
170 public void ChangeInventoryGroup(UUID groupID) 177 public void ChangeInventoryGroup(UUID groupID)
171 { 178 {
172 lock (Items) 179 m_items.LockItemsForWrite(true);
180 if (0 == Items.Count)
173 { 181 {
174 if (0 == Items.Count) 182 m_items.LockItemsForWrite(false);
175 { 183 return;
176 return; 184 }
177 }
178 185
179 HasInventoryChanged = true; 186 HasInventoryChanged = true;
180 m_part.ParentGroup.HasGroupChanged = true; 187 m_part.ParentGroup.HasGroupChanged = true;
181 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 188 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
182 foreach (TaskInventoryItem item in items) 189 foreach (TaskInventoryItem item in items)
190 {
191 if (groupID != item.GroupID)
183 { 192 {
184 if (groupID != item.GroupID) 193 item.GroupID = groupID;
185 {
186 item.GroupID = groupID;
187 }
188 } 194 }
189 } 195 }
196 m_items.LockItemsForWrite(false);
190 } 197 }
191 198
192 /// <summary> 199 /// <summary>
@@ -194,15 +201,15 @@ namespace OpenSim.Region.Framework.Scenes
194 /// </summary> 201 /// </summary>
195 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 202 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
196 { 203 {
197 lock (m_items) 204 Items.LockItemsForRead(true);
205 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
206 Items.LockItemsForRead(false);
207 foreach (TaskInventoryItem item in items)
198 { 208 {
199 foreach (TaskInventoryItem item in Items.Values) 209 if ((int)InventoryType.LSL == item.InvType)
200 { 210 {
201 if ((int)InventoryType.LSL == item.InvType) 211 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
202 { 212 Thread.Sleep(10); // workaround for Mono cpu utilization > 100% bug
203 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
204 Thread.Sleep(10); // workaround for Mono cpu utilization > 100% bug
205 }
206 } 213 }
207 } 214 }
208 } 215 }
@@ -237,16 +244,20 @@ namespace OpenSim.Region.Framework.Scenes
237 /// </param> 244 /// </param>
238 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 245 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
239 { 246 {
240 lock (Items) 247 Items.LockItemsForRead(true);
248 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
249 Items.LockItemsForRead(false);
250
251 foreach (TaskInventoryItem item in items)
241 { 252 {
242 foreach (TaskInventoryItem item in Items.Values) 253 if ((int)InventoryType.LSL == item.InvType)
243 { 254 {
244 if ((int)InventoryType.LSL == item.InvType) 255 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
245 { 256 m_part.RemoveScriptEvents(item.ItemID);
246 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
247 }
248 } 257 }
249 } 258 }
259
260
250 } 261 }
251 262
252 /// <summary> 263 /// <summary>
@@ -262,7 +273,10 @@ namespace OpenSim.Region.Framework.Scenes
262 // item.Name, item.ItemID, m_part.Name, m_part.UUID); 273 // item.Name, item.ItemID, m_part.Name, m_part.UUID);
263 274
264 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 275 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
276 {
277 StoreScriptError(item.ItemID, "no permission");
265 return; 278 return;
279 }
266 280
267 m_part.AddFlag(PrimFlags.Scripted); 281 m_part.AddFlag(PrimFlags.Scripted);
268 282
@@ -271,14 +285,13 @@ namespace OpenSim.Region.Framework.Scenes
271 if (stateSource == 1 && // Prim crossing 285 if (stateSource == 1 && // Prim crossing
272 m_part.ParentGroup.Scene.m_trustBinaries) 286 m_part.ParentGroup.Scene.m_trustBinaries)
273 { 287 {
274 lock (m_items) 288 m_items.LockItemsForWrite(true);
275 { 289 m_items[item.ItemID].PermsMask = 0;
276 m_items[item.ItemID].PermsMask = 0; 290 m_items[item.ItemID].PermsGranter = UUID.Zero;
277 m_items[item.ItemID].PermsGranter = UUID.Zero; 291 m_items.LockItemsForWrite(false);
278 }
279
280 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 292 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
281 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 293 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
294 StoreScriptErrors(item.ItemID, null);
282 m_part.ParentGroup.AddActiveScriptCount(1); 295 m_part.ParentGroup.AddActiveScriptCount(1);
283 m_part.ScheduleFullUpdate(); 296 m_part.ScheduleFullUpdate();
284 return; 297 return;
@@ -287,6 +300,8 @@ namespace OpenSim.Region.Framework.Scenes
287 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 300 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
288 if (null == asset) 301 if (null == asset)
289 { 302 {
303 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
304 StoreScriptError(item.ItemID, msg);
290 m_log.ErrorFormat( 305 m_log.ErrorFormat(
291 "[PRIM INVENTORY]: " + 306 "[PRIM INVENTORY]: " +
292 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 307 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -295,20 +310,22 @@ namespace OpenSim.Region.Framework.Scenes
295 } 310 }
296 else 311 else
297 { 312 {
298 lock (m_items) 313 if (m_part.ParentGroup.m_savedScriptState != null)
299 { 314 RestoreSavedScriptState(item.OldItemID, item.ItemID);
300 if (m_part.ParentGroup.m_savedScriptState != null)
301 RestoreSavedScriptState(item.OldItemID, item.ItemID);
302 315
303 m_items[item.ItemID].PermsMask = 0; 316 m_items.LockItemsForWrite(true);
304 m_items[item.ItemID].PermsGranter = UUID.Zero;
305 317
306 string script = Utils.BytesToString(asset.Data); 318 m_items[item.ItemID].PermsMask = 0;
307 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 319 m_items[item.ItemID].PermsGranter = UUID.Zero;
308 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 320
309 m_part.ParentGroup.AddActiveScriptCount(1); 321 m_items.LockItemsForWrite(false);
310 m_part.ScheduleFullUpdate(); 322
311 } 323 string script = Utils.BytesToString(asset.Data);
324 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
325 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
326 StoreScriptErrors(item.ItemID, null);
327 m_part.ParentGroup.AddActiveScriptCount(1);
328 m_part.ScheduleFullUpdate();
312 } 329 }
313 } 330 }
314 } 331 }
@@ -370,27 +387,145 @@ namespace OpenSim.Region.Framework.Scenes
370 387
371 /// <summary> 388 /// <summary>
372 /// Start a script which is in this prim's inventory. 389 /// Start a script which is in this prim's inventory.
390 /// Some processing may occur in the background, but this routine returns asap.
373 /// </summary> 391 /// </summary>
374 /// <param name="itemId"> 392 /// <param name="itemId">
375 /// A <see cref="UUID"/> 393 /// A <see cref="UUID"/>
376 /// </param> 394 /// </param>
377 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 395 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
378 { 396 {
379 lock (m_items) 397 lock (m_scriptErrors)
398 {
399 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
400 m_scriptErrors.Remove(itemId);
401 }
402 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
403 }
404
405 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
406 {
407 m_items.LockItemsForRead(true);
408 if (m_items.ContainsKey(itemId))
380 { 409 {
381 if (m_items.ContainsKey(itemId)) 410 if (m_items.ContainsKey(itemId))
382 { 411 {
412 m_items.LockItemsForRead(false);
383 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource); 413 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
384 } 414 }
385 else 415 else
386 { 416 {
417 m_items.LockItemsForRead(false);
418 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
419 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
420 StoreScriptError(itemId, msg);
387 m_log.ErrorFormat( 421 m_log.ErrorFormat(
388 "[PRIM INVENTORY]: " + 422 "[PRIM INVENTORY]: " +
389 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 423 "Couldn't start script with ID {0} since it {1}", itemId, msg);
390 itemId, m_part.Name, m_part.UUID,
391 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
392 } 424 }
393 } 425 }
426 else
427 {
428 m_items.LockItemsForRead(false);
429 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
430 StoreScriptError(itemId, msg);
431 m_log.ErrorFormat(
432 "[PRIM INVENTORY]: " +
433 "Couldn't start script with ID {0} since it {1}", itemId, msg);
434 }
435
436 }
437
438 /// <summary>
439 /// Start a script which is in this prim's inventory and return any compilation error messages.
440 /// </summary>
441 /// <param name="itemId">
442 /// A <see cref="UUID"/>
443 /// </param>
444 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
445 {
446 ArrayList errors;
447
448 // Indicate to CreateScriptInstanceInternal() we want it to
449 // post any compilation/loading error messages
450 lock (m_scriptErrors)
451 {
452 m_scriptErrors[itemId] = null;
453 }
454
455 // Perform compilation/loading
456 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
457
458 // Wait for and retrieve any errors
459 lock (m_scriptErrors)
460 {
461 while ((errors = m_scriptErrors[itemId]) == null)
462 {
463 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
464 {
465 m_log.ErrorFormat(
466 "[PRIM INVENTORY]: " +
467 "timedout waiting for script {0} errors", itemId);
468 errors = m_scriptErrors[itemId];
469 if (errors == null)
470 {
471 errors = new ArrayList(1);
472 errors.Add("timedout waiting for errors");
473 }
474 break;
475 }
476 }
477 m_scriptErrors.Remove(itemId);
478 }
479 return errors;
480 }
481
482 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
483 private void StoreScriptErrors(UUID itemId, ArrayList errors)
484 {
485 lock (m_scriptErrors)
486 {
487 // If compilation/loading initiated via CreateScriptInstance(),
488 // it does not want the errors, so just get out
489 if (!m_scriptErrors.ContainsKey(itemId))
490 {
491 return;
492 }
493
494 // Initiated via CreateScriptInstanceEr(), if we know what the
495 // errors are, save them and wake CreateScriptInstanceEr().
496 if (errors != null)
497 {
498 m_scriptErrors[itemId] = errors;
499 System.Threading.Monitor.PulseAll(m_scriptErrors);
500 return;
501 }
502 }
503
504 // Initiated via CreateScriptInstanceEr() but we don't know what
505 // the errors are yet, so retrieve them from the script engine.
506 // This may involve some waiting internal to GetScriptErrors().
507 errors = GetScriptErrors(itemId);
508
509 // Get a default non-null value to indicate success.
510 if (errors == null)
511 {
512 errors = new ArrayList();
513 }
514
515 // Post to CreateScriptInstanceEr() and wake it up
516 lock (m_scriptErrors)
517 {
518 m_scriptErrors[itemId] = errors;
519 System.Threading.Monitor.PulseAll(m_scriptErrors);
520 }
521 }
522
523 // Like StoreScriptErrors(), but just posts a single string message
524 private void StoreScriptError(UUID itemId, string message)
525 {
526 ArrayList errors = new ArrayList(1);
527 errors.Add(message);
528 StoreScriptErrors(itemId, errors);
394 } 529 }
395 530
396 /// <summary> 531 /// <summary>
@@ -403,15 +538,7 @@ namespace OpenSim.Region.Framework.Scenes
403 /// </param> 538 /// </param>
404 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 539 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
405 { 540 {
406 bool scriptPresent = false; 541 if (m_items.ContainsKey(itemId))
407
408 lock (m_items)
409 {
410 if (m_items.ContainsKey(itemId))
411 scriptPresent = true;
412 }
413
414 if (scriptPresent)
415 { 542 {
416 if (!sceneObjectBeingDeleted) 543 if (!sceneObjectBeingDeleted)
417 m_part.RemoveScriptEvents(itemId); 544 m_part.RemoveScriptEvents(itemId);
@@ -437,11 +564,16 @@ namespace OpenSim.Region.Framework.Scenes
437 /// <returns></returns> 564 /// <returns></returns>
438 private bool InventoryContainsName(string name) 565 private bool InventoryContainsName(string name)
439 { 566 {
440 foreach (TaskInventoryItem item in Items.Values) 567 m_items.LockItemsForRead(true);
568 foreach (TaskInventoryItem item in m_items.Values)
441 { 569 {
442 if (item.Name == name) 570 if (item.Name == name)
571 {
572 m_items.LockItemsForRead(false);
443 return true; 573 return true;
574 }
444 } 575 }
576 m_items.LockItemsForRead(false);
445 return false; 577 return false;
446 } 578 }
447 579
@@ -483,13 +615,9 @@ namespace OpenSim.Region.Framework.Scenes
483 /// <param name="item"></param> 615 /// <param name="item"></param>
484 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 616 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
485 { 617 {
486 List<TaskInventoryItem> il; 618 m_items.LockItemsForRead(true);
487 619 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
488 lock (m_items) 620 m_items.LockItemsForRead(false);
489 {
490 il = new List<TaskInventoryItem>(m_items.Values);
491 }
492
493 foreach (TaskInventoryItem i in il) 621 foreach (TaskInventoryItem i in il)
494 { 622 {
495 if (i.Name == item.Name) 623 if (i.Name == item.Name)
@@ -527,15 +655,14 @@ namespace OpenSim.Region.Framework.Scenes
527 item.Name = name; 655 item.Name = name;
528 item.GroupID = m_part.GroupID; 656 item.GroupID = m_part.GroupID;
529 657
530 lock (m_items) 658 m_items.LockItemsForWrite(true);
531 { 659 m_items.Add(item.ItemID, item);
532 m_items.Add(item.ItemID, item); 660 m_items.LockItemsForWrite(false);
533
534 if (allowedDrop) 661 if (allowedDrop)
535 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 662 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
536 else 663 else
537 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 664 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
538 } 665
539 666
540 m_inventorySerial++; 667 m_inventorySerial++;
541 //m_inventorySerial += 2; 668 //m_inventorySerial += 2;
@@ -552,14 +679,13 @@ namespace OpenSim.Region.Framework.Scenes
552 /// <param name="items"></param> 679 /// <param name="items"></param>
553 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 680 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
554 { 681 {
555 lock (m_items) 682 m_items.LockItemsForWrite(true);
683 foreach (TaskInventoryItem item in items)
556 { 684 {
557 foreach (TaskInventoryItem item in items) 685 m_items.Add(item.ItemID, item);
558 { 686// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
559 m_items.Add(item.ItemID, item);
560// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
561 }
562 } 687 }
688 m_items.LockItemsForWrite(false);
563 689
564 m_inventorySerial++; 690 m_inventorySerial++;
565 } 691 }
@@ -572,10 +698,9 @@ namespace OpenSim.Region.Framework.Scenes
572 public TaskInventoryItem GetInventoryItem(UUID itemId) 698 public TaskInventoryItem GetInventoryItem(UUID itemId)
573 { 699 {
574 TaskInventoryItem item; 700 TaskInventoryItem item;
575 701 m_items.LockItemsForRead(true);
576 lock (m_items) 702 m_items.TryGetValue(itemId, out item);
577 m_items.TryGetValue(itemId, out item); 703 m_items.LockItemsForRead(false);
578
579 return item; 704 return item;
580 } 705 }
581 706
@@ -591,15 +716,16 @@ namespace OpenSim.Region.Framework.Scenes
591 { 716 {
592 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 717 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
593 718
594 lock (m_items) 719 m_items.LockItemsForRead(true);
720
721 foreach (TaskInventoryItem item in m_items.Values)
595 { 722 {
596 foreach (TaskInventoryItem item in m_items.Values) 723 if (item.Name == name)
597 { 724 items.Add(item);
598 if (item.Name == name)
599 items.Add(item);
600 }
601 } 725 }
602 726
727 m_items.LockItemsForRead(false);
728
603 return items; 729 return items;
604 } 730 }
605 731
@@ -616,45 +742,54 @@ namespace OpenSim.Region.Framework.Scenes
616 742
617 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents) 743 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents)
618 { 744 {
619 lock(m_items) 745 m_items.LockItemsForWrite(true);
746
747 if (m_items.ContainsKey(item.ItemID))
620 { 748 {
621 if (m_items.ContainsKey(item.ItemID)) 749 item.ParentID = m_part.UUID;
750 item.ParentPartID = m_part.UUID;
751 item.Flags = m_items[item.ItemID].Flags;
752
753 // If group permissions have been set on, check that the groupID is up to date in case it has
754 // changed since permissions were last set.
755 if (item.GroupPermissions != (uint)PermissionMask.None)
756 item.GroupID = m_part.GroupID;
757
758 if (item.AssetID == UUID.Zero)
622 { 759 {
623 if (m_items.ContainsKey(item.ItemID)) 760 item.AssetID = m_items[item.ItemID].AssetID;
624 { 761 }
625 item.ParentID = m_part.UUID; 762 else if ((InventoryType)item.Type == InventoryType.Notecard)
626 item.ParentPartID = m_part.UUID; 763 {
627 item.Flags = m_items[item.ItemID].Flags; 764 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
628 765
629 // If group permissions have been set on, check that the groupID is up to date in case it has 766 if (presence != null)
630 // changed since permissions were last set.
631 if (item.GroupPermissions != (uint)PermissionMask.None)
632 item.GroupID = m_part.GroupID;
633
634 if (item.AssetID == UUID.Zero)
635 {
636 item.AssetID = m_items[item.ItemID].AssetID;
637 }
638 m_items[item.ItemID] = item;
639 m_inventorySerial++;
640 if (fireScriptEvents)
641 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
642 HasInventoryChanged = true;
643 m_part.ParentGroup.HasGroupChanged = true;
644 return true;
645 }
646 else
647 { 767 {
648 m_log.ErrorFormat( 768 presence.ControllingClient.SendAgentAlertMessage(
649 "[PRIM INVENTORY]: " + 769 "Notecard saved", false);
650 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
651 item.ItemID, m_part.Name, m_part.UUID,
652 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
653 } 770 }
654
655 } 771 }
656 return false; 772
773 m_items[item.ItemID] = item;
774 m_inventorySerial++;
775 if (fireScriptEvents)
776 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
777 HasInventoryChanged = true;
778 m_part.ParentGroup.HasGroupChanged = true;
779 m_items.LockItemsForWrite(false);
780 return true;
657 } 781 }
782 else
783 {
784 m_log.ErrorFormat(
785 "[PRIM INVENTORY]: " +
786 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
787 item.ItemID, m_part.Name, m_part.UUID,
788 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
789 }
790 m_items.LockItemsForWrite(false);
791
792 return false;
658 } 793 }
659 794
660 /// <summary> 795 /// <summary>
@@ -665,52 +800,53 @@ namespace OpenSim.Region.Framework.Scenes
665 /// in this prim's inventory.</returns> 800 /// in this prim's inventory.</returns>
666 public int RemoveInventoryItem(UUID itemID) 801 public int RemoveInventoryItem(UUID itemID)
667 { 802 {
668 lock (m_items) 803 m_items.LockItemsForRead(true);
804
805 if (m_items.ContainsKey(itemID))
669 { 806 {
670 if (m_items.ContainsKey(itemID)) 807 int type = m_items[itemID].InvType;
808 m_items.LockItemsForRead(false);
809 if (type == 10) // Script
671 { 810 {
672 int type = m_items[itemID].InvType; 811 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
673 if (type == 10) // Script 812 }
674 { 813 m_items.LockItemsForWrite(true);
675 m_part.RemoveScriptEvents(itemID); 814 m_items.Remove(itemID);
676 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 815 m_items.LockItemsForWrite(false);
677 } 816 m_inventorySerial++;
678 m_items.Remove(itemID); 817 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
679 m_inventorySerial++;
680 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
681
682 HasInventoryChanged = true;
683 m_part.ParentGroup.HasGroupChanged = true;
684 818
685 int scriptcount = 0; 819 HasInventoryChanged = true;
686 lock (m_items) 820 m_part.ParentGroup.HasGroupChanged = true;
687 {
688 foreach (TaskInventoryItem item in m_items.Values)
689 {
690 if (item.Type == 10)
691 {
692 scriptcount++;
693 }
694 }
695 }
696 821
697 if (scriptcount <= 0) 822 int scriptcount = 0;
823 m_items.LockItemsForRead(true);
824 foreach (TaskInventoryItem item in m_items.Values)
825 {
826 if (item.Type == 10)
698 { 827 {
699 m_part.RemFlag(PrimFlags.Scripted); 828 scriptcount++;
700 } 829 }
701
702 m_part.ScheduleFullUpdate();
703
704 return type;
705 } 830 }
706 else 831 m_items.LockItemsForRead(false);
832
833
834 if (scriptcount <= 0)
707 { 835 {
708 m_log.ErrorFormat( 836 m_part.RemFlag(PrimFlags.Scripted);
709 "[PRIM INVENTORY]: " +
710 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
711 itemID, m_part.Name, m_part.UUID,
712 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
713 } 837 }
838
839 m_part.ScheduleFullUpdate();
840
841 return type;
842 }
843 else
844 {
845 m_items.LockItemsForRead(false);
846 m_log.ErrorFormat(
847 "[PRIM INVENTORY]: " +
848 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
849 itemID, m_part.Name, m_part.UUID);
714 } 850 }
715 851
716 return -1; 852 return -1;
@@ -764,53 +900,54 @@ namespace OpenSim.Region.Framework.Scenes
764 // isn't available (such as drag from prim inventory to agent inventory) 900 // isn't available (such as drag from prim inventory to agent inventory)
765 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 901 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
766 902
767 lock (m_items) 903 m_items.LockItemsForRead(true);
904
905 foreach (TaskInventoryItem item in m_items.Values)
768 { 906 {
769 foreach (TaskInventoryItem item in m_items.Values) 907 UUID ownerID = item.OwnerID;
770 { 908 uint everyoneMask = 0;
771 UUID ownerID = item.OwnerID; 909 uint baseMask = item.BasePermissions;
772 uint everyoneMask = 0; 910 uint ownerMask = item.CurrentPermissions;
773 uint baseMask = item.BasePermissions; 911 uint groupMask = item.GroupPermissions;
774 uint ownerMask = item.CurrentPermissions;
775 uint groupMask = item.GroupPermissions;
776 912
777 invString.AddItemStart(); 913 invString.AddItemStart();
778 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 914 invString.AddNameValueLine("item_id", item.ItemID.ToString());
779 invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); 915 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
780 916
781 invString.AddPermissionsStart(); 917 invString.AddPermissionsStart();
782 918
783 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 919 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
784 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 920 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
785 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 921 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
786 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); 922 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
787 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); 923 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
788 924
789 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 925 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
790 invString.AddNameValueLine("owner_id", ownerID.ToString()); 926 invString.AddNameValueLine("owner_id", ownerID.ToString());
791 927
792 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 928 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
793 929
794 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 930 invString.AddNameValueLine("group_id", item.GroupID.ToString());
795 invString.AddSectionEnd(); 931 invString.AddSectionEnd();
796 932
797 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 933 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
798 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); 934 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
799 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); 935 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
800 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); 936 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
801 937
802 invString.AddSaleStart(); 938 invString.AddSaleStart();
803 invString.AddNameValueLine("sale_type", "not"); 939 invString.AddNameValueLine("sale_type", "not");
804 invString.AddNameValueLine("sale_price", "0"); 940 invString.AddNameValueLine("sale_price", "0");
805 invString.AddSectionEnd(); 941 invString.AddSectionEnd();
806 942
807 invString.AddNameValueLine("name", item.Name + "|"); 943 invString.AddNameValueLine("name", item.Name + "|");
808 invString.AddNameValueLine("desc", item.Description + "|"); 944 invString.AddNameValueLine("desc", item.Description + "|");
809 945
810 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 946 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
811 invString.AddSectionEnd(); 947 invString.AddSectionEnd();
812 }
813 } 948 }
949 int count = m_items.Count;
950 m_items.LockItemsForRead(false);
814 951
815 fileData = Utils.StringToBytes(invString.BuildString); 952 fileData = Utils.StringToBytes(invString.BuildString);
816 953
@@ -831,10 +968,9 @@ namespace OpenSim.Region.Framework.Scenes
831 { 968 {
832 if (HasInventoryChanged) 969 if (HasInventoryChanged)
833 { 970 {
834 lock (Items) 971 Items.LockItemsForRead(true);
835 { 972 datastore.StorePrimInventory(m_part.UUID, Items.Values);
836 datastore.StorePrimInventory(m_part.UUID, Items.Values); 973 Items.LockItemsForRead(false);
837 }
838 974
839 HasInventoryChanged = false; 975 HasInventoryChanged = false;
840 } 976 }
@@ -903,90 +1039,76 @@ namespace OpenSim.Region.Framework.Scenes
903 { 1039 {
904 uint mask=0x7fffffff; 1040 uint mask=0x7fffffff;
905 1041
906 lock (m_items) 1042 foreach (TaskInventoryItem item in m_items.Values)
907 { 1043 {
908 foreach (TaskInventoryItem item in m_items.Values) 1044 if (item.InvType != (int)InventoryType.Object)
909 { 1045 {
910 if (item.InvType != (int)InventoryType.Object) 1046 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
911 { 1047 mask &= ~((uint)PermissionMask.Copy >> 13);
912 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1048 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
913 mask &= ~((uint)PermissionMask.Copy >> 13); 1049 mask &= ~((uint)PermissionMask.Transfer >> 13);
914 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1050 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
915 mask &= ~((uint)PermissionMask.Transfer >> 13); 1051 mask &= ~((uint)PermissionMask.Modify >> 13);
916 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
917 mask &= ~((uint)PermissionMask.Modify >> 13);
918 }
919 else
920 {
921 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
922 mask &= ~((uint)PermissionMask.Copy >> 13);
923 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
924 mask &= ~((uint)PermissionMask.Transfer >> 13);
925 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
926 mask &= ~((uint)PermissionMask.Modify >> 13);
927 }
928
929 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
930 mask &= ~(uint)PermissionMask.Copy;
931 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
932 mask &= ~(uint)PermissionMask.Transfer;
933 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
934 mask &= ~(uint)PermissionMask.Modify;
935 } 1052 }
1053 else
1054 {
1055 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1056 mask &= ~((uint)PermissionMask.Copy >> 13);
1057 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1058 mask &= ~((uint)PermissionMask.Transfer >> 13);
1059 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1060 mask &= ~((uint)PermissionMask.Modify >> 13);
1061 }
1062
1063 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1064 mask &= ~(uint)PermissionMask.Copy;
1065 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1066 mask &= ~(uint)PermissionMask.Transfer;
1067 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1068 mask &= ~(uint)PermissionMask.Modify;
936 } 1069 }
937
938 return mask; 1070 return mask;
939 } 1071 }
940 1072
941 public void ApplyNextOwnerPermissions() 1073 public void ApplyNextOwnerPermissions()
942 { 1074 {
943 lock (m_items) 1075 foreach (TaskInventoryItem item in m_items.Values)
944 { 1076 {
945 foreach (TaskInventoryItem item in m_items.Values) 1077 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
946 { 1078 {
947 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1079 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
948 { 1080 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
949 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1081 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
950 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1082 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
951 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1083 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
952 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1084 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
953 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) 1085 item.CurrentPermissions |= 8;
954 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
955 item.CurrentPermissions |= 8;
956 }
957 item.CurrentPermissions &= item.NextPermissions;
958 item.BasePermissions &= item.NextPermissions;
959 item.EveryonePermissions &= item.NextPermissions;
960 item.OwnerChanged = true;
961 } 1086 }
1087 item.OwnerChanged = true;
1088 item.CurrentPermissions &= item.NextPermissions;
1089 item.BasePermissions &= item.NextPermissions;
1090 item.EveryonePermissions &= item.NextPermissions;
962 } 1091 }
963 } 1092 }
964 1093
965 public void ApplyGodPermissions(uint perms) 1094 public void ApplyGodPermissions(uint perms)
966 { 1095 {
967 lock (m_items) 1096 foreach (TaskInventoryItem item in m_items.Values)
968 { 1097 {
969 foreach (TaskInventoryItem item in m_items.Values) 1098 item.CurrentPermissions = perms;
970 { 1099 item.BasePermissions = perms;
971 item.CurrentPermissions = perms;
972 item.BasePermissions = perms;
973 }
974 } 1100 }
975 } 1101 }
976 1102
977 public bool ContainsScripts() 1103 public bool ContainsScripts()
978 { 1104 {
979 lock (m_items) 1105 foreach (TaskInventoryItem item in m_items.Values)
980 { 1106 {
981 foreach (TaskInventoryItem item in m_items.Values) 1107 if (item.InvType == (int)InventoryType.LSL)
982 { 1108 {
983 if (item.InvType == (int)InventoryType.LSL) 1109 return true;
984 {
985 return true;
986 }
987 } 1110 }
988 } 1111 }
989
990 return false; 1112 return false;
991 } 1113 }
992 1114
@@ -994,46 +1116,52 @@ namespace OpenSim.Region.Framework.Scenes
994 { 1116 {
995 List<UUID> ret = new List<UUID>(); 1117 List<UUID> ret = new List<UUID>();
996 1118
997 lock (m_items) 1119 foreach (TaskInventoryItem item in m_items.Values)
998 { 1120 ret.Add(item.ItemID);
999 foreach (TaskInventoryItem item in m_items.Values)
1000 ret.Add(item.ItemID);
1001 }
1002 1121
1003 return ret; 1122 return ret;
1004 } 1123 }
1005 1124
1006 public Dictionary<UUID, string> GetScriptStates() 1125 public Dictionary<UUID, string> GetScriptStates()
1007 { 1126 {
1127 return GetScriptStates(false);
1128 }
1129
1130 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1131 {
1008 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 1132 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
1009 1133
1010 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1134 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1011 if (engines == null) // No engine at all 1135 if (engines == null) // No engine at all
1012 return ret; 1136 return ret;
1013 1137
1014 lock (m_items) 1138 foreach (TaskInventoryItem item in m_items.Values)
1015 { 1139 {
1016 foreach (TaskInventoryItem item in m_items.Values) 1140 if (item.InvType == (int)InventoryType.LSL)
1017 { 1141 {
1018 if (item.InvType == (int)InventoryType.LSL) 1142 foreach (IScriptModule e in engines)
1019 { 1143 {
1020 foreach (IScriptModule e in engines) 1144 if (e != null)
1021 { 1145 {
1022 if (e != null) 1146 string n = e.GetXMLState(item.ItemID);
1147 if (n != String.Empty)
1023 { 1148 {
1024 string n = e.GetXMLState(item.ItemID); 1149 if (oldIDs)
1025 if (n != String.Empty) 1150 {
1151 if (!ret.ContainsKey(item.OldItemID))
1152 ret[item.OldItemID] = n;
1153 }
1154 else
1026 { 1155 {
1027 if (!ret.ContainsKey(item.ItemID)) 1156 if (!ret.ContainsKey(item.ItemID))
1028 ret[item.ItemID] = n; 1157 ret[item.ItemID] = n;
1029 break;
1030 } 1158 }
1159 break;
1031 } 1160 }
1032 } 1161 }
1033 } 1162 }
1034 } 1163 }
1035 } 1164 }
1036
1037 return ret; 1165 return ret;
1038 } 1166 }
1039 1167
@@ -1043,25 +1171,27 @@ namespace OpenSim.Region.Framework.Scenes
1043 if (engines == null) 1171 if (engines == null)
1044 return; 1172 return;
1045 1173
1046 lock (m_items) 1174
1175 Items.LockItemsForRead(true);
1176
1177 foreach (TaskInventoryItem item in m_items.Values)
1047 { 1178 {
1048 foreach (TaskInventoryItem item in m_items.Values) 1179 if (item.InvType == (int)InventoryType.LSL)
1049 { 1180 {
1050 if (item.InvType == (int)InventoryType.LSL) 1181 foreach (IScriptModule engine in engines)
1051 { 1182 {
1052 foreach (IScriptModule engine in engines) 1183 if (engine != null)
1053 { 1184 {
1054 if (engine != null) 1185 if (item.OwnerChanged)
1055 { 1186 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1056 if (item.OwnerChanged) 1187 item.OwnerChanged = false;
1057 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1188 engine.ResumeScript(item.ItemID);
1058 item.OwnerChanged = false;
1059 engine.ResumeScript(item.ItemID);
1060 }
1061 } 1189 }
1062 } 1190 }
1063 } 1191 }
1064 } 1192 }
1193
1194 Items.LockItemsForRead(false);
1065 } 1195 }
1066 } 1196 }
1067} 1197}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 6c119c2..4a4cac9 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.Reflection; 31using System.Reflection;
31using System.Timers; 32using System.Timers;
@@ -73,7 +74,7 @@ namespace OpenSim.Region.Framework.Scenes
73// { 74// {
74// m_log.Debug("[ScenePresence] Destructor called"); 75// m_log.Debug("[ScenePresence] Destructor called");
75// } 76// }
76 77
77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
78 79
79 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; 80 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
@@ -89,7 +90,9 @@ namespace OpenSim.Region.Framework.Scenes
89 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 90 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
90 /// issue #1716 91 /// issue #1716
91 /// </summary> 92 /// </summary>
92 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); 93// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
94 // Value revised by KF 091121 by comparison with SL.
95 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
93 96
94 public UUID currentParcelUUID = UUID.Zero; 97 public UUID currentParcelUUID = UUID.Zero;
95 98
@@ -123,8 +126,11 @@ namespace OpenSim.Region.Framework.Scenes
123 public Vector3 lastKnownAllowedPosition; 126 public Vector3 lastKnownAllowedPosition;
124 public bool sentMessageAboutRestrictedParcelFlyingDown; 127 public bool sentMessageAboutRestrictedParcelFlyingDown;
125 public Vector4 CollisionPlane = Vector4.UnitW; 128 public Vector4 CollisionPlane = Vector4.UnitW;
126 129
130 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
131 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
127 private Vector3 m_lastPosition; 132 private Vector3 m_lastPosition;
133 private Vector3 m_lastWorldPosition;
128 private Quaternion m_lastRotation; 134 private Quaternion m_lastRotation;
129 private Vector3 m_lastVelocity; 135 private Vector3 m_lastVelocity;
130 //private int m_lastTerseSent; 136 //private int m_lastTerseSent;
@@ -157,7 +163,6 @@ namespace OpenSim.Region.Framework.Scenes
157 private int m_perfMonMS; 163 private int m_perfMonMS;
158 164
159 private bool m_setAlwaysRun; 165 private bool m_setAlwaysRun;
160
161 private bool m_forceFly; 166 private bool m_forceFly;
162 private bool m_flyDisabled; 167 private bool m_flyDisabled;
163 168
@@ -181,7 +186,8 @@ namespace OpenSim.Region.Framework.Scenes
181 protected RegionInfo m_regionInfo; 186 protected RegionInfo m_regionInfo;
182 protected ulong crossingFromRegion; 187 protected ulong crossingFromRegion;
183 188
184 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 189 private readonly Vector3[] Dir_Vectors = new Vector3[11];
190 private bool m_isNudging = false;
185 191
186 // Position of agent's camera in world (region cordinates) 192 // Position of agent's camera in world (region cordinates)
187 protected Vector3 m_CameraCenter; 193 protected Vector3 m_CameraCenter;
@@ -206,17 +212,23 @@ namespace OpenSim.Region.Framework.Scenes
206 private bool m_autopilotMoving; 212 private bool m_autopilotMoving;
207 private Vector3 m_autoPilotTarget; 213 private Vector3 m_autoPilotTarget;
208 private bool m_sitAtAutoTarget; 214 private bool m_sitAtAutoTarget;
215 private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
209 216
210 private string m_nextSitAnimation = String.Empty; 217 private string m_nextSitAnimation = String.Empty;
211 218
212 //PauPaw:Proper PID Controler for autopilot************ 219 //PauPaw:Proper PID Controler for autopilot************
213 private bool m_moveToPositionInProgress; 220 private bool m_moveToPositionInProgress;
214 private Vector3 m_moveToPositionTarget; 221 private Vector3 m_moveToPositionTarget;
222 private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
215 223
216 private bool m_followCamAuto; 224 private bool m_followCamAuto;
217 225
218 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
219 private const int NumMovementsBetweenRayCast = 5; 230 private const int NumMovementsBetweenRayCast = 5;
231 private List<uint> m_lastColliders = new List<uint>();
220 232
221 private bool CameraConstraintActive; 233 private bool CameraConstraintActive;
222 //private int m_moveToPositionStateStatus; 234 //private int m_moveToPositionStateStatus;
@@ -243,7 +255,9 @@ namespace OpenSim.Region.Framework.Scenes
243 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 255 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
244 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 256 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
245 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 257 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
246 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 258 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
259 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
260 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
247 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 261 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
248 } 262 }
249 263
@@ -450,9 +464,18 @@ namespace OpenSim.Region.Framework.Scenes
450 get 464 get
451 { 465 {
452 PhysicsActor actor = m_physicsActor; 466 PhysicsActor actor = m_physicsActor;
453 if (actor != null) 467// if (actor != null)
468 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
454 m_pos = actor.Position; 469 m_pos = actor.Position;
455 470
471 // If we're sitting, we need to update our position
472 if (m_parentID != 0)
473 {
474 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
475 if (part != null)
476 m_parentPosition = part.AbsolutePosition;
477 }
478
456 return m_parentPosition + m_pos; 479 return m_parentPosition + m_pos;
457 } 480 }
458 set 481 set
@@ -471,7 +494,8 @@ namespace OpenSim.Region.Framework.Scenes
471 } 494 }
472 } 495 }
473 496
474 m_pos = value; 497 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
498 m_pos = value;
475 m_parentPosition = Vector3.Zero; 499 m_parentPosition = Vector3.Zero;
476 } 500 }
477 } 501 }
@@ -515,10 +539,39 @@ namespace OpenSim.Region.Framework.Scenes
515 } 539 }
516 } 540 }
517 541
542 public Quaternion OffsetRotation
543 {
544 get { return m_offsetRotation; }
545 set { m_offsetRotation = value; }
546 }
547
518 public Quaternion Rotation 548 public Quaternion Rotation
519 { 549 {
520 get { return m_bodyRot; } 550 get {
521 set { m_bodyRot = value; } 551 if (m_parentID != 0)
552 {
553 if (m_offsetRotation != null)
554 {
555 return m_offsetRotation;
556 }
557 else
558 {
559 return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
560 }
561
562 }
563 else
564 {
565 return m_bodyRot;
566 }
567 }
568 set {
569 m_bodyRot = value;
570 if (m_parentID != 0)
571 {
572 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
573 }
574 }
522 } 575 }
523 576
524 public Quaternion PreviousRotation 577 public Quaternion PreviousRotation
@@ -669,7 +722,7 @@ namespace OpenSim.Region.Framework.Scenes
669 CreateSceneViewer(); 722 CreateSceneViewer();
670 m_animator = new ScenePresenceAnimator(this); 723 m_animator = new ScenePresenceAnimator(this);
671 } 724 }
672 725
673 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() 726 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
674 { 727 {
675 m_rootRegionHandle = reginfo.RegionHandle; 728 m_rootRegionHandle = reginfo.RegionHandle;
@@ -701,16 +754,16 @@ namespace OpenSim.Region.Framework.Scenes
701 m_reprioritization_timer.AutoReset = false; 754 m_reprioritization_timer.AutoReset = false;
702 755
703 AdjustKnownSeeds(); 756 AdjustKnownSeeds();
704
705 // TODO: I think, this won't send anything, as we are still a child here...
706 Animator.TrySetMovementAnimation("STAND"); 757 Animator.TrySetMovementAnimation("STAND");
707
708 // we created a new ScenePresence (a new child agent) in a fresh region. 758 // we created a new ScenePresence (a new child agent) in a fresh region.
709 // Request info about all the (root) agents in this region 759 // Request info about all the (root) agents in this region
710 // Note: This won't send data *to* other clients in that region (children don't send) 760 // Note: This won't send data *to* other clients in that region (children don't send)
711 SendInitialFullUpdateToAllClients(); 761 SendInitialFullUpdateToAllClients();
712
713 RegisterToEvents(); 762 RegisterToEvents();
763 if (m_controllingClient != null)
764 {
765 m_controllingClient.ProcessPendingPackets();
766 }
714 SetDirectionVectors(); 767 SetDirectionVectors();
715 } 768 }
716 769
@@ -760,25 +813,47 @@ namespace OpenSim.Region.Framework.Scenes
760 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 813 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
761 Dir_Vectors[4] = Vector3.UnitZ; //UP 814 Dir_Vectors[4] = Vector3.UnitZ; //UP
762 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 815 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
763 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 816 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
764 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 817 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
765 Dir_Vectors[7] = -Vector3.UnitX; //BACK 818 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
819 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
820 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
766 } 821 }
767 822
768 private Vector3[] GetWalkDirectionVectors() 823 private Vector3[] GetWalkDirectionVectors()
769 { 824 {
770 Vector3[] vector = new Vector3[9]; 825 Vector3[] vector = new Vector3[11];
771 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 826 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
772 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 827 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
773 vector[2] = Vector3.UnitY; //LEFT 828 vector[2] = Vector3.UnitY; //LEFT
774 vector[3] = -Vector3.UnitY; //RIGHT 829 vector[3] = -Vector3.UnitY; //RIGHT
775 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 830 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
776 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 831 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
777 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 832 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
778 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 833 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
779 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 834 vector[8] = Vector3.UnitY; //LEFT_NUDGE
835 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
836 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
780 return vector; 837 return vector;
781 } 838 }
839
840 private bool[] GetDirectionIsNudge()
841 {
842 bool[] isNudge = new bool[11];
843 isNudge[0] = false; //FORWARD
844 isNudge[1] = false; //BACK
845 isNudge[2] = false; //LEFT
846 isNudge[3] = false; //RIGHT
847 isNudge[4] = false; //UP
848 isNudge[5] = false; //DOWN
849 isNudge[6] = true; //FORWARD_NUDGE
850 isNudge[7] = true; //BACK_NUDGE
851 isNudge[8] = true; //LEFT_NUDGE
852 isNudge[9] = true; //RIGHT_NUDGE
853 isNudge[10] = true; //DOWN_Nudge
854 return isNudge;
855 }
856
782 857
783 #endregion 858 #endregion
784 859
@@ -821,7 +896,6 @@ namespace OpenSim.Region.Framework.Scenes
821 m_grouptitle = gm.GetGroupTitle(m_uuid); 896 m_grouptitle = gm.GetGroupTitle(m_uuid);
822 897
823 m_rootRegionHandle = m_scene.RegionInfo.RegionHandle; 898 m_rootRegionHandle = m_scene.RegionInfo.RegionHandle;
824
825 m_scene.SetRootAgentScene(m_uuid); 899 m_scene.SetRootAgentScene(m_uuid);
826 900
827 // Moved this from SendInitialData to ensure that m_appearance is initialized 901 // Moved this from SendInitialData to ensure that m_appearance is initialized
@@ -840,6 +914,52 @@ namespace OpenSim.Region.Framework.Scenes
840 pos.Y = crossedBorder.BorderLine.Z - 1; 914 pos.Y = crossedBorder.BorderLine.Z - 1;
841 } 915 }
842 916
917 //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
918 //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
919 //they'll bypass the landing point. But I can't think of any decent way of fixing this.
920 if (KnownChildRegionHandles.Count == 0)
921 {
922 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
923 if (land != null)
924 {
925 //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
926 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && UserLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
927 {
928 pos = land.LandData.UserLocation;
929 }
930 }
931 }
932
933 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
934 {
935 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
936
937 if (pos.X < 0)
938 {
939 emergencyPos.X = (int)Constants.RegionSize + pos.X;
940 if (!(pos.Y < 0))
941 emergencyPos.Y = pos.Y;
942 if (!(pos.Z < 0))
943 emergencyPos.Z = pos.Z;
944 }
945 if (pos.Y < 0)
946 {
947 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
948 if (!(pos.X < 0))
949 emergencyPos.X = pos.X;
950 if (!(pos.Z < 0))
951 emergencyPos.Z = pos.Z;
952 }
953 if (pos.Z < 0)
954 {
955 emergencyPos.Z = 128;
956 if (!(pos.Y < 0))
957 emergencyPos.Y = pos.Y;
958 if (!(pos.X < 0))
959 emergencyPos.X = pos.X;
960 }
961 }
962
843 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 963 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
844 { 964 {
845 m_log.WarnFormat( 965 m_log.WarnFormat(
@@ -972,9 +1092,10 @@ namespace OpenSim.Region.Framework.Scenes
972 public void Teleport(Vector3 pos) 1092 public void Teleport(Vector3 pos)
973 { 1093 {
974 bool isFlying = false; 1094 bool isFlying = false;
1095
975 if (m_physicsActor != null) 1096 if (m_physicsActor != null)
976 isFlying = m_physicsActor.Flying; 1097 isFlying = m_physicsActor.Flying;
977 1098
978 RemoveFromPhysicalScene(); 1099 RemoveFromPhysicalScene();
979 Velocity = Vector3.Zero; 1100 Velocity = Vector3.Zero;
980 AbsolutePosition = pos; 1101 AbsolutePosition = pos;
@@ -986,6 +1107,7 @@ namespace OpenSim.Region.Framework.Scenes
986 } 1107 }
987 1108
988 SendTerseUpdateToAllClients(); 1109 SendTerseUpdateToAllClients();
1110
989 } 1111 }
990 1112
991 public void TeleportWithMomentum(Vector3 pos) 1113 public void TeleportWithMomentum(Vector3 pos)
@@ -1099,7 +1221,6 @@ namespace OpenSim.Region.Framework.Scenes
1099 pos.Z = ground + 1.5f; 1221 pos.Z = ground + 1.5f;
1100 AbsolutePosition = pos; 1222 AbsolutePosition = pos;
1101 } 1223 }
1102
1103 m_isChildAgent = false; 1224 m_isChildAgent = false;
1104 bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1225 bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1105 MakeRootAgent(AbsolutePosition, m_flying); 1226 MakeRootAgent(AbsolutePosition, m_flying);
@@ -1198,6 +1319,7 @@ namespace OpenSim.Region.Framework.Scenes
1198 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1319 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1199 1320
1200 m_pos = m_LastFinitePos; 1321 m_pos = m_LastFinitePos;
1322
1201 if (!m_pos.IsFinite()) 1323 if (!m_pos.IsFinite())
1202 { 1324 {
1203 m_pos.X = 127f; 1325 m_pos.X = 127f;
@@ -1264,7 +1386,6 @@ namespace OpenSim.Region.Framework.Scenes
1264 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1386 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1265 } 1387 }
1266 } 1388 }
1267
1268 lock (scriptedcontrols) 1389 lock (scriptedcontrols)
1269 { 1390 {
1270 if (scriptedcontrols.Count > 0) 1391 if (scriptedcontrols.Count > 0)
@@ -1279,6 +1400,9 @@ namespace OpenSim.Region.Framework.Scenes
1279 1400
1280 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1401 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1281 { 1402 {
1403 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1404 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1405
1282 // TODO: This doesn't prevent the user from walking yet. 1406 // TODO: This doesn't prevent the user from walking yet.
1283 // Setting parent ID would fix this, if we knew what value 1407 // Setting parent ID would fix this, if we knew what value
1284 // to use. Or we could add a m_isSitting variable. 1408 // to use. Or we could add a m_isSitting variable.
@@ -1333,6 +1457,11 @@ namespace OpenSim.Region.Framework.Scenes
1333 update_rotation = true; 1457 update_rotation = true;
1334 } 1458 }
1335 1459
1460 //guilty until proven innocent..
1461 bool Nudging = true;
1462 //Basically, if there is at least one non-nudge control then we don't need
1463 //to worry about stopping the avatar
1464
1336 if (m_parentID == 0) 1465 if (m_parentID == 0)
1337 { 1466 {
1338 bool bAllowUpdateMoveToPosition = false; 1467 bool bAllowUpdateMoveToPosition = false;
@@ -1347,9 +1476,12 @@ namespace OpenSim.Region.Framework.Scenes
1347 else 1476 else
1348 dirVectors = Dir_Vectors; 1477 dirVectors = Dir_Vectors;
1349 1478
1350 // The fact that m_movementflag is a byte needs to be fixed 1479 bool[] isNudge = GetDirectionIsNudge();
1351 // it really should be a uint 1480
1352 uint nudgehack = 250; 1481
1482
1483
1484
1353 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1485 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1354 { 1486 {
1355 if (((uint)flags & (uint)DCF) != 0) 1487 if (((uint)flags & (uint)DCF) != 0)
@@ -1359,40 +1491,28 @@ namespace OpenSim.Region.Framework.Scenes
1359 try 1491 try
1360 { 1492 {
1361 agent_control_v3 += dirVectors[i]; 1493 agent_control_v3 += dirVectors[i];
1362 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1494 if (isNudge[i] == false)
1495 {
1496 Nudging = false;
1497 }
1363 } 1498 }
1364 catch (IndexOutOfRangeException) 1499 catch (IndexOutOfRangeException)
1365 { 1500 {
1366 // Why did I get this? 1501 // Why did I get this?
1367 } 1502 }
1368 1503
1369 if ((m_movementflag & (byte)(uint)DCF) == 0) 1504 if ((m_movementflag & (uint)DCF) == 0)
1370 { 1505 {
1371 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1372 {
1373 m_movementflag |= (byte)nudgehack;
1374 }
1375 m_movementflag += (byte)(uint)DCF; 1506 m_movementflag += (byte)(uint)DCF;
1376 update_movementflag = true; 1507 update_movementflag = true;
1377 } 1508 }
1378 } 1509 }
1379 else 1510 else
1380 { 1511 {
1381 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1512 if ((m_movementflag & (uint)DCF) != 0)
1382 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1383 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1384 ) // This or is for Nudge forward
1385 { 1513 {
1386 m_movementflag -= ((byte)(uint)DCF); 1514 m_movementflag -= (byte)(uint)DCF;
1387
1388 update_movementflag = true; 1515 update_movementflag = true;
1389 /*
1390 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1391 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1392 {
1393 m_log.Debug("Removed Hack flag");
1394 }
1395 */
1396 } 1516 }
1397 else 1517 else
1398 { 1518 {
@@ -1401,7 +1521,6 @@ namespace OpenSim.Region.Framework.Scenes
1401 } 1521 }
1402 i++; 1522 i++;
1403 } 1523 }
1404
1405 //Paupaw:Do Proper PID for Autopilot here 1524 //Paupaw:Do Proper PID for Autopilot here
1406 if (bResetMoveToPosition) 1525 if (bResetMoveToPosition)
1407 { 1526 {
@@ -1436,6 +1555,9 @@ namespace OpenSim.Region.Framework.Scenes
1436 // Ignore z component of vector 1555 // Ignore z component of vector
1437 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1556 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1438 LocalVectorToTarget2D.Normalize(); 1557 LocalVectorToTarget2D.Normalize();
1558
1559 //We're not nudging
1560 Nudging = false;
1439 agent_control_v3 += LocalVectorToTarget2D; 1561 agent_control_v3 += LocalVectorToTarget2D;
1440 1562
1441 // update avatar movement flags. the avatar coordinate system is as follows: 1563 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1524,13 +1646,13 @@ namespace OpenSim.Region.Framework.Scenes
1524 // m_log.DebugFormat( 1646 // m_log.DebugFormat(
1525 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1647 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1526 1648
1527 AddNewMovement(agent_control_v3, q); 1649 AddNewMovement(agent_control_v3, q, Nudging);
1528 1650
1529 1651
1530 } 1652 }
1531 } 1653 }
1532 1654
1533 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1655 if (update_movementflag && !SitGround)
1534 Animator.UpdateMovementAnimations(); 1656 Animator.UpdateMovementAnimations();
1535 1657
1536 m_scene.EventManager.TriggerOnClientMovement(this); 1658 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1545,7 +1667,6 @@ namespace OpenSim.Region.Framework.Scenes
1545 m_sitAtAutoTarget = false; 1667 m_sitAtAutoTarget = false;
1546 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1668 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1547 //proxy.PCode = (byte)PCode.ParticleSystem; 1669 //proxy.PCode = (byte)PCode.ParticleSystem;
1548
1549 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1670 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1550 proxyObjectGroup.AttachToScene(m_scene); 1671 proxyObjectGroup.AttachToScene(m_scene);
1551 1672
@@ -1587,7 +1708,7 @@ namespace OpenSim.Region.Framework.Scenes
1587 } 1708 }
1588 m_moveToPositionInProgress = true; 1709 m_moveToPositionInProgress = true;
1589 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1710 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1590 } 1711 }
1591 catch (Exception ex) 1712 catch (Exception ex)
1592 { 1713 {
1593 //Why did I get this error? 1714 //Why did I get this error?
@@ -1609,7 +1730,7 @@ namespace OpenSim.Region.Framework.Scenes
1609 Velocity = Vector3.Zero; 1730 Velocity = Vector3.Zero;
1610 SendFullUpdateToAllClients(); 1731 SendFullUpdateToAllClients();
1611 1732
1612 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1733 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1613 } 1734 }
1614 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1735 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1615 m_requestedSitTargetUUID = UUID.Zero; 1736 m_requestedSitTargetUUID = UUID.Zero;
@@ -1646,50 +1767,84 @@ namespace OpenSim.Region.Framework.Scenes
1646 1767
1647 if (m_parentID != 0) 1768 if (m_parentID != 0)
1648 { 1769 {
1649 m_log.Debug("StandupCode Executed"); 1770 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1650 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1651 if (part != null) 1771 if (part != null)
1652 { 1772 {
1773 part.TaskInventory.LockItemsForRead(true);
1653 TaskInventoryDictionary taskIDict = part.TaskInventory; 1774 TaskInventoryDictionary taskIDict = part.TaskInventory;
1654 if (taskIDict != null) 1775 if (taskIDict != null)
1655 { 1776 {
1656 lock (taskIDict) 1777 foreach (UUID taskID in taskIDict.Keys)
1657 { 1778 {
1658 foreach (UUID taskID in taskIDict.Keys) 1779 UnRegisterControlEventsToScript(LocalId, taskID);
1659 { 1780 taskIDict[taskID].PermsMask &= ~(
1660 UnRegisterControlEventsToScript(LocalId, taskID); 1781 2048 | //PERMISSION_CONTROL_CAMERA
1661 taskIDict[taskID].PermsMask &= ~( 1782 4); // PERMISSION_TAKE_CONTROLS
1662 2048 | //PERMISSION_CONTROL_CAMERA
1663 4); // PERMISSION_TAKE_CONTROLS
1664 }
1665 } 1783 }
1666
1667 } 1784 }
1785 part.TaskInventory.LockItemsForRead(false);
1668 // Reset sit target. 1786 // Reset sit target.
1669 if (part.GetAvatarOnSitTarget() == UUID) 1787 if (part.GetAvatarOnSitTarget() == UUID)
1670 part.SetAvatarOnSitTarget(UUID.Zero); 1788 part.SetAvatarOnSitTarget(UUID.Zero);
1671
1672 m_parentPosition = part.GetWorldPosition(); 1789 m_parentPosition = part.GetWorldPosition();
1673 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1790 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1674 } 1791 }
1792 // part.GetWorldRotation() is the rotation of the object being sat on
1793 // Rotation is the sittiing Av's rotation
1794
1795 Quaternion partRot;
1796// if (part.LinkNum == 1)
1797// { // Root prim of linkset
1798// partRot = part.ParentGroup.RootPart.RotationOffset;
1799// }
1800// else
1801// { // single or child prim
1802
1803// }
1804 if (part == null) //CW: Part may be gone. llDie() for example.
1805 {
1806 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1807 }
1808 else
1809 {
1810 partRot = part.GetWorldRotation();
1811 }
1675 1812
1813 Quaternion partIRot = Quaternion.Inverse(partRot);
1814
1815 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1816 Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
1817
1818
1676 if (m_physicsActor == null) 1819 if (m_physicsActor == null)
1677 { 1820 {
1678 AddToPhysicalScene(false); 1821 AddToPhysicalScene(false);
1679 } 1822 }
1680 1823 //CW: If the part isn't null then we can set the current position
1681 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1824 if (part != null)
1682 m_parentPosition = Vector3.Zero; 1825 {
1683 1826 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
1684 m_parentID = 0; 1827 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1828 part.IsOccupied = false;
1829 part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
1830 }
1831 else
1832 {
1833 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1834 AbsolutePosition = m_lastWorldPosition;
1835 }
1836
1837 m_parentPosition = Vector3.Zero;
1838 m_parentID = 0;
1839 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1685 SendFullUpdateToAllClients(); 1840 SendFullUpdateToAllClients();
1686 m_requestedSitTargetID = 0; 1841 m_requestedSitTargetID = 0;
1842
1687 if ((m_physicsActor != null) && (m_avHeight > 0)) 1843 if ((m_physicsActor != null) && (m_avHeight > 0))
1688 { 1844 {
1689 SetHeight(m_avHeight); 1845 SetHeight(m_avHeight);
1690 } 1846 }
1691 } 1847 }
1692
1693 Animator.TrySetMovementAnimation("STAND"); 1848 Animator.TrySetMovementAnimation("STAND");
1694 } 1849 }
1695 1850
@@ -1720,13 +1875,9 @@ namespace OpenSim.Region.Framework.Scenes
1720 Vector3 avSitOffSet = part.SitTargetPosition; 1875 Vector3 avSitOffSet = part.SitTargetPosition;
1721 Quaternion avSitOrientation = part.SitTargetOrientation; 1876 Quaternion avSitOrientation = part.SitTargetOrientation;
1722 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1877 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1723 1878 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1724 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1879 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1725 bool SitTargetisSet = 1880 if (SitTargetisSet && !SitTargetOccupied)
1726 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1727 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1728
1729 if (SitTargetisSet && SitTargetUnOccupied)
1730 { 1881 {
1731 //switch the target to this prim 1882 //switch the target to this prim
1732 return part; 1883 return part;
@@ -1740,84 +1891,156 @@ namespace OpenSim.Region.Framework.Scenes
1740 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 1891 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1741 { 1892 {
1742 bool autopilot = true; 1893 bool autopilot = true;
1894 Vector3 autopilotTarget = new Vector3();
1895 Quaternion sitOrientation = Quaternion.Identity;
1743 Vector3 pos = new Vector3(); 1896 Vector3 pos = new Vector3();
1744 Quaternion sitOrientation = pSitOrientation;
1745 Vector3 cameraEyeOffset = Vector3.Zero; 1897 Vector3 cameraEyeOffset = Vector3.Zero;
1746 Vector3 cameraAtOffset = Vector3.Zero; 1898 Vector3 cameraAtOffset = Vector3.Zero;
1747 bool forceMouselook = false; 1899 bool forceMouselook = false;
1748 1900
1749 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1901 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1750 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1902 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1751 if (part != null) 1903 if (part == null) return;
1752 { 1904
1753 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1905 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1754 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 1906 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1755 1907
1756 // Is a sit target available? 1908 // part is the prim to sit on
1757 Vector3 avSitOffSet = part.SitTargetPosition; 1909 // offset is the world-ref vector distance from that prim center to the click-spot
1758 Quaternion avSitOrientation = part.SitTargetOrientation; 1910 // UUID is the UUID of the Avatar doing the clicking
1759 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1911
1760 1912 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1761 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1913
1762 bool SitTargetisSet = 1914 // Is a sit target available?
1763 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1915 Vector3 avSitOffSet = part.SitTargetPosition;
1764 ( 1916 Quaternion avSitOrientation = part.SitTargetOrientation;
1765 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1917
1766 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 1918 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1767 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 1919 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1768 ) 1920 Quaternion partRot;
1769 )); 1921// if (part.LinkNum == 1)
1770 1922// { // Root prim of linkset
1771 if (SitTargetisSet && SitTargetUnOccupied) 1923// partRot = part.ParentGroup.RootPart.RotationOffset;
1772 { 1924// }
1773 part.SetAvatarOnSitTarget(UUID); 1925// else
1774 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1926// { // single or child prim
1775 sitOrientation = avSitOrientation; 1927 partRot = part.GetWorldRotation();
1776 autopilot = false; 1928// }
1777 } 1929 Quaternion partIRot = Quaternion.Inverse(partRot);
1778 1930//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1779 pos = part.AbsolutePosition + offset; 1931 // Sit analysis rewritten by KF 091125
1780 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 1932 if (SitTargetisSet) // scipted sit
1781 //{ 1933 {
1782 // offset = pos; 1934 if (!part.IsOccupied)
1783 //autopilot = false; 1935 {
1784 //} 1936//Console.WriteLine("Scripted, unoccupied");
1785 if (m_physicsActor != null) 1937 part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
1786 { 1938 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1787 // If we're not using the client autopilot, we're immediately warping the avatar to the location 1939 sitOrientation = avSitOrientation; // Change rotatione to the scripted one
1788 // We can remove the physicsActor until they stand up. 1940 OffsetRotation = avSitOrientation;
1789 m_sitAvatarHeight = m_physicsActor.Size.Z; 1941 autopilot = false; // Jump direct to scripted llSitPos()
1790 1942 }
1791 if (autopilot) 1943 else
1792 { 1944 {
1793 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1945//Console.WriteLine("Scripted, occupied");
1794 { 1946 return;
1795 autopilot = false; 1947 }
1948 }
1949 else // Not Scripted
1950 {
1951 if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
1952 {
1953 // large prim & offset, ignore if other Avs sitting
1954// offset.Z -= 0.05f;
1955 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
1956 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
1957
1958//Console.WriteLine(" offset ={0}", offset);
1959//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
1960//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
1961
1962 }
1963 else // small offset
1964 {
1965//Console.WriteLine("Small offset");
1966 if (!part.IsOccupied)
1967 {
1968 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
1969 autopilotTarget = part.AbsolutePosition;
1970//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
1971 }
1972 else return; // occupied small
1973 } // end large/small
1974 } // end Scripted/not
1975 cameraAtOffset = part.GetCameraAtOffset();
1976 cameraEyeOffset = part.GetCameraEyeOffset();
1977 forceMouselook = part.GetForceMouselook();
1978 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
1979 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
1796 1980
1797 RemoveFromPhysicalScene(); 1981 if (m_physicsActor != null)
1798 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 1982 {
1799 } 1983 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1800 } 1984 // We can remove the physicsActor until they stand up.
1801 else 1985 m_sitAvatarHeight = m_physicsActor.Size.Z;
1986 if (autopilot)
1987 { // its not a scripted sit
1988// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
1989 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
1802 { 1990 {
1991 autopilot = false; // close enough
1992 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
1993 Not using the part's position because returning the AV to the last known standing
1994 position is likely to be more friendly, isn't it? */
1803 RemoveFromPhysicalScene(); 1995 RemoveFromPhysicalScene();
1804 } 1996 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
1997 } // else the autopilot will get us close
1998 }
1999 else
2000 { // its a scripted sit
2001 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2002 I *am* using the part's position this time because we have no real idea how far away
2003 the avatar is from the sit target. */
2004 RemoveFromPhysicalScene();
1805 } 2005 }
1806
1807 cameraAtOffset = part.GetCameraAtOffset();
1808 cameraEyeOffset = part.GetCameraEyeOffset();
1809 forceMouselook = part.GetForceMouselook();
1810 } 2006 }
1811 2007 else return; // physactor is null!
1812 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 2008
1813 m_requestedSitTargetUUID = targetID; 2009 Vector3 offsetr; // = offset * partIRot;
2010 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
2011 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
2012 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
2013 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
2014 offsetr = offset * partIRot;
2015//
2016 // else
2017 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
2018 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
2019 // (offset * partRot);
2020 // }
2021
2022//Console.WriteLine(" ");
2023//Console.WriteLine("link number ={0}", part.LinkNum);
2024//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2025//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2026//Console.WriteLine("Click offst ={0}", offset);
2027//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2028//Console.WriteLine("offsetr ={0}", offsetr);
2029//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2030//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2031
2032 //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
2033 ControllingClient.SendSitResponse(part.ParentGroup.UUID, offsetr + part.OffsetPosition, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2034
2035 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1814 // This calls HandleAgentSit twice, once from here, and the client calls 2036 // This calls HandleAgentSit twice, once from here, and the client calls
1815 // HandleAgentSit itself after it gets to the location 2037 // HandleAgentSit itself after it gets to the location
1816 // It doesn't get to the location until we've moved them there though 2038 // It doesn't get to the location until we've moved them there though
1817 // which happens in HandleAgentSit :P 2039 // which happens in HandleAgentSit :P
1818 m_autopilotMoving = autopilot; 2040 m_autopilotMoving = autopilot;
1819 m_autoPilotTarget = pos; 2041 m_autoPilotTarget = autopilotTarget;
1820 m_sitAtAutoTarget = autopilot; 2042 m_sitAtAutoTarget = autopilot;
2043 m_initialSitTarget = autopilotTarget;
1821 if (!autopilot) 2044 if (!autopilot)
1822 HandleAgentSit(remoteClient, UUID); 2045 HandleAgentSit(remoteClient, UUID);
1823 } 2046 }
@@ -2112,47 +2335,122 @@ namespace OpenSim.Region.Framework.Scenes
2112 { 2335 {
2113 if (part != null) 2336 if (part != null)
2114 { 2337 {
2338//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2115 if (part.GetAvatarOnSitTarget() == UUID) 2339 if (part.GetAvatarOnSitTarget() == UUID)
2116 { 2340 {
2341//Console.WriteLine("Scripted Sit");
2342 // Scripted sit
2117 Vector3 sitTargetPos = part.SitTargetPosition; 2343 Vector3 sitTargetPos = part.SitTargetPosition;
2118 Quaternion sitTargetOrient = part.SitTargetOrientation; 2344 Quaternion sitTargetOrient = part.SitTargetOrientation;
2119
2120 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2121 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2122
2123 //Quaternion result = (sitTargetOrient * vq) * nq;
2124
2125 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2345 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2126 m_pos += SIT_TARGET_ADJUSTMENT; 2346 m_pos += SIT_TARGET_ADJUSTMENT;
2127 m_bodyRot = sitTargetOrient; 2347 m_bodyRot = sitTargetOrient;
2128 //Rotation = sitTargetOrient;
2129 m_parentPosition = part.AbsolutePosition; 2348 m_parentPosition = part.AbsolutePosition;
2130 2349 part.IsOccupied = true;
2131 //SendTerseUpdateToAllClients(); 2350 part.ParentGroup.AddAvatar(agentID);
2351Console.WriteLine("Scripted Sit ofset {0}", m_pos);
2132 } 2352 }
2133 else 2353 else
2134 { 2354 {
2135 m_pos -= part.AbsolutePosition; 2355 // if m_avUnscriptedSitPos is zero then Av sits above center
2356 // Else Av sits at m_avUnscriptedSitPos
2357
2358 // Non-scripted sit by Kitto Flora 21Nov09
2359 // Calculate angle of line from prim to Av
2360 Quaternion partIRot;
2361// if (part.LinkNum == 1)
2362// { // Root prim of linkset
2363// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2364// }
2365// else
2366// { // single or child prim
2367 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2368// }
2369 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2370 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2371 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2372 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2373 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2374 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2375 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2376 // Av sits at world euler <0,0, z>, translated by part rotation
2377 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2378
2136 m_parentPosition = part.AbsolutePosition; 2379 m_parentPosition = part.AbsolutePosition;
2137 } 2380 part.IsOccupied = true;
2381 part.ParentGroup.AddAvatar(agentID);
2382 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2383 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2384 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2385 m_avUnscriptedSitPos; // adds click offset, if any
2386 //Set up raytrace to find top surface of prim
2387 Vector3 size = part.Scale;
2388 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2389 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2390 Vector3 down = new Vector3(0f, 0f, -1f);
2391//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2392 m_scene.PhysicsScene.RaycastWorld(
2393 start, // Vector3 position,
2394 down, // Vector3 direction,
2395 mag, // float length,
2396 SitAltitudeCallback); // retMethod
2397 } // end scripted/not
2138 } 2398 }
2139 else 2399 else // no Av
2140 { 2400 {
2141 return; 2401 return;
2142 } 2402 }
2143 } 2403 }
2144 m_parentID = m_requestedSitTargetID; 2404
2405 //We want our offsets to reference the root prim, not the child we may have sat on
2406 if (!part.IsRoot)
2407 {
2408 m_parentID = part.ParentGroup.RootPart.LocalId;
2409 m_pos += part.OffsetPosition;
2410 }
2411 else
2412 {
2413 m_parentID = m_requestedSitTargetID;
2414 }
2145 2415
2146 Velocity = Vector3.Zero; 2416 Velocity = Vector3.Zero;
2147 RemoveFromPhysicalScene(); 2417 RemoveFromPhysicalScene();
2148 2418
2149 Animator.TrySetMovementAnimation(sitAnimation); 2419 Animator.TrySetMovementAnimation(sitAnimation);
2150 SendFullUpdateToAllClients(); 2420 SendFullUpdateToAllClients();
2151 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2152 // So we're also sending a terse update (which has avatar rotation)
2153 // [Update] We do now.
2154 //SendTerseUpdateToAllClients();
2155 } 2421 }
2422
2423 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2424 {
2425 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2426 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2427 if(hitYN)
2428 {
2429 // m_pos = Av offset from prim center to make look like on center
2430 // m_parentPosition = Actual center pos of prim
2431 // collisionPoint = spot on prim where we want to sit
2432 // collisionPoint.Z = global sit surface height
2433 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2434 Quaternion partIRot;
2435// if (part.LinkNum == 1)
2436/// { // Root prim of linkset
2437// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2438// }
2439// else
2440// { // single or child prim
2441 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2442// }
2443 if (m_initialSitTarget != null)
2444 {
2445 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2446 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2447 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2448 m_pos += offset;
2449 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2450 }
2451
2452 }
2453 } // End SitAltitudeCallback KF.
2156 2454
2157 /// <summary> 2455 /// <summary>
2158 /// Event handler for the 'Always run' setting on the client 2456 /// Event handler for the 'Always run' setting on the client
@@ -2182,7 +2480,7 @@ namespace OpenSim.Region.Framework.Scenes
2182 /// </summary> 2480 /// </summary>
2183 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2481 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2184 /// <param name="rotation">The direction in which this avatar should now face. 2482 /// <param name="rotation">The direction in which this avatar should now face.
2185 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2483 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2186 { 2484 {
2187 if (m_isChildAgent) 2485 if (m_isChildAgent)
2188 { 2486 {
@@ -2223,10 +2521,11 @@ namespace OpenSim.Region.Framework.Scenes
2223 Rotation = rotation; 2521 Rotation = rotation;
2224 Vector3 direc = vec * rotation; 2522 Vector3 direc = vec * rotation;
2225 direc.Normalize(); 2523 direc.Normalize();
2524 PhysicsActor actor = m_physicsActor;
2525 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2226 2526
2227 direc *= 0.03f * 128f * m_speedModifier; 2527 direc *= 0.03f * 128f * m_speedModifier;
2228 2528
2229 PhysicsActor actor = m_physicsActor;
2230 if (actor != null) 2529 if (actor != null)
2231 { 2530 {
2232 if (actor.Flying) 2531 if (actor.Flying)
@@ -2248,18 +2547,25 @@ namespace OpenSim.Region.Framework.Scenes
2248 { 2547 {
2249 if (direc.Z > 2.0f) 2548 if (direc.Z > 2.0f)
2250 { 2549 {
2251 direc.Z *= 3.0f; 2550 if(m_animator.m_animTickJump == -1)
2252 2551 {
2253 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2552 direc.Z *= 3.0f; // jump
2254 Animator.TrySetMovementAnimation("PREJUMP"); 2553 }
2255 Animator.TrySetMovementAnimation("JUMP"); 2554 else
2555 {
2556 direc.Z *= 0.1f; // prejump
2557 }
2558 /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
2559 Animator.TrySetMovementAnimation("PREJUMP");
2560 Animator.TrySetMovementAnimation("JUMP");
2561 */
2256 } 2562 }
2257 } 2563 }
2258 } 2564 }
2259 2565
2260 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2566 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2261 m_forceToApply = direc; 2567 m_forceToApply = direc;
2262 2568 m_isNudging = Nudging;
2263 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2569 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2264 } 2570 }
2265 2571
@@ -2274,7 +2580,7 @@ namespace OpenSim.Region.Framework.Scenes
2274 const float POSITION_TOLERANCE = 0.05f; 2580 const float POSITION_TOLERANCE = 0.05f;
2275 //const int TIME_MS_TOLERANCE = 3000; 2581 //const int TIME_MS_TOLERANCE = 3000;
2276 2582
2277 SendPrimUpdates(); 2583
2278 2584
2279 if (m_isChildAgent == false) 2585 if (m_isChildAgent == false)
2280 { 2586 {
@@ -2304,6 +2610,9 @@ namespace OpenSim.Region.Framework.Scenes
2304 CheckForBorderCrossing(); 2610 CheckForBorderCrossing();
2305 CheckForSignificantMovement(); // sends update to the modules. 2611 CheckForSignificantMovement(); // sends update to the modules.
2306 } 2612 }
2613
2614 //Sending prim updates AFTER the avatar terse updates are sent
2615 SendPrimUpdates();
2307 } 2616 }
2308 2617
2309 #endregion 2618 #endregion
@@ -3076,6 +3385,7 @@ namespace OpenSim.Region.Framework.Scenes
3076 m_callbackURI = cAgent.CallbackURI; 3385 m_callbackURI = cAgent.CallbackURI;
3077 3386
3078 m_pos = cAgent.Position; 3387 m_pos = cAgent.Position;
3388
3079 m_velocity = cAgent.Velocity; 3389 m_velocity = cAgent.Velocity;
3080 m_CameraCenter = cAgent.Center; 3390 m_CameraCenter = cAgent.Center;
3081 //m_avHeight = cAgent.Size.Z; 3391 //m_avHeight = cAgent.Size.Z;
@@ -3165,14 +3475,25 @@ namespace OpenSim.Region.Framework.Scenes
3165 { 3475 {
3166 if (m_forceToApply.HasValue) 3476 if (m_forceToApply.HasValue)
3167 { 3477 {
3168 Vector3 force = m_forceToApply.Value;
3169 3478
3479 Vector3 force = m_forceToApply.Value;
3170 m_updateflag = true; 3480 m_updateflag = true;
3171// movementvector = force;
3172 Velocity = force; 3481 Velocity = force;
3173 3482
3174 m_forceToApply = null; 3483 m_forceToApply = null;
3175 } 3484 }
3485 else
3486 {
3487 if (m_isNudging)
3488 {
3489 Vector3 force = Vector3.Zero;
3490
3491 m_updateflag = true;
3492 Velocity = force;
3493 m_isNudging = false;
3494 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3495 }
3496 }
3176 } 3497 }
3177 3498
3178 public override void SetText(string text, Vector3 color, double alpha) 3499 public override void SetText(string text, Vector3 color, double alpha)
@@ -3223,18 +3544,29 @@ namespace OpenSim.Region.Framework.Scenes
3223 { 3544 {
3224 if (e == null) 3545 if (e == null)
3225 return; 3546 return;
3226 3547
3227 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3548 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3228 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3229 // as of this comment the interval is set in AddToPhysicalScene 3549 // as of this comment the interval is set in AddToPhysicalScene
3230 if (Animator!=null) 3550 if (Animator!=null)
3231 Animator.UpdateMovementAnimations(); 3551 {
3552 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3553 { // else its will lock out other animation changes, like ground sit.
3554 Animator.UpdateMovementAnimations();
3555 m_updateCount--;
3556 }
3557 }
3232 3558
3233 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3559 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3234 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3560 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3235 3561
3236 CollisionPlane = Vector4.UnitW; 3562 CollisionPlane = Vector4.UnitW;
3237 3563
3564 if (m_lastColCount != coldata.Count)
3565 {
3566 m_updateCount = UPDATE_COUNT;
3567 m_lastColCount = coldata.Count;
3568 }
3569
3238 if (coldata.Count != 0 && Animator != null) 3570 if (coldata.Count != 0 && Animator != null)
3239 { 3571 {
3240 switch (Animator.CurrentMovementAnimation) 3572 switch (Animator.CurrentMovementAnimation)
@@ -3264,6 +3596,145 @@ namespace OpenSim.Region.Framework.Scenes
3264 } 3596 }
3265 } 3597 }
3266 3598
3599 List<uint> thisHitColliders = new List<uint>();
3600 List<uint> endedColliders = new List<uint>();
3601 List<uint> startedColliders = new List<uint>();
3602
3603 foreach (uint localid in coldata.Keys)
3604 {
3605 thisHitColliders.Add(localid);
3606 if (!m_lastColliders.Contains(localid))
3607 {
3608 startedColliders.Add(localid);
3609 }
3610 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3611 }
3612
3613 // calculate things that ended colliding
3614 foreach (uint localID in m_lastColliders)
3615 {
3616 if (!thisHitColliders.Contains(localID))
3617 {
3618 endedColliders.Add(localID);
3619 }
3620 }
3621 //add the items that started colliding this time to the last colliders list.
3622 foreach (uint localID in startedColliders)
3623 {
3624 m_lastColliders.Add(localID);
3625 }
3626 // remove things that ended colliding from the last colliders list
3627 foreach (uint localID in endedColliders)
3628 {
3629 m_lastColliders.Remove(localID);
3630 }
3631
3632 // do event notification
3633 if (startedColliders.Count > 0)
3634 {
3635 ColliderArgs StartCollidingMessage = new ColliderArgs();
3636 List<DetectedObject> colliding = new List<DetectedObject>();
3637 foreach (uint localId in startedColliders)
3638 {
3639 if (localId == 0)
3640 continue;
3641
3642 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3643 string data = "";
3644 if (obj != null)
3645 {
3646 DetectedObject detobj = new DetectedObject();
3647 detobj.keyUUID = obj.UUID;
3648 detobj.nameStr = obj.Name;
3649 detobj.ownerUUID = obj.OwnerID;
3650 detobj.posVector = obj.AbsolutePosition;
3651 detobj.rotQuat = obj.GetWorldRotation();
3652 detobj.velVector = obj.Velocity;
3653 detobj.colliderType = 0;
3654 detobj.groupUUID = obj.GroupID;
3655 colliding.Add(detobj);
3656 }
3657 }
3658
3659 if (colliding.Count > 0)
3660 {
3661 StartCollidingMessage.Colliders = colliding;
3662
3663 foreach (SceneObjectGroup att in Attachments)
3664 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3665 }
3666 }
3667
3668 if (endedColliders.Count > 0)
3669 {
3670 ColliderArgs EndCollidingMessage = new ColliderArgs();
3671 List<DetectedObject> colliding = new List<DetectedObject>();
3672 foreach (uint localId in endedColliders)
3673 {
3674 if (localId == 0)
3675 continue;
3676
3677 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3678 string data = "";
3679 if (obj != null)
3680 {
3681 DetectedObject detobj = new DetectedObject();
3682 detobj.keyUUID = obj.UUID;
3683 detobj.nameStr = obj.Name;
3684 detobj.ownerUUID = obj.OwnerID;
3685 detobj.posVector = obj.AbsolutePosition;
3686 detobj.rotQuat = obj.GetWorldRotation();
3687 detobj.velVector = obj.Velocity;
3688 detobj.colliderType = 0;
3689 detobj.groupUUID = obj.GroupID;
3690 colliding.Add(detobj);
3691 }
3692 }
3693
3694 if (colliding.Count > 0)
3695 {
3696 EndCollidingMessage.Colliders = colliding;
3697
3698 foreach (SceneObjectGroup att in Attachments)
3699 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
3700 }
3701 }
3702
3703 if (thisHitColliders.Count > 0)
3704 {
3705 ColliderArgs CollidingMessage = new ColliderArgs();
3706 List<DetectedObject> colliding = new List<DetectedObject>();
3707 foreach (uint localId in thisHitColliders)
3708 {
3709 if (localId == 0)
3710 continue;
3711
3712 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3713 string data = "";
3714 if (obj != null)
3715 {
3716 DetectedObject detobj = new DetectedObject();
3717 detobj.keyUUID = obj.UUID;
3718 detobj.nameStr = obj.Name;
3719 detobj.ownerUUID = obj.OwnerID;
3720 detobj.posVector = obj.AbsolutePosition;
3721 detobj.rotQuat = obj.GetWorldRotation();
3722 detobj.velVector = obj.Velocity;
3723 detobj.colliderType = 0;
3724 detobj.groupUUID = obj.GroupID;
3725 colliding.Add(detobj);
3726 }
3727 }
3728
3729 if (colliding.Count > 0)
3730 {
3731 CollidingMessage.Colliders = colliding;
3732
3733 foreach (SceneObjectGroup att in Attachments)
3734 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
3735 }
3736 }
3737
3267 if (m_invulnerable) 3738 if (m_invulnerable)
3268 return; 3739 return;
3269 3740
@@ -3438,7 +3909,10 @@ namespace OpenSim.Region.Framework.Scenes
3438 m_scene = scene; 3909 m_scene = scene;
3439 3910
3440 RegisterToEvents(); 3911 RegisterToEvents();
3441 3912 if (m_controllingClient != null)
3913 {
3914 m_controllingClient.ProcessPendingPackets();
3915 }
3442 /* 3916 /*
3443 AbsolutePosition = client.StartPos; 3917 AbsolutePosition = client.StartPos;
3444 3918
@@ -3669,6 +4143,39 @@ namespace OpenSim.Region.Framework.Scenes
3669 return; 4143 return;
3670 } 4144 }
3671 4145
4146 XmlDocument doc = new XmlDocument();
4147 string stateData = String.Empty;
4148
4149 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
4150 if (attServ != null)
4151 {
4152 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
4153 stateData = attServ.Get(ControllingClient.AgentId.ToString());
4154 if (stateData != String.Empty)
4155 {
4156 try
4157 {
4158 doc.LoadXml(stateData);
4159 }
4160 catch { }
4161 }
4162 }
4163
4164 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
4165
4166 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
4167 if (nodes.Count > 0)
4168 {
4169 foreach (XmlNode n in nodes)
4170 {
4171 XmlElement elem = (XmlElement)n;
4172 string itemID = elem.GetAttribute("ItemID");
4173 string xml = elem.InnerXml;
4174
4175 itemData[new UUID(itemID)] = xml;
4176 }
4177 }
4178
3672 List<int> attPoints = m_appearance.GetAttachedPoints(); 4179 List<int> attPoints = m_appearance.GetAttachedPoints();
3673 foreach (int p in attPoints) 4180 foreach (int p in attPoints)
3674 { 4181 {
@@ -3688,9 +4195,26 @@ namespace OpenSim.Region.Framework.Scenes
3688 4195
3689 try 4196 try
3690 { 4197 {
3691 // Rez from inventory 4198 string xmlData;
3692 UUID asset 4199 XmlDocument d = new XmlDocument();
3693 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); 4200 UUID asset;
4201 if (itemData.TryGetValue(itemID, out xmlData))
4202 {
4203 d.LoadXml(xmlData);
4204 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
4205
4206 // Rez from inventory
4207 asset
4208 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
4209
4210 }
4211 else
4212 {
4213 // Rez from inventory (with a null doc to let
4214 // CHANGED_OWNER happen)
4215 asset
4216 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
4217 }
3694 4218
3695 m_log.InfoFormat( 4219 m_log.InfoFormat(
3696 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", 4220 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})",
@@ -3727,5 +4251,16 @@ namespace OpenSim.Region.Framework.Scenes
3727 m_reprioritization_called = false; 4251 m_reprioritization_called = false;
3728 } 4252 }
3729 } 4253 }
4254
4255 private Vector3 Quat2Euler(Quaternion rot){
4256 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4257 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4258 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4259 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4260 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4261 return(new Vector3(x,y,z));
4262 }
4263
4264
3730 } 4265 }
3731} 4266}