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.cs39
-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.cs869
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs211
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs736
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs888
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs168
21 files changed, 2478 insertions, 966 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index 2af2548..9fe6d96 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 9db2e41..e060c05 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 6e73fe9..c77efc7 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 {
@@ -913,8 +928,12 @@ namespace OpenSim.Region.Framework.Scenes
913 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 928 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
914 { 929 {
915 SceneObjectPart part = GetSceneObjectPart(localID); 930 SceneObjectPart part = GetSceneObjectPart(localID);
916 SceneObjectGroup group = part.ParentGroup; 931 SceneObjectGroup group = null;
917 if (group != null) 932 if (part != null)
933 {
934 group = part.ParentGroup;
935 }
936 if (part != null && group != null)
918 { 937 {
919 TaskInventoryItem item = group.GetInventoryItem(localID, itemID); 938 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
920 if (item == null) 939 if (item == null)
@@ -1442,7 +1461,7 @@ namespace OpenSim.Region.Framework.Scenes
1442 return; 1461 return;
1443 1462
1444 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1463 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1445 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1464 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1446 remoteClient.AgentId); 1465 remoteClient.AgentId);
1447 AssetService.Store(asset); 1466 AssetService.Store(asset);
1448 1467
@@ -1668,15 +1687,21 @@ namespace OpenSim.Region.Framework.Scenes
1668 } 1687 }
1669 else 1688 else
1670 { 1689 {
1671 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1690 if (action == DeRezAction.TakeCopy)
1691 {
1692 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1693 permissionToTakeCopy = false;
1694 }
1695 else
1696 {
1672 permissionToTakeCopy = false; 1697 permissionToTakeCopy = false;
1698 }
1673 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1699 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1674 permissionToTake = false; 1700 permissionToTake = false;
1675 1701
1676 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1702 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1677 permissionToDelete = false; 1703 permissionToDelete = false;
1678 } 1704 }
1679
1680 } 1705 }
1681 1706
1682 // Handle god perms 1707 // Handle god perms
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index b0f4ac0..daad3d2 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
@@ -607,6 +621,8 @@ namespace OpenSim.Region.Framework.Scenes
607 621
608 // Load region settings 622 // Load region settings
609 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID); 623 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID);
624 m_regInfo.WindlightSettings = m_storageManager.DataStore.LoadRegionWindlightSettings(m_regInfo.RegionID);
625
610 if (m_storageManager.EstateDataStore != null) 626 if (m_storageManager.EstateDataStore != null)
611 { 627 {
612 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID, false); 628 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -709,7 +725,7 @@ namespace OpenSim.Region.Framework.Scenes
709 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 725 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
710 // TODO: Change default to true once the feature is supported 726 // TODO: Change default to true once the feature is supported
711 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 727 m_usePreJump = startupConfig.GetBoolean("enableprejump", false);
712 728 m_usePreJump = true; // Above line fails!?
713 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 729 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
714 if (RegionInfo.NonphysPrimMax > 0) 730 if (RegionInfo.NonphysPrimMax > 0)
715 { 731 {
@@ -1023,6 +1039,15 @@ namespace OpenSim.Region.Framework.Scenes
1023 /// <param name="seconds">float indicating duration before restart.</param> 1039 /// <param name="seconds">float indicating duration before restart.</param>
1024 public virtual void Restart(float seconds) 1040 public virtual void Restart(float seconds)
1025 { 1041 {
1042 Restart(seconds, true);
1043 }
1044
1045 /// <summary>
1046 /// Given float seconds, this will restart the region. showDialog will optionally alert the users.
1047 /// </summary>
1048 /// <param name="seconds">float indicating duration before restart.</param>
1049 public virtual void Restart(float seconds, bool showDialog)
1050 {
1026 // notifications are done in 15 second increments 1051 // notifications are done in 15 second increments
1027 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request 1052 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request
1028 // It's a 'Cancel restart' request. 1053 // It's a 'Cancel restart' request.
@@ -1043,8 +1068,11 @@ namespace OpenSim.Region.Framework.Scenes
1043 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed); 1068 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed);
1044 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes"); 1069 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes");
1045 m_restartTimer.Start(); 1070 m_restartTimer.Start();
1046 m_dialogModule.SendNotificationToUsersInRegion( 1071 if (showDialog)
1072 {
1073 m_dialogModule.SendNotificationToUsersInRegion(
1047 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0))); 1074 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0)));
1075 }
1048 } 1076 }
1049 } 1077 }
1050 1078
@@ -1402,16 +1430,16 @@ namespace OpenSim.Region.Framework.Scenes
1402 // Check if any objects have reached their targets 1430 // Check if any objects have reached their targets
1403 CheckAtTargets(); 1431 CheckAtTargets();
1404 1432
1405 // Update SceneObjectGroups that have scheduled themselves for updates
1406 // Objects queue their updates onto all scene presences
1407 if (m_frame % m_update_objects == 0)
1408 m_sceneGraph.UpdateObjectGroups();
1409
1410 // Run through all ScenePresences looking for updates 1433 // Run through all ScenePresences looking for updates
1411 // Presence updates and queued object updates for each presence are sent to clients 1434 // Presence updates and queued object updates for each presence are sent to clients
1412 if (m_frame % m_update_presences == 0) 1435 if (m_frame % m_update_presences == 0)
1413 m_sceneGraph.UpdatePresences(); 1436 m_sceneGraph.UpdatePresences();
1414 1437
1438 // Update SceneObjectGroups that have scheduled themselves for updates
1439 // Objects queue their updates onto all scene presences
1440 if (m_frame % m_update_objects == 0)
1441 m_sceneGraph.UpdateObjectGroups();
1442
1415 if (m_frame % m_update_coarse_locations == 0) 1443 if (m_frame % m_update_coarse_locations == 0)
1416 { 1444 {
1417 List<Vector3> coarseLocations; 1445 List<Vector3> coarseLocations;
@@ -1740,6 +1768,7 @@ namespace OpenSim.Region.Framework.Scenes
1740 public void StoreWindlightProfile(RegionLightShareData wl) 1768 public void StoreWindlightProfile(RegionLightShareData wl)
1741 { 1769 {
1742 m_regInfo.WindlightSettings = wl; 1770 m_regInfo.WindlightSettings = wl;
1771 wl.Save();
1743 m_storageManager.DataStore.StoreRegionWindlightSettings(wl); 1772 m_storageManager.DataStore.StoreRegionWindlightSettings(wl);
1744 m_eventManager.TriggerOnSaveNewWindlightProfile(); 1773 m_eventManager.TriggerOnSaveNewWindlightProfile();
1745 } 1774 }
@@ -1918,14 +1947,24 @@ namespace OpenSim.Region.Framework.Scenes
1918 /// <returns></returns> 1947 /// <returns></returns>
1919 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1948 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1920 { 1949 {
1950
1951 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1952 Vector3 wpos = Vector3.Zero;
1953 // Check for water surface intersection from above
1954 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1955 {
1956 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1957 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1958 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1959 wpos.Z = wheight;
1960 }
1961
1921 Vector3 pos = Vector3.Zero; 1962 Vector3 pos = Vector3.Zero;
1922 if (RayEndIsIntersection == (byte)1) 1963 if (RayEndIsIntersection == (byte)1)
1923 { 1964 {
1924 pos = RayEnd; 1965 pos = RayEnd;
1925 return pos;
1926 } 1966 }
1927 1967 else if (RayTargetID != UUID.Zero)
1928 if (RayTargetID != UUID.Zero)
1929 { 1968 {
1930 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1969 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1931 1970
@@ -1947,7 +1986,7 @@ namespace OpenSim.Region.Framework.Scenes
1947 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1986 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1948 1987
1949 // Un-comment out the following line to Get Raytrace results printed to the console. 1988 // Un-comment out the following line to Get Raytrace results printed to the console.
1950 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1989 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1951 float ScaleOffset = 0.5f; 1990 float ScaleOffset = 0.5f;
1952 1991
1953 // If we hit something 1992 // If we hit something
@@ -1970,13 +2009,10 @@ namespace OpenSim.Region.Framework.Scenes
1970 //pos.Z -= 0.25F; 2009 //pos.Z -= 0.25F;
1971 2010
1972 } 2011 }
1973
1974 return pos;
1975 } 2012 }
1976 else 2013 else
1977 { 2014 {
1978 // We don't have a target here, so we're going to raytrace all the objects in the scene. 2015 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1979
1980 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 2016 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1981 2017
1982 // Un-comment the following line to print the raytrace results to the console. 2018 // Un-comment the following line to print the raytrace results to the console.
@@ -1985,13 +2021,12 @@ namespace OpenSim.Region.Framework.Scenes
1985 if (ei.HitTF) 2021 if (ei.HitTF)
1986 { 2022 {
1987 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 2023 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1988 } else 2024 }
2025 else
1989 { 2026 {
1990 // fall back to our stupid functionality 2027 // fall back to our stupid functionality
1991 pos = RayEnd; 2028 pos = RayEnd;
1992 } 2029 }
1993
1994 return pos;
1995 } 2030 }
1996 } 2031 }
1997 else 2032 else
@@ -2002,8 +2037,12 @@ namespace OpenSim.Region.Framework.Scenes
2002 //increase height so its above the ground. 2037 //increase height so its above the ground.
2003 //should be getting the normal of the ground at the rez point and using that? 2038 //should be getting the normal of the ground at the rez point and using that?
2004 pos.Z += scale.Z / 2f; 2039 pos.Z += scale.Z / 2f;
2005 return pos; 2040// return pos;
2006 } 2041 }
2042
2043 // check against posible water intercept
2044 if (wpos.Z > pos.Z) pos = wpos;
2045 return pos;
2007 } 2046 }
2008 2047
2009 2048
@@ -2136,13 +2175,22 @@ namespace OpenSim.Region.Framework.Scenes
2136 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 2175 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
2137 { 2176 {
2138 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); 2177 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates);
2139 } 2178 }
2140 2179
2141 /// <summary> 2180 /// <summary>
2142 /// Delete every object from the scene. This does not include attachments worn by avatars. 2181 /// Delete every object from the scene. This does not include attachments worn by avatars.
2143 /// </summary> 2182 /// </summary>
2144 public void DeleteAllSceneObjects() 2183 public void DeleteAllSceneObjects()
2145 { 2184 {
2185 DeleteAllSceneObjects(false);
2186 }
2187
2188 /// <summary>
2189 /// Delete every object from the scene. This does not include attachments worn by avatars.
2190 /// </summary>
2191 public void DeleteAllSceneObjects(bool exceptNoCopy)
2192 {
2193 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2146 lock (Entities) 2194 lock (Entities)
2147 { 2195 {
2148 ICollection<EntityBase> entities = new List<EntityBase>(Entities); 2196 ICollection<EntityBase> entities = new List<EntityBase>(Entities);
@@ -2152,11 +2200,24 @@ namespace OpenSim.Region.Framework.Scenes
2152 if (e is SceneObjectGroup) 2200 if (e is SceneObjectGroup)
2153 { 2201 {
2154 SceneObjectGroup sog = (SceneObjectGroup)e; 2202 SceneObjectGroup sog = (SceneObjectGroup)e;
2155 if (!sog.IsAttachment) 2203 if (sog != null && !sog.IsAttachment)
2156 DeleteSceneObject((SceneObjectGroup)e, false); 2204 {
2205 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2206 {
2207 DeleteSceneObject((SceneObjectGroup)e, false);
2208 }
2209 else
2210 {
2211 toReturn.Add((SceneObjectGroup)e);
2212 }
2213 }
2157 } 2214 }
2158 } 2215 }
2159 } 2216 }
2217 if (toReturn.Count > 0)
2218 {
2219 returnObjects(toReturn.ToArray(), UUID.Zero);
2220 }
2160 } 2221 }
2161 2222
2162 /// <summary> 2223 /// <summary>
@@ -3194,6 +3255,16 @@ namespace OpenSim.Region.Framework.Scenes
3194 /// <param name="flags"></param> 3255 /// <param name="flags"></param>
3195 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3256 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3196 { 3257 {
3258 //Add half the avatar's height so that the user doesn't fall through prims
3259 ScenePresence presence;
3260 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3261 {
3262 if (presence.Appearance != null)
3263 {
3264 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3265 }
3266 }
3267
3197 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3268 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3198 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3269 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3199 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3270 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3581,6 +3652,8 @@ namespace OpenSim.Region.Framework.Scenes
3581 } 3652 }
3582 } 3653 }
3583 // Honor parcel landing type and position. 3654 // Honor parcel landing type and position.
3655 /*
3656 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3584 if (land != null) 3657 if (land != null)
3585 { 3658 {
3586 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3659 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3588,6 +3661,7 @@ namespace OpenSim.Region.Framework.Scenes
3588 agent.startpos = land.LandData.UserLocation; 3661 agent.startpos = land.LandData.UserLocation;
3589 } 3662 }
3590 } 3663 }
3664 */// This is now handled properly in ScenePresence.MakeRootAgent
3591 } 3665 }
3592 3666
3593 return true; 3667 return true;
@@ -3950,12 +4024,22 @@ namespace OpenSim.Region.Framework.Scenes
3950 return false; 4024 return false;
3951 } 4025 }
3952 4026
4027 public bool IncomingCloseAgent(UUID agentID)
4028 {
4029 return IncomingCloseAgent(agentID, false);
4030 }
4031
4032 public bool IncomingCloseChildAgent(UUID agentID)
4033 {
4034 return IncomingCloseAgent(agentID, true);
4035 }
4036
3953 /// <summary> 4037 /// <summary>
3954 /// Tell a single agent to disconnect from the region. 4038 /// Tell a single agent to disconnect from the region.
3955 /// </summary> 4039 /// </summary>
3956 /// <param name="regionHandle"></param>
3957 /// <param name="agentID"></param> 4040 /// <param name="agentID"></param>
3958 public bool IncomingCloseAgent(UUID agentID) 4041 /// <param name="childOnly"></param>
4042 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3959 { 4043 {
3960 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4044 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3961 4045
@@ -3967,7 +4051,7 @@ namespace OpenSim.Region.Framework.Scenes
3967 { 4051 {
3968 m_sceneGraph.removeUserCount(false); 4052 m_sceneGraph.removeUserCount(false);
3969 } 4053 }
3970 else 4054 else if (!childOnly)
3971 { 4055 {
3972 m_sceneGraph.removeUserCount(true); 4056 m_sceneGraph.removeUserCount(true);
3973 } 4057 }
@@ -3983,9 +4067,12 @@ namespace OpenSim.Region.Framework.Scenes
3983 } 4067 }
3984 else 4068 else
3985 presence.ControllingClient.SendShutdownConnectionNotice(); 4069 presence.ControllingClient.SendShutdownConnectionNotice();
4070 presence.ControllingClient.Close(false);
4071 }
4072 else if (!childOnly)
4073 {
4074 presence.ControllingClient.Close(true);
3986 } 4075 }
3987
3988 presence.ControllingClient.Close();
3989 return true; 4076 return true;
3990 } 4077 }
3991 4078
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 40332a6..a36800b 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 9a01a28..abb4de6 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 1ca390a..7053c02 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 }
@@ -221,7 +349,21 @@ namespace OpenSim.Region.Framework.Scenes
221 public virtual Quaternion Rotation 349 public virtual Quaternion Rotation
222 { 350 {
223 get { return m_rotation; } 351 get { return m_rotation; }
224 set { m_rotation = value; } 352 set {
353 lockPartsForRead(true);
354 try
355 {
356 foreach(SceneObjectPart p in m_parts.Values)
357 {
358 p.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
359 }
360 }
361 finally
362 {
363 lockPartsForRead(false);
364 }
365 m_rotation = value;
366 }
225 } 367 }
226 368
227 public Quaternion GroupRotation 369 public Quaternion GroupRotation
@@ -258,13 +400,16 @@ namespace OpenSim.Region.Framework.Scenes
258 set 400 set
259 { 401 {
260 m_regionHandle = value; 402 m_regionHandle = value;
261 lock (m_parts) 403 lockPartsForRead(true);
262 { 404 {
263 foreach (SceneObjectPart part in m_parts.Values) 405 foreach (SceneObjectPart part in m_parts.Values)
264 { 406 {
407
265 part.RegionHandle = m_regionHandle; 408 part.RegionHandle = m_regionHandle;
409
266 } 410 }
267 } 411 }
412 lockPartsForRead(false);
268 } 413 }
269 } 414 }
270 415
@@ -298,6 +443,12 @@ namespace OpenSim.Region.Framework.Scenes
298 { 443 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 444 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 445 }
446
447 lockPartsForRead(true);
448 foreach (SceneObjectPart part in m_parts.Values)
449 {
450 part.IgnoreUndoUpdate = true;
451 }
301 if (RootPart.GetStatusSandbox()) 452 if (RootPart.GetStatusSandbox())
302 { 453 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 454 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -305,16 +456,17 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 456 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 457 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 458 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
459 lockPartsForRead(false);
308 return; 460 return;
309 } 461 }
310 } 462 }
311 lock (m_parts) 463 foreach (SceneObjectPart part in m_parts.Values)
312 { 464 {
313 foreach (SceneObjectPart part in m_parts.Values) 465 part.IgnoreUndoUpdate = false;
314 { 466 part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
315 part.GroupPosition = val; 467 part.GroupPosition = val;
316 }
317 } 468 }
469 lockPartsForRead(false);
318 470
319 //if (m_rootPart.PhysActor != null) 471 //if (m_rootPart.PhysActor != null)
320 //{ 472 //{
@@ -457,6 +609,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 609 /// </summary>
458 public SceneObjectGroup() 610 public SceneObjectGroup()
459 { 611 {
612
460 } 613 }
461 614
462 /// <summary> 615 /// <summary>
@@ -473,7 +626,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 626 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 627 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 628 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 629 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 630 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 631 }
479 632
@@ -504,13 +657,16 @@ namespace OpenSim.Region.Framework.Scenes
504 657
505 public void SetFromItemID(UUID AssetId) 658 public void SetFromItemID(UUID AssetId)
506 { 659 {
507 lock (m_parts) 660 lockPartsForRead(true);
508 { 661 {
509 foreach (SceneObjectPart part in m_parts.Values) 662 foreach (SceneObjectPart part in m_parts.Values)
510 { 663 {
664
511 part.FromItemID = AssetId; 665 part.FromItemID = AssetId;
666
512 } 667 }
513 } 668 }
669 lockPartsForRead(false);
514 } 670 }
515 671
516 public UUID GetFromItemID() 672 public UUID GetFromItemID()
@@ -523,6 +679,9 @@ namespace OpenSim.Region.Framework.Scenes
523 /// </summary> 679 /// </summary>
524 public virtual void AttachToBackup() 680 public virtual void AttachToBackup()
525 { 681 {
682 if (IsAttachment) return;
683 m_scene.SceneGraph.FireAttachToBackup(this);
684
526 if (InSceneBackup) 685 if (InSceneBackup)
527 { 686 {
528 //m_log.DebugFormat( 687 //m_log.DebugFormat(
@@ -579,7 +738,7 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 738 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 739 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 740
582 lock (m_parts) 741 lockPartsForRead(true);
583 { 742 {
584 foreach (SceneObjectPart part in m_parts.Values) 743 foreach (SceneObjectPart part in m_parts.Values)
585 { 744 {
@@ -593,8 +752,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 752 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; 753 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; 754 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
755
596 } 756 }
597 } 757 }
758 lockPartsForRead(false);
759
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 760 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 761 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 762 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +772,11 @@ namespace OpenSim.Region.Framework.Scenes
610 772
611 EntityIntersection result = new EntityIntersection(); 773 EntityIntersection result = new EntityIntersection();
612 774
613 lock (m_parts) 775 lockPartsForRead(true);
614 { 776 {
615 foreach (SceneObjectPart part in m_parts.Values) 777 foreach (SceneObjectPart part in m_parts.Values)
616 { 778 {
779
617 // Temporary commented to stop compiler warning 780 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 781 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 782 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +804,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 804 result.distance = inter.distance;
642 } 805 }
643 } 806 }
807
644 } 808 }
645 } 809 }
810 lockPartsForRead(false);
646 return result; 811 return result;
647 } 812 }
648 813
@@ -661,10 +826,11 @@ namespace OpenSim.Region.Framework.Scenes
661 minY = 256f; 826 minY = 256f;
662 minZ = 8192f; 827 minZ = 8192f;
663 828
664 lock(m_parts); 829 lockPartsForRead(true);
665 { 830 {
666 foreach (SceneObjectPart part in m_parts.Values) 831 foreach (SceneObjectPart part in m_parts.Values)
667 { 832 {
833
668 Vector3 worldPos = part.GetWorldPosition(); 834 Vector3 worldPos = part.GetWorldPosition();
669 Vector3 offset = worldPos - AbsolutePosition; 835 Vector3 offset = worldPos - AbsolutePosition;
670 Quaternion worldRot; 836 Quaternion worldRot;
@@ -723,6 +889,8 @@ namespace OpenSim.Region.Framework.Scenes
723 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 889 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
724 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 890 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
725 891
892
893
726 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 894 //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); 895 //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); 896 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -894,6 +1062,7 @@ namespace OpenSim.Region.Framework.Scenes
894 minZ = backBottomLeft.Z; 1062 minZ = backBottomLeft.Z;
895 } 1063 }
896 } 1064 }
1065 lockPartsForRead(false);
897 } 1066 }
898 1067
899 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 1068 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
@@ -929,21 +1098,29 @@ namespace OpenSim.Region.Framework.Scenes
929 1098
930 public void SaveScriptedState(XmlTextWriter writer) 1099 public void SaveScriptedState(XmlTextWriter writer)
931 { 1100 {
1101 SaveScriptedState(writer, false);
1102 }
1103
1104 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1105 {
932 XmlDocument doc = new XmlDocument(); 1106 XmlDocument doc = new XmlDocument();
933 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1107 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
934 1108
935 // Capture script state while holding the lock 1109 // Capture script state while holding the lock
936 lock (m_parts) 1110 lockPartsForRead(true);
937 { 1111 {
938 foreach (SceneObjectPart part in m_parts.Values) 1112 foreach (SceneObjectPart part in m_parts.Values)
939 { 1113 {
940 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1114
1115 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs);
941 foreach (UUID itemid in pstates.Keys) 1116 foreach (UUID itemid in pstates.Keys)
942 { 1117 {
943 states.Add(itemid, pstates[itemid]); 1118 states.Add(itemid, pstates[itemid]);
944 } 1119 }
1120
945 } 1121 }
946 } 1122 }
1123 lockPartsForRead(false);
947 1124
948 if (states.Count > 0) 1125 if (states.Count > 0)
949 { 1126 {
@@ -962,6 +1139,47 @@ namespace OpenSim.Region.Framework.Scenes
962 } 1139 }
963 1140
964 /// <summary> 1141 /// <summary>
1142 /// Add the avatar to this linkset (avatar is sat).
1143 /// </summary>
1144 /// <param name="agentID"></param>
1145 public void AddAvatar(UUID agentID)
1146 {
1147 ScenePresence presence;
1148 if (m_scene.TryGetScenePresence(agentID, out presence))
1149 {
1150 if (!m_linkedAvatars.Contains(presence))
1151 {
1152 m_linkedAvatars.Add(presence);
1153 }
1154 }
1155 }
1156
1157 /// <summary>
1158 /// Delete the avatar from this linkset (avatar is unsat).
1159 /// </summary>
1160 /// <param name="agentID"></param>
1161 public void DeleteAvatar(UUID agentID)
1162 {
1163 ScenePresence presence;
1164 if (m_scene.TryGetScenePresence(agentID, out presence))
1165 {
1166 if (m_linkedAvatars.Contains(presence))
1167 {
1168 m_linkedAvatars.Remove(presence);
1169 }
1170 }
1171 }
1172
1173 /// <summary>
1174 /// Returns the list of linked presences (avatars sat on this group)
1175 /// </summary>
1176 /// <param name="agentID"></param>
1177 public List<ScenePresence> GetLinkedAvatars()
1178 {
1179 return m_linkedAvatars;
1180 }
1181
1182 /// <summary>
965 /// Attach this scene object to the given avatar. 1183 /// Attach this scene object to the given avatar.
966 /// </summary> 1184 /// </summary>
967 /// <param name="agentID"></param> 1185 /// <param name="agentID"></param>
@@ -1112,13 +1330,16 @@ namespace OpenSim.Region.Framework.Scenes
1112 1330
1113 public override void UpdateMovement() 1331 public override void UpdateMovement()
1114 { 1332 {
1115 lock (m_parts) 1333 lockPartsForRead(true);
1116 { 1334 {
1117 foreach (SceneObjectPart part in m_parts.Values) 1335 foreach (SceneObjectPart part in m_parts.Values)
1118 { 1336 {
1337
1119 part.UpdateMovement(); 1338 part.UpdateMovement();
1339
1120 } 1340 }
1121 } 1341 }
1342 lockPartsForRead(false);
1122 } 1343 }
1123 1344
1124 public ushort GetTimeDilation() 1345 public ushort GetTimeDilation()
@@ -1162,7 +1383,7 @@ namespace OpenSim.Region.Framework.Scenes
1162 /// <param name="part"></param> 1383 /// <param name="part"></param>
1163 public void AddPart(SceneObjectPart part) 1384 public void AddPart(SceneObjectPart part)
1164 { 1385 {
1165 lock (m_parts) 1386 lockPartsForWrite(true);
1166 { 1387 {
1167 part.SetParent(this); 1388 part.SetParent(this);
1168 m_parts.Add(part.UUID, part); 1389 m_parts.Add(part.UUID, part);
@@ -1172,6 +1393,7 @@ namespace OpenSim.Region.Framework.Scenes
1172 if (part.LinkNum == 2 && RootPart != null) 1393 if (part.LinkNum == 2 && RootPart != null)
1173 RootPart.LinkNum = 1; 1394 RootPart.LinkNum = 1;
1174 } 1395 }
1396 lockPartsForWrite(false);
1175 } 1397 }
1176 1398
1177 /// <summary> 1399 /// <summary>
@@ -1179,28 +1401,33 @@ namespace OpenSim.Region.Framework.Scenes
1179 /// </summary> 1401 /// </summary>
1180 private void UpdateParentIDs() 1402 private void UpdateParentIDs()
1181 { 1403 {
1182 lock (m_parts) 1404 lockPartsForRead(true);
1183 { 1405 {
1184 foreach (SceneObjectPart part in m_parts.Values) 1406 foreach (SceneObjectPart part in m_parts.Values)
1185 { 1407 {
1408
1186 if (part.UUID != m_rootPart.UUID) 1409 if (part.UUID != m_rootPart.UUID)
1187 { 1410 {
1188 part.ParentID = m_rootPart.LocalId; 1411 part.ParentID = m_rootPart.LocalId;
1189 } 1412 }
1413
1190 } 1414 }
1191 } 1415 }
1416 lockPartsForRead(false);
1192 } 1417 }
1193 1418
1194 public void RegenerateFullIDs() 1419 public void RegenerateFullIDs()
1195 { 1420 {
1196 lock (m_parts) 1421 lockPartsForRead(true);
1197 { 1422 {
1198 foreach (SceneObjectPart part in m_parts.Values) 1423 foreach (SceneObjectPart part in m_parts.Values)
1199 { 1424 {
1425
1200 part.UUID = UUID.Random(); 1426 part.UUID = UUID.Random();
1201 1427
1202 } 1428 }
1203 } 1429 }
1430 lockPartsForRead(false);
1204 } 1431 }
1205 1432
1206 // helper provided for parts. 1433 // helper provided for parts.
@@ -1261,7 +1488,7 @@ namespace OpenSim.Region.Framework.Scenes
1261 1488
1262 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1489 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1263 { 1490 {
1264 part.StoreUndoState(); 1491 part.StoreUndoState(UndoType.STATE_PRIM_ALL);
1265 part.OnGrab(offsetPos, remoteClient); 1492 part.OnGrab(offsetPos, remoteClient);
1266 } 1493 }
1267 1494
@@ -1281,27 +1508,32 @@ namespace OpenSim.Region.Framework.Scenes
1281 1508
1282 DetachFromBackup(); 1509 DetachFromBackup();
1283 1510
1284 lock (m_parts) 1511 lockPartsForRead(true);
1512 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1513 lockPartsForRead(false);
1514
1515 foreach (SceneObjectPart part in values)
1285 { 1516 {
1286 foreach (SceneObjectPart part in m_parts.Values)
1287 {
1288// part.Inventory.RemoveScriptInstances(); 1517// part.Inventory.RemoveScriptInstances();
1289 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1518
1519 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1520 {
1521 if (sp.ParentID == LocalId)
1290 { 1522 {
1291 if (avatar.ParentID == LocalId) 1523 sp.StandUp();
1292 { 1524 }
1293 avatar.StandUp();
1294 }
1295 1525
1296 if (!silent) 1526 if (!silent)
1297 { 1527 {
1298 part.UpdateFlag = 0; 1528 part.UpdateFlag = 0;
1299 if (part == m_rootPart) 1529 if (part == m_rootPart)
1300 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1530 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1301 } 1531 }
1302 }); 1532 });
1303 } 1533
1304 } 1534 }
1535
1536
1305 } 1537 }
1306 1538
1307 public void AddScriptLPS(int count) 1539 public void AddScriptLPS(int count)
@@ -1326,17 +1558,20 @@ namespace OpenSim.Region.Framework.Scenes
1326 1558
1327 scriptEvents aggregateScriptEvents=0; 1559 scriptEvents aggregateScriptEvents=0;
1328 1560
1329 lock (m_parts) 1561 lockPartsForRead(true);
1330 { 1562 {
1331 foreach (SceneObjectPart part in m_parts.Values) 1563 foreach (SceneObjectPart part in m_parts.Values)
1332 { 1564 {
1565
1333 if (part == null) 1566 if (part == null)
1334 continue; 1567 continue;
1335 if (part != RootPart) 1568 if (part != RootPart)
1336 part.ObjectFlags = objectflagupdate; 1569 part.ObjectFlags = objectflagupdate;
1337 aggregateScriptEvents |= part.AggregateScriptEvents; 1570 aggregateScriptEvents |= part.AggregateScriptEvents;
1571
1338 } 1572 }
1339 } 1573 }
1574 lockPartsForRead(false);
1340 1575
1341 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1576 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1342 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1577 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1378,42 +1613,52 @@ namespace OpenSim.Region.Framework.Scenes
1378 /// <param name="m_physicalPrim"></param> 1613 /// <param name="m_physicalPrim"></param>
1379 public void ApplyPhysics(bool m_physicalPrim) 1614 public void ApplyPhysics(bool m_physicalPrim)
1380 { 1615 {
1381 lock (m_parts) 1616 lockPartsForRead(true);
1617
1618 if (m_parts.Count > 1)
1382 { 1619 {
1383 if (m_parts.Count > 1) 1620 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1621 lockPartsForRead(false);
1622 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1623 foreach (SceneObjectPart part in values)
1384 { 1624 {
1385 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1625
1386 foreach (SceneObjectPart part in m_parts.Values) 1626 if (part.LocalId != m_rootPart.LocalId)
1387 { 1627 {
1388 if (part.LocalId != m_rootPart.LocalId) 1628 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1389 {
1390 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1391 }
1392 } 1629 }
1393 1630
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 } 1631 }
1632 // Hack to get the physics scene geometries in the right spot
1633 ResetChildPrimPhysicsPositions();
1634 }
1635 else
1636 {
1637 lockPartsForRead(false);
1638 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1401 } 1639 }
1402 } 1640 }
1403 1641
1404 public void SetOwnerId(UUID userId) 1642 public void SetOwnerId(UUID userId)
1405 { 1643 {
1406 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1644 ForEachPart(delegate(SceneObjectPart part)
1645 {
1646
1647 part.OwnerID = userId;
1648
1649 });
1407 } 1650 }
1408 1651
1409 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1652 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1410 { 1653 {
1411 lock (m_parts) 1654 lockPartsForRead(true);
1655 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1656 lockPartsForRead(false);
1657 foreach (SceneObjectPart part in values)
1412 { 1658 {
1413 foreach (SceneObjectPart part in m_parts.Values) 1659
1414 { 1660 whatToDo(part);
1415 whatToDo(part); 1661
1416 }
1417 } 1662 }
1418 } 1663 }
1419 1664
@@ -1511,15 +1756,17 @@ namespace OpenSim.Region.Framework.Scenes
1511 RootPart.SendFullUpdate( 1756 RootPart.SendFullUpdate(
1512 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1757 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1513 1758
1514 lock (m_parts) 1759 lockPartsForRead(true);
1515 { 1760 {
1516 foreach (SceneObjectPart part in m_parts.Values) 1761 foreach (SceneObjectPart part in m_parts.Values)
1517 { 1762 {
1763
1518 if (part != RootPart) 1764 if (part != RootPart)
1519 part.SendFullUpdate( 1765 part.SendFullUpdate(
1520 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1766 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1521 } 1767 }
1522 } 1768 }
1769 lockPartsForRead(false);
1523 } 1770 }
1524 1771
1525 #region Copying 1772 #region Copying
@@ -1580,10 +1827,11 @@ namespace OpenSim.Region.Framework.Scenes
1580 1827
1581 List<SceneObjectPart> partList; 1828 List<SceneObjectPart> partList;
1582 1829
1583 lock (m_parts) 1830 lockPartsForRead(true);
1584 { 1831
1585 partList = new List<SceneObjectPart>(m_parts.Values); 1832 partList = new List<SceneObjectPart>(m_parts.Values);
1586 } 1833
1834 lockPartsForRead(false);
1587 1835
1588 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1836 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1589 { 1837 {
@@ -1800,13 +2048,40 @@ namespace OpenSim.Region.Framework.Scenes
1800 } 2048 }
1801 } 2049 }
1802 2050
2051 public void rotLookAt(Quaternion target, float strength, float damping)
2052 {
2053 SceneObjectPart rootpart = m_rootPart;
2054 if (rootpart != null)
2055 {
2056 if (IsAttachment)
2057 {
2058 /*
2059 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2060 if (avatar != null)
2061 {
2062 Rotate the Av?
2063 } */
2064 }
2065 else
2066 {
2067 if (rootpart.PhysActor != null)
2068 { // APID must be implemented in your physics system for this to function.
2069 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2070 rootpart.PhysActor.APIDStrength = strength;
2071 rootpart.PhysActor.APIDDamping = damping;
2072 rootpart.PhysActor.APIDActive = true;
2073 }
2074 }
2075 }
2076 }
2077
1803 public void stopLookAt() 2078 public void stopLookAt()
1804 { 2079 {
1805 SceneObjectPart rootpart = m_rootPart; 2080 SceneObjectPart rootpart = m_rootPart;
1806 if (rootpart != null) 2081 if (rootpart != null)
1807 { 2082 {
1808 if (rootpart.PhysActor != null) 2083 if (rootpart.PhysActor != null)
1809 { 2084 { // APID must be implemented in your physics system for this to function.
1810 rootpart.PhysActor.APIDActive = false; 2085 rootpart.PhysActor.APIDActive = false;
1811 } 2086 }
1812 } 2087 }
@@ -1874,10 +2149,11 @@ namespace OpenSim.Region.Framework.Scenes
1874 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2149 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1875 newPart.SetParent(this); 2150 newPart.SetParent(this);
1876 2151
1877 lock (m_parts) 2152 lockPartsForWrite(true);
1878 { 2153 {
1879 m_parts.Add(newPart.UUID, newPart); 2154 m_parts.Add(newPart.UUID, newPart);
1880 } 2155 }
2156 lockPartsForWrite(false);
1881 2157
1882 SetPartAsNonRoot(newPart); 2158 SetPartAsNonRoot(newPart);
1883 2159
@@ -1940,7 +2216,7 @@ namespace OpenSim.Region.Framework.Scenes
1940 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2216 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1941 // return; 2217 // return;
1942 2218
1943 lock (m_parts) 2219 lockPartsForRead(true);
1944 { 2220 {
1945 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2221 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1946 2222
@@ -1960,9 +2236,12 @@ namespace OpenSim.Region.Framework.Scenes
1960 { 2236 {
1961 if (!IsSelected) 2237 if (!IsSelected)
1962 part.UpdateLookAt(); 2238 part.UpdateLookAt();
2239
1963 part.SendScheduledUpdates(); 2240 part.SendScheduledUpdates();
2241
1964 } 2242 }
1965 } 2243 }
2244 lockPartsForRead(false);
1966 } 2245 }
1967 2246
1968 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2247 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1971,27 +2250,29 @@ namespace OpenSim.Region.Framework.Scenes
1971 2250
1972 RootPart.AddFullUpdateToAvatar(presence); 2251 RootPart.AddFullUpdateToAvatar(presence);
1973 2252
1974 lock (m_parts) 2253 lockPartsForRead(true);
1975 { 2254 {
1976 foreach (SceneObjectPart part in m_parts.Values) 2255 foreach (SceneObjectPart part in m_parts.Values)
1977 { 2256 {
2257
1978 if (part != RootPart) 2258 if (part != RootPart)
1979 part.AddFullUpdateToAvatar(presence); 2259 part.AddFullUpdateToAvatar(presence);
2260
1980 } 2261 }
1981 } 2262 }
2263 lockPartsForRead(false);
1982 } 2264 }
1983 2265
1984 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2266 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1985 { 2267 {
1986// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2268 lockPartsForRead(true);
1987 2269
1988 lock (m_parts) 2270 foreach (SceneObjectPart part in m_parts.Values)
1989 { 2271 {
1990 foreach (SceneObjectPart part in m_parts.Values) 2272 part.AddTerseUpdateToAvatar(presence);
1991 {
1992 part.AddTerseUpdateToAvatar(presence);
1993 }
1994 } 2273 }
2274
2275 lockPartsForRead(false);
1995 } 2276 }
1996 2277
1997 /// <summary> 2278 /// <summary>
@@ -1999,20 +2280,23 @@ namespace OpenSim.Region.Framework.Scenes
1999 /// </summary> 2280 /// </summary>
2000 public void ScheduleGroupForFullUpdate() 2281 public void ScheduleGroupForFullUpdate()
2001 { 2282 {
2002 if (IsAttachment) 2283 //if (IsAttachment)
2003 m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); 2284 // m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
2004 2285
2005 checkAtTargets(); 2286 checkAtTargets();
2006 RootPart.ScheduleFullUpdate(); 2287 RootPart.ScheduleFullUpdate();
2007 2288
2008 lock (m_parts) 2289 lockPartsForRead(true);
2009 { 2290 {
2010 foreach (SceneObjectPart part in m_parts.Values) 2291 foreach (SceneObjectPart part in m_parts.Values)
2011 { 2292 {
2293
2012 if (part != RootPart) 2294 if (part != RootPart)
2013 part.ScheduleFullUpdate(); 2295 part.ScheduleFullUpdate();
2296
2014 } 2297 }
2015 } 2298 }
2299 lockPartsForRead(false);
2016 } 2300 }
2017 2301
2018 /// <summary> 2302 /// <summary>
@@ -2020,37 +2304,38 @@ namespace OpenSim.Region.Framework.Scenes
2020 /// </summary> 2304 /// </summary>
2021 public void ScheduleGroupForTerseUpdate() 2305 public void ScheduleGroupForTerseUpdate()
2022 { 2306 {
2023// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2307 lockPartsForRead(true);
2024 2308 foreach (SceneObjectPart part in m_parts.Values)
2025 lock (m_parts)
2026 { 2309 {
2027 foreach (SceneObjectPart part in m_parts.Values) 2310 part.ScheduleTerseUpdate();
2028 {
2029 part.ScheduleTerseUpdate();
2030 }
2031 } 2311 }
2312
2313 lockPartsForRead(false);
2032 } 2314 }
2033 2315
2034 /// <summary> 2316 /// <summary>
2035 /// Immediately send a full update for this scene object. 2317 /// Immediately send a full update for this scene object.
2036 /// </summary> 2318 /// </summary>
2037 public void SendGroupFullUpdate() 2319 public void SendGroupFullUpdate()
2038 { 2320 {
2039 if (IsDeleted) 2321 if (IsDeleted)
2040 return; 2322 return;
2041 2323
2042// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2324// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2043 2325
2044 RootPart.SendFullUpdateToAllClients(); 2326 RootPart.SendFullUpdateToAllClients();
2045 2327
2046 lock (m_parts) 2328 lockPartsForRead(true);
2047 { 2329 {
2048 foreach (SceneObjectPart part in m_parts.Values) 2330 foreach (SceneObjectPart part in m_parts.Values)
2049 { 2331 {
2332
2050 if (part != RootPart) 2333 if (part != RootPart)
2051 part.SendFullUpdateToAllClients(); 2334 part.SendFullUpdateToAllClients();
2335
2052 } 2336 }
2053 } 2337 }
2338 lockPartsForRead(false);
2054 } 2339 }
2055 2340
2056 /// <summary> 2341 /// <summary>
@@ -2082,14 +2367,15 @@ namespace OpenSim.Region.Framework.Scenes
2082 { 2367 {
2083 if (IsDeleted) 2368 if (IsDeleted)
2084 return; 2369 return;
2085 2370
2086 lock (m_parts) 2371 lockPartsForRead(true);
2087 { 2372 {
2088 foreach (SceneObjectPart part in m_parts.Values) 2373 foreach (SceneObjectPart part in m_parts.Values)
2089 { 2374 {
2090 part.SendTerseUpdateToAllClients(); 2375 part.SendTerseUpdateToAllClients();
2091 } 2376 }
2092 } 2377 }
2378 lockPartsForRead(false);
2093 } 2379 }
2094 2380
2095 #endregion 2381 #endregion
@@ -2103,16 +2389,18 @@ namespace OpenSim.Region.Framework.Scenes
2103 /// <returns>null if no child part with that linknum or child part</returns> 2389 /// <returns>null if no child part with that linknum or child part</returns>
2104 public SceneObjectPart GetLinkNumPart(int linknum) 2390 public SceneObjectPart GetLinkNumPart(int linknum)
2105 { 2391 {
2106 lock (m_parts) 2392 lockPartsForRead(true);
2107 { 2393 {
2108 foreach (SceneObjectPart part in m_parts.Values) 2394 foreach (SceneObjectPart part in m_parts.Values)
2109 { 2395 {
2110 if (part.LinkNum == linknum) 2396 if (part.LinkNum == linknum)
2111 { 2397 {
2398 lockPartsForRead(false);
2112 return part; 2399 return part;
2113 } 2400 }
2114 } 2401 }
2115 } 2402 }
2403 lockPartsForRead(false);
2116 2404
2117 return null; 2405 return null;
2118 } 2406 }
@@ -2140,17 +2428,19 @@ namespace OpenSim.Region.Framework.Scenes
2140 public SceneObjectPart GetChildPart(uint localID) 2428 public SceneObjectPart GetChildPart(uint localID)
2141 { 2429 {
2142 //m_log.DebugFormat("Entered looking for {0}", localID); 2430 //m_log.DebugFormat("Entered looking for {0}", localID);
2143 lock (m_parts) 2431 lockPartsForRead(true);
2144 { 2432 {
2145 foreach (SceneObjectPart part in m_parts.Values) 2433 foreach (SceneObjectPart part in m_parts.Values)
2146 { 2434 {
2147 //m_log.DebugFormat("Found {0}", part.LocalId); 2435 //m_log.DebugFormat("Found {0}", part.LocalId);
2148 if (part.LocalId == localID) 2436 if (part.LocalId == localID)
2149 { 2437 {
2438 lockPartsForRead(false);
2150 return part; 2439 return part;
2151 } 2440 }
2152 } 2441 }
2153 } 2442 }
2443 lockPartsForRead(false);
2154 2444
2155 return null; 2445 return null;
2156 } 2446 }
@@ -2180,17 +2470,19 @@ namespace OpenSim.Region.Framework.Scenes
2180 public bool HasChildPrim(uint localID) 2470 public bool HasChildPrim(uint localID)
2181 { 2471 {
2182 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2472 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2183 lock (m_parts) 2473 lockPartsForRead(true);
2184 { 2474 {
2185 foreach (SceneObjectPart part in m_parts.Values) 2475 foreach (SceneObjectPart part in m_parts.Values)
2186 { 2476 {
2187 //m_log.DebugFormat("Found {0}", part.LocalId); 2477 //m_log.DebugFormat("Found {0}", part.LocalId);
2188 if (part.LocalId == localID) 2478 if (part.LocalId == localID)
2189 { 2479 {
2480 lockPartsForRead(false);
2190 return true; 2481 return true;
2191 } 2482 }
2192 } 2483 }
2193 } 2484 }
2485 lockPartsForRead(false);
2194 2486
2195 return false; 2487 return false;
2196 } 2488 }
@@ -2240,53 +2532,57 @@ namespace OpenSim.Region.Framework.Scenes
2240 if (m_rootPart.LinkNum == 0) 2532 if (m_rootPart.LinkNum == 0)
2241 m_rootPart.LinkNum = 1; 2533 m_rootPart.LinkNum = 1;
2242 2534
2243 lock (m_parts) 2535 lockPartsForWrite(true);
2244 { 2536
2245 m_parts.Add(linkPart.UUID, linkPart); 2537 m_parts.Add(linkPart.UUID, linkPart);
2538
2539 lockPartsForWrite(false);
2246 2540
2247 // Insert in terms of link numbers, the new links 2541 // Insert in terms of link numbers, the new links
2248 // before the current ones (with the exception of 2542 // before the current ones (with the exception of
2249 // the root prim. Shuffle the old ones up 2543 // the root prim. Shuffle the old ones up
2250 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2544 lockPartsForRead(true);
2545 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2546 {
2547 if (kvp.Value.LinkNum != 1)
2251 { 2548 {
2252 if (kvp.Value.LinkNum != 1) 2549 // Don't update root prim link number
2253 { 2550 kvp.Value.LinkNum += objectGroup.PrimCount;
2254 // Don't update root prim link number
2255 kvp.Value.LinkNum += objectGroup.PrimCount;
2256 }
2257 } 2551 }
2552 }
2553 lockPartsForRead(false);
2258 2554
2259 linkPart.LinkNum = 2; 2555 linkPart.LinkNum = 2;
2260 2556
2261 linkPart.SetParent(this); 2557 linkPart.SetParent(this);
2262 linkPart.CreateSelected = true; 2558 linkPart.CreateSelected = true;
2263 2559
2264 //if (linkPart.PhysActor != null) 2560 //if (linkPart.PhysActor != null)
2265 //{ 2561 //{
2266 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2562 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2267 2563
2268 //linkPart.PhysActor = null; 2564 //linkPart.PhysActor = null;
2269 //} 2565 //}
2270 2566
2271 //TODO: rest of parts 2567 //TODO: rest of parts
2272 int linkNum = 3; 2568 int linkNum = 3;
2273 foreach (SceneObjectPart part in objectGroup.Children.Values) 2569 foreach (SceneObjectPart part in objectGroup.Children.Values)
2570 {
2571 if (part.UUID != objectGroup.m_rootPart.UUID)
2274 { 2572 {
2275 if (part.UUID != objectGroup.m_rootPart.UUID) 2573 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2276 {
2277 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2278 }
2279 part.ClearUndoState();
2280 } 2574 }
2575 part.ClearUndoState();
2281 } 2576 }
2282 2577
2283 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2578 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2284 objectGroup.m_isDeleted = true; 2579 objectGroup.m_isDeleted = true;
2580
2581 objectGroup.lockPartsForWrite(true);
2285 2582
2286 lock (objectGroup.m_parts) 2583 objectGroup.m_parts.Clear();
2287 { 2584
2288 objectGroup.m_parts.Clear(); 2585 objectGroup.lockPartsForWrite(false);
2289 }
2290 2586
2291 // Can't do this yet since backup still makes use of the root part without any synchronization 2587 // Can't do this yet since backup still makes use of the root part without any synchronization
2292// objectGroup.m_rootPart = null; 2588// objectGroup.m_rootPart = null;
@@ -2356,11 +2652,12 @@ namespace OpenSim.Region.Framework.Scenes
2356 Quaternion worldRot = linkPart.GetWorldRotation(); 2652 Quaternion worldRot = linkPart.GetWorldRotation();
2357 2653
2358 // Remove the part from this object 2654 // Remove the part from this object
2359 lock (m_parts) 2655 lockPartsForWrite(true);
2360 { 2656 {
2361 m_parts.Remove(linkPart.UUID); 2657 m_parts.Remove(linkPart.UUID);
2362 } 2658 }
2363 2659 lockPartsForWrite(false);
2660 lockPartsForRead(true);
2364 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2661 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2365 RootPart.LinkNum = 0; 2662 RootPart.LinkNum = 0;
2366 else 2663 else
@@ -2371,6 +2668,7 @@ namespace OpenSim.Region.Framework.Scenes
2371 p.LinkNum--; 2668 p.LinkNum--;
2372 } 2669 }
2373 } 2670 }
2671 lockPartsForRead(false);
2374 2672
2375 linkPart.ParentID = 0; 2673 linkPart.ParentID = 0;
2376 linkPart.LinkNum = 0; 2674 linkPart.LinkNum = 0;
@@ -2414,6 +2712,8 @@ namespace OpenSim.Region.Framework.Scenes
2414 /// <param name="objectGroup"></param> 2712 /// <param name="objectGroup"></param>
2415 public virtual void DetachFromBackup() 2713 public virtual void DetachFromBackup()
2416 { 2714 {
2715 m_scene.SceneGraph.FireDetachFromBackup(this);
2716
2417 if (m_isBackedUp) 2717 if (m_isBackedUp)
2418 m_scene.EventManager.OnBackup -= ProcessBackup; 2718 m_scene.EventManager.OnBackup -= ProcessBackup;
2419 2719
@@ -2692,9 +2992,12 @@ namespace OpenSim.Region.Framework.Scenes
2692 2992
2693 if (selectionPart != null) 2993 if (selectionPart != null)
2694 { 2994 {
2695 lock (m_parts) 2995 lockPartsForRead(true);
2996 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2997 lockPartsForRead(false);
2998 foreach (SceneObjectPart part in parts)
2696 { 2999 {
2697 foreach (SceneObjectPart part in m_parts.Values) 3000 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2698 { 3001 {
2699 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 3002 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2700 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 3003 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2704,12 +3007,13 @@ namespace OpenSim.Region.Framework.Scenes
2704 break; 3007 break;
2705 } 3008 }
2706 } 3009 }
3010 }
2707 3011
2708 foreach (SceneObjectPart part in m_parts.Values) 3012 foreach (SceneObjectPart part in parts)
2709 { 3013 {
2710 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3014 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2711 }
2712 } 3015 }
3016
2713 } 3017 }
2714 } 3018 }
2715 3019
@@ -2722,6 +3026,17 @@ namespace OpenSim.Region.Framework.Scenes
2722 } 3026 }
2723 } 3027 }
2724 3028
3029
3030
3031 /// <summary>
3032 /// Gets the number of parts
3033 /// </summary>
3034 /// <returns></returns>
3035 public int GetPartCount()
3036 {
3037 return Children.Count;
3038 }
3039
2725 /// <summary> 3040 /// <summary>
2726 /// Get the parts of this scene object 3041 /// Get the parts of this scene object
2727 /// </summary> 3042 /// </summary>
@@ -2795,11 +3110,9 @@ namespace OpenSim.Region.Framework.Scenes
2795 scale.Y = m_scene.m_maxNonphys; 3110 scale.Y = m_scene.m_maxNonphys;
2796 if (scale.Z > m_scene.m_maxNonphys) 3111 if (scale.Z > m_scene.m_maxNonphys)
2797 scale.Z = m_scene.m_maxNonphys; 3112 scale.Z = m_scene.m_maxNonphys;
2798
2799 SceneObjectPart part = GetChildPart(localID); 3113 SceneObjectPart part = GetChildPart(localID);
2800 if (part != null) 3114 if (part != null)
2801 { 3115 {
2802 part.Resize(scale);
2803 if (part.PhysActor != null) 3116 if (part.PhysActor != null)
2804 { 3117 {
2805 if (part.PhysActor.IsPhysical) 3118 if (part.PhysActor.IsPhysical)
@@ -2814,7 +3127,7 @@ namespace OpenSim.Region.Framework.Scenes
2814 part.PhysActor.Size = scale; 3127 part.PhysActor.Size = scale;
2815 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3128 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2816 } 3129 }
2817 //if (part.UUID != m_rootPart.UUID) 3130 part.Resize(scale);
2818 3131
2819 HasGroupChanged = true; 3132 HasGroupChanged = true;
2820 ScheduleGroupForFullUpdate(); 3133 ScheduleGroupForFullUpdate();
@@ -2836,7 +3149,6 @@ namespace OpenSim.Region.Framework.Scenes
2836 SceneObjectPart part = GetChildPart(localID); 3149 SceneObjectPart part = GetChildPart(localID);
2837 if (part != null) 3150 if (part != null)
2838 { 3151 {
2839 part.IgnoreUndoUpdate = true;
2840 if (scale.X > m_scene.m_maxNonphys) 3152 if (scale.X > m_scene.m_maxNonphys)
2841 scale.X = m_scene.m_maxNonphys; 3153 scale.X = m_scene.m_maxNonphys;
2842 if (scale.Y > m_scene.m_maxNonphys) 3154 if (scale.Y > m_scene.m_maxNonphys)
@@ -2856,94 +3168,100 @@ namespace OpenSim.Region.Framework.Scenes
2856 float y = (scale.Y / part.Scale.Y); 3168 float y = (scale.Y / part.Scale.Y);
2857 float z = (scale.Z / part.Scale.Z); 3169 float z = (scale.Z / part.Scale.Z);
2858 3170
2859 lock (m_parts) 3171 lockPartsForRead(true);
3172 if (x > 1.0f || y > 1.0f || z > 1.0f)
2860 { 3173 {
2861 if (x > 1.0f || y > 1.0f || z > 1.0f) 3174 foreach (SceneObjectPart obPart in m_parts.Values)
2862 { 3175 {
2863 foreach (SceneObjectPart obPart in m_parts.Values) 3176 if (obPart.UUID != m_rootPart.UUID)
2864 { 3177 {
2865 if (obPart.UUID != m_rootPart.UUID) 3178 Vector3 oldSize = new Vector3(obPart.Scale);
2866 { 3179 obPart.IgnoreUndoUpdate = true;
2867 obPart.IgnoreUndoUpdate = true;
2868 Vector3 oldSize = new Vector3(obPart.Scale);
2869 3180
2870 float f = 1.0f; 3181 float f = 1.0f;
2871 float a = 1.0f; 3182 float a = 1.0f;
2872 3183
2873 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3184 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3185 {
3186 if (oldSize.X*x > m_scene.m_maxPhys)
2874 { 3187 {
2875 if (oldSize.X*x > m_scene.m_maxPhys) 3188 f = m_scene.m_maxPhys / oldSize.X;
2876 { 3189 a = f / x;
2877 f = m_scene.m_maxPhys / oldSize.X; 3190 x *= a;
2878 a = f / x; 3191 y *= a;
2879 x *= a; 3192 z *= a;
2880 y *= a;
2881 z *= a;
2882 }
2883 if (oldSize.Y*y > m_scene.m_maxPhys)
2884 {
2885 f = m_scene.m_maxPhys / oldSize.Y;
2886 a = f / y;
2887 x *= a;
2888 y *= a;
2889 z *= a;
2890 }
2891 if (oldSize.Z*z > m_scene.m_maxPhys)
2892 {
2893 f = m_scene.m_maxPhys / oldSize.Z;
2894 a = f / z;
2895 x *= a;
2896 y *= a;
2897 z *= a;
2898 }
2899 } 3193 }
2900 else 3194 if (oldSize.Y*y > m_scene.m_maxPhys)
3195 {
3196 f = m_scene.m_maxPhys / oldSize.Y;
3197 a = f / y;
3198 x *= a;
3199 y *= a;
3200 z *= a;
3201 }
3202 if (oldSize.Z*z > m_scene.m_maxPhys)
3203 {
3204 f = m_scene.m_maxPhys / oldSize.Z;
3205 a = f / z;
3206 x *= a;
3207 y *= a;
3208 z *= a;
3209 }
3210 }
3211 else
3212 {
3213 if (oldSize.X*x > m_scene.m_maxNonphys)
3214 {
3215 f = m_scene.m_maxNonphys / oldSize.X;
3216 a = f / x;
3217 x *= a;
3218 y *= a;
3219 z *= a;
3220 }
3221 if (oldSize.Y*y > m_scene.m_maxNonphys)
3222 {
3223 f = m_scene.m_maxNonphys / oldSize.Y;
3224 a = f / y;
3225 x *= a;
3226 y *= a;
3227 z *= a;
3228 }
3229 if (oldSize.Z*z > m_scene.m_maxNonphys)
2901 { 3230 {
2902 if (oldSize.X*x > m_scene.m_maxNonphys) 3231 f = m_scene.m_maxNonphys / oldSize.Z;
2903 { 3232 a = f / z;
2904 f = m_scene.m_maxNonphys / oldSize.X; 3233 x *= a;
2905 a = f / x; 3234 y *= a;
2906 x *= a; 3235 z *= a;
2907 y *= a;
2908 z *= a;
2909 }
2910 if (oldSize.Y*y > m_scene.m_maxNonphys)
2911 {
2912 f = m_scene.m_maxNonphys / oldSize.Y;
2913 a = f / y;
2914 x *= a;
2915 y *= a;
2916 z *= a;
2917 }
2918 if (oldSize.Z*z > m_scene.m_maxNonphys)
2919 {
2920 f = m_scene.m_maxNonphys / oldSize.Z;
2921 a = f / z;
2922 x *= a;
2923 y *= a;
2924 z *= a;
2925 }
2926 } 3236 }
2927 obPart.IgnoreUndoUpdate = false; 3237
2928 obPart.StoreUndoState();
2929 } 3238 }
2930 } 3239 }
2931 } 3240 }
2932 } 3241 }
3242 lockPartsForRead(false);
2933 3243
2934 Vector3 prevScale = part.Scale; 3244 Vector3 prevScale = part.Scale;
2935 prevScale.X *= x; 3245 prevScale.X *= x;
2936 prevScale.Y *= y; 3246 prevScale.Y *= y;
2937 prevScale.Z *= z; 3247 prevScale.Z *= z;;
3248
3249 part.IgnoreUndoUpdate = false;
3250 part.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3251 part.IgnoreUndoUpdate = true;
2938 part.Resize(prevScale); 3252 part.Resize(prevScale);
3253 part.IgnoreUndoUpdate = false;
2939 3254
2940 lock (m_parts) 3255 lockPartsForRead(true);
2941 { 3256 {
2942 foreach (SceneObjectPart obPart in m_parts.Values) 3257 foreach (SceneObjectPart obPart in m_parts.Values)
2943 { 3258 {
2944 obPart.IgnoreUndoUpdate = true;
2945 if (obPart.UUID != m_rootPart.UUID) 3259 if (obPart.UUID != m_rootPart.UUID)
2946 { 3260 {
3261 obPart.IgnoreUndoUpdate = false;
3262 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3263 obPart.IgnoreUndoUpdate = true;
3264
2947 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3265 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2948 currentpos.X *= x; 3266 currentpos.X *= x;
2949 currentpos.Y *= y; 3267 currentpos.Y *= y;
@@ -2956,9 +3274,9 @@ namespace OpenSim.Region.Framework.Scenes
2956 obPart.UpdateOffSet(currentpos); 3274 obPart.UpdateOffSet(currentpos);
2957 } 3275 }
2958 obPart.IgnoreUndoUpdate = false; 3276 obPart.IgnoreUndoUpdate = false;
2959 obPart.StoreUndoState();
2960 } 3277 }
2961 } 3278 }
3279 lockPartsForRead(false);
2962 3280
2963 if (part.PhysActor != null) 3281 if (part.PhysActor != null)
2964 { 3282 {
@@ -2967,7 +3285,6 @@ namespace OpenSim.Region.Framework.Scenes
2967 } 3285 }
2968 3286
2969 part.IgnoreUndoUpdate = false; 3287 part.IgnoreUndoUpdate = false;
2970 part.StoreUndoState();
2971 HasGroupChanged = true; 3288 HasGroupChanged = true;
2972 ScheduleGroupForTerseUpdate(); 3289 ScheduleGroupForTerseUpdate();
2973 } 3290 }
@@ -2983,14 +3300,11 @@ namespace OpenSim.Region.Framework.Scenes
2983 /// <param name="pos"></param> 3300 /// <param name="pos"></param>
2984 public void UpdateGroupPosition(Vector3 pos) 3301 public void UpdateGroupPosition(Vector3 pos)
2985 { 3302 {
2986 foreach (SceneObjectPart part in Children.Values)
2987 {
2988 part.StoreUndoState();
2989 }
2990 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3303 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2991 { 3304 {
2992 if (IsAttachment) 3305 if (IsAttachment)
2993 { 3306 {
3307 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
2994 m_rootPart.AttachedPos = pos; 3308 m_rootPart.AttachedPos = pos;
2995 } 3309 }
2996 if (RootPart.GetStatusSandbox()) 3310 if (RootPart.GetStatusSandbox())
@@ -3023,7 +3337,7 @@ namespace OpenSim.Region.Framework.Scenes
3023 SceneObjectPart part = GetChildPart(localID); 3337 SceneObjectPart part = GetChildPart(localID);
3024 foreach (SceneObjectPart parts in Children.Values) 3338 foreach (SceneObjectPart parts in Children.Values)
3025 { 3339 {
3026 parts.StoreUndoState(); 3340 parts.StoreUndoState(UndoType.STATE_PRIM_POSITION);
3027 } 3341 }
3028 if (part != null) 3342 if (part != null)
3029 { 3343 {
@@ -3048,7 +3362,7 @@ namespace OpenSim.Region.Framework.Scenes
3048 { 3362 {
3049 foreach (SceneObjectPart part in Children.Values) 3363 foreach (SceneObjectPart part in Children.Values)
3050 { 3364 {
3051 part.StoreUndoState(); 3365 part.StoreUndoState(UndoType.STATE_PRIM_POSITION);
3052 } 3366 }
3053 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3367 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
3054 Vector3 oldPos = 3368 Vector3 oldPos =
@@ -3061,7 +3375,7 @@ namespace OpenSim.Region.Framework.Scenes
3061 axDiff *= Quaternion.Inverse(partRotation); 3375 axDiff *= Quaternion.Inverse(partRotation);
3062 diff = axDiff; 3376 diff = axDiff;
3063 3377
3064 lock (m_parts) 3378 lockPartsForRead(true);
3065 { 3379 {
3066 foreach (SceneObjectPart obPart in m_parts.Values) 3380 foreach (SceneObjectPart obPart in m_parts.Values)
3067 { 3381 {
@@ -3071,11 +3385,29 @@ namespace OpenSim.Region.Framework.Scenes
3071 } 3385 }
3072 } 3386 }
3073 } 3387 }
3388 lockPartsForRead(false);
3074 3389
3075 AbsolutePosition = newPos; 3390 //We have to set undoing here because otherwise an undo state will be saved
3391 if (!m_rootPart.Undoing)
3392 {
3393 m_rootPart.Undoing = true;
3394 AbsolutePosition = newPos;
3395 m_rootPart.Undoing = false;
3396 }
3397 else
3398 {
3399 AbsolutePosition = newPos;
3400 }
3076 3401
3077 HasGroupChanged = true; 3402 HasGroupChanged = true;
3078 ScheduleGroupForTerseUpdate(); 3403 if (m_rootPart.Undoing)
3404 {
3405 ScheduleGroupForFullUpdate();
3406 }
3407 else
3408 {
3409 ScheduleGroupForTerseUpdate();
3410 }
3079 } 3411 }
3080 3412
3081 public void OffsetForNewRegion(Vector3 offset) 3413 public void OffsetForNewRegion(Vector3 offset)
@@ -3095,7 +3427,7 @@ namespace OpenSim.Region.Framework.Scenes
3095 { 3427 {
3096 foreach (SceneObjectPart parts in Children.Values) 3428 foreach (SceneObjectPart parts in Children.Values)
3097 { 3429 {
3098 parts.StoreUndoState(); 3430 parts.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
3099 } 3431 }
3100 m_rootPart.UpdateRotation(rot); 3432 m_rootPart.UpdateRotation(rot);
3101 3433
@@ -3119,7 +3451,7 @@ namespace OpenSim.Region.Framework.Scenes
3119 { 3451 {
3120 foreach (SceneObjectPart parts in Children.Values) 3452 foreach (SceneObjectPart parts in Children.Values)
3121 { 3453 {
3122 parts.StoreUndoState(); 3454 parts.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
3123 } 3455 }
3124 m_rootPart.UpdateRotation(rot); 3456 m_rootPart.UpdateRotation(rot);
3125 3457
@@ -3146,7 +3478,7 @@ namespace OpenSim.Region.Framework.Scenes
3146 SceneObjectPart part = GetChildPart(localID); 3478 SceneObjectPart part = GetChildPart(localID);
3147 foreach (SceneObjectPart parts in Children.Values) 3479 foreach (SceneObjectPart parts in Children.Values)
3148 { 3480 {
3149 parts.StoreUndoState(); 3481 parts.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3150 } 3482 }
3151 if (part != null) 3483 if (part != null)
3152 { 3484 {
@@ -3174,15 +3506,24 @@ namespace OpenSim.Region.Framework.Scenes
3174 if (part.UUID == m_rootPart.UUID) 3506 if (part.UUID == m_rootPart.UUID)
3175 { 3507 {
3176 UpdateRootRotation(rot); 3508 UpdateRootRotation(rot);
3177 AbsolutePosition = pos; 3509 if (!m_rootPart.Undoing)
3510 {
3511 m_rootPart.Undoing = true;
3512 AbsolutePosition = pos;
3513 m_rootPart.Undoing = false;
3514 }
3515 else
3516 {
3517 AbsolutePosition = pos;
3518 }
3178 } 3519 }
3179 else 3520 else
3180 { 3521 {
3522 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3181 part.IgnoreUndoUpdate = true; 3523 part.IgnoreUndoUpdate = true;
3182 part.UpdateRotation(rot); 3524 part.UpdateRotation(rot);
3183 part.OffsetPosition = pos; 3525 part.OffsetPosition = pos;
3184 part.IgnoreUndoUpdate = false; 3526 part.IgnoreUndoUpdate = false;
3185 part.StoreUndoState();
3186 } 3527 }
3187 } 3528 }
3188 } 3529 }
@@ -3196,7 +3537,13 @@ namespace OpenSim.Region.Framework.Scenes
3196 Quaternion axRot = rot; 3537 Quaternion axRot = rot;
3197 Quaternion oldParentRot = m_rootPart.RotationOffset; 3538 Quaternion oldParentRot = m_rootPart.RotationOffset;
3198 3539
3199 m_rootPart.StoreUndoState(); 3540 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3541 bool cancelUndo = false;
3542 if (!m_rootPart.Undoing)
3543 {
3544 m_rootPart.Undoing = true;
3545 cancelUndo = true;
3546 }
3200 m_rootPart.UpdateRotation(rot); 3547 m_rootPart.UpdateRotation(rot);
3201 if (m_rootPart.PhysActor != null) 3548 if (m_rootPart.PhysActor != null)
3202 { 3549 {
@@ -3204,33 +3551,31 @@ namespace OpenSim.Region.Framework.Scenes
3204 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3551 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3205 } 3552 }
3206 3553
3207 lock (m_parts) 3554 lockPartsForRead(true);
3555
3556 foreach (SceneObjectPart prim in m_parts.Values)
3208 { 3557 {
3209 foreach (SceneObjectPart prim in m_parts.Values) 3558 if (prim.UUID != m_rootPart.UUID)
3210 { 3559 {
3211 if (prim.UUID != m_rootPart.UUID) 3560 prim.IgnoreUndoUpdate = true;
3212 { 3561 Vector3 axPos = prim.OffsetPosition;
3213 prim.IgnoreUndoUpdate = true; 3562 axPos *= oldParentRot;
3214 Vector3 axPos = prim.OffsetPosition; 3563 axPos *= Quaternion.Inverse(axRot);
3215 axPos *= oldParentRot; 3564 prim.OffsetPosition = axPos;
3216 axPos *= Quaternion.Inverse(axRot); 3565 Quaternion primsRot = prim.RotationOffset;
3217 prim.OffsetPosition = axPos; 3566 Quaternion newRot = primsRot * oldParentRot;
3218 Quaternion primsRot = prim.RotationOffset; 3567 newRot *= Quaternion.Inverse(axRot);
3219 Quaternion newRot = primsRot * oldParentRot; 3568 prim.RotationOffset = newRot;
3220 newRot *= Quaternion.Inverse(axRot); 3569 prim.ScheduleTerseUpdate();
3221 prim.RotationOffset = newRot; 3570 prim.IgnoreUndoUpdate = false;
3222 prim.ScheduleTerseUpdate();
3223 }
3224 } 3571 }
3225 } 3572 }
3226 foreach (SceneObjectPart childpart in Children.Values) 3573 if (cancelUndo == true)
3227 { 3574 {
3228 if (childpart != m_rootPart) 3575 m_rootPart.Undoing = false;
3229 {
3230 childpart.IgnoreUndoUpdate = false;
3231 childpart.StoreUndoState();
3232 }
3233 } 3576 }
3577 lockPartsForRead(false);
3578
3234 m_rootPart.ScheduleTerseUpdate(); 3579 m_rootPart.ScheduleTerseUpdate();
3235 } 3580 }
3236 3581
@@ -3352,7 +3697,7 @@ namespace OpenSim.Region.Framework.Scenes
3352 if (atTargets.Count > 0) 3697 if (atTargets.Count > 0)
3353 { 3698 {
3354 uint[] localids = new uint[0]; 3699 uint[] localids = new uint[0];
3355 lock (m_parts) 3700 lockPartsForRead(true);
3356 { 3701 {
3357 localids = new uint[m_parts.Count]; 3702 localids = new uint[m_parts.Count];
3358 int cntr = 0; 3703 int cntr = 0;
@@ -3362,6 +3707,7 @@ namespace OpenSim.Region.Framework.Scenes
3362 cntr++; 3707 cntr++;
3363 } 3708 }
3364 } 3709 }
3710 lockPartsForRead(false);
3365 3711
3366 for (int ctr = 0; ctr < localids.Length; ctr++) 3712 for (int ctr = 0; ctr < localids.Length; ctr++)
3367 { 3713 {
@@ -3380,7 +3726,7 @@ namespace OpenSim.Region.Framework.Scenes
3380 { 3726 {
3381 //trigger not_at_target 3727 //trigger not_at_target
3382 uint[] localids = new uint[0]; 3728 uint[] localids = new uint[0];
3383 lock (m_parts) 3729 lockPartsForRead(true);
3384 { 3730 {
3385 localids = new uint[m_parts.Count]; 3731 localids = new uint[m_parts.Count];
3386 int cntr = 0; 3732 int cntr = 0;
@@ -3390,7 +3736,8 @@ namespace OpenSim.Region.Framework.Scenes
3390 cntr++; 3736 cntr++;
3391 } 3737 }
3392 } 3738 }
3393 3739 lockPartsForRead(false);
3740
3394 for (int ctr = 0; ctr < localids.Length; ctr++) 3741 for (int ctr = 0; ctr < localids.Length; ctr++)
3395 { 3742 {
3396 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3743 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3431,7 +3778,8 @@ namespace OpenSim.Region.Framework.Scenes
3431 if (atRotTargets.Count > 0) 3778 if (atRotTargets.Count > 0)
3432 { 3779 {
3433 uint[] localids = new uint[0]; 3780 uint[] localids = new uint[0];
3434 lock (m_parts) 3781 lockPartsForRead(true);
3782 try
3435 { 3783 {
3436 localids = new uint[m_parts.Count]; 3784 localids = new uint[m_parts.Count];
3437 int cntr = 0; 3785 int cntr = 0;
@@ -3441,6 +3789,10 @@ namespace OpenSim.Region.Framework.Scenes
3441 cntr++; 3789 cntr++;
3442 } 3790 }
3443 } 3791 }
3792 finally
3793 {
3794 lockPartsForRead(false);
3795 }
3444 3796
3445 for (int ctr = 0; ctr < localids.Length; ctr++) 3797 for (int ctr = 0; ctr < localids.Length; ctr++)
3446 { 3798 {
@@ -3459,7 +3811,8 @@ namespace OpenSim.Region.Framework.Scenes
3459 { 3811 {
3460 //trigger not_at_target 3812 //trigger not_at_target
3461 uint[] localids = new uint[0]; 3813 uint[] localids = new uint[0];
3462 lock (m_parts) 3814 lockPartsForRead(true);
3815 try
3463 { 3816 {
3464 localids = new uint[m_parts.Count]; 3817 localids = new uint[m_parts.Count];
3465 int cntr = 0; 3818 int cntr = 0;
@@ -3469,6 +3822,10 @@ namespace OpenSim.Region.Framework.Scenes
3469 cntr++; 3822 cntr++;
3470 } 3823 }
3471 } 3824 }
3825 finally
3826 {
3827 lockPartsForRead(false);
3828 }
3472 3829
3473 for (int ctr = 0; ctr < localids.Length; ctr++) 3830 for (int ctr = 0; ctr < localids.Length; ctr++)
3474 { 3831 {
@@ -3482,19 +3839,20 @@ namespace OpenSim.Region.Framework.Scenes
3482 public float GetMass() 3839 public float GetMass()
3483 { 3840 {
3484 float retmass = 0f; 3841 float retmass = 0f;
3485 lock (m_parts) 3842 lockPartsForRead(true);
3486 { 3843 {
3487 foreach (SceneObjectPart part in m_parts.Values) 3844 foreach (SceneObjectPart part in m_parts.Values)
3488 { 3845 {
3489 retmass += part.GetMass(); 3846 retmass += part.GetMass();
3490 } 3847 }
3491 } 3848 }
3849 lockPartsForRead(false);
3492 return retmass; 3850 return retmass;
3493 } 3851 }
3494 3852
3495 public void CheckSculptAndLoad() 3853 public void CheckSculptAndLoad()
3496 { 3854 {
3497 lock (m_parts) 3855 lockPartsForRead(true);
3498 { 3856 {
3499 if (!IsDeleted) 3857 if (!IsDeleted)
3500 { 3858 {
@@ -3519,6 +3877,7 @@ namespace OpenSim.Region.Framework.Scenes
3519 } 3877 }
3520 } 3878 }
3521 } 3879 }
3880 lockPartsForRead(false);
3522 } 3881 }
3523 3882
3524 protected void AssetReceived(string id, Object sender, AssetBase asset) 3883 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3539,7 +3898,7 @@ namespace OpenSim.Region.Framework.Scenes
3539 /// <param name="client"></param> 3898 /// <param name="client"></param>
3540 public void SetGroup(UUID GroupID, IClientAPI client) 3899 public void SetGroup(UUID GroupID, IClientAPI client)
3541 { 3900 {
3542 lock (m_parts) 3901 lockPartsForRead(true);
3543 { 3902 {
3544 foreach (SceneObjectPart part in m_parts.Values) 3903 foreach (SceneObjectPart part in m_parts.Values)
3545 { 3904 {
@@ -3549,6 +3908,7 @@ namespace OpenSim.Region.Framework.Scenes
3549 3908
3550 HasGroupChanged = true; 3909 HasGroupChanged = true;
3551 } 3910 }
3911 lockPartsForRead(false);
3552 3912
3553 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3913 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3554 // for the same object with very different properties. The caller must schedule the update. 3914 // for the same object with very different properties. The caller must schedule the update.
@@ -3570,11 +3930,12 @@ namespace OpenSim.Region.Framework.Scenes
3570 3930
3571 public void SetAttachmentPoint(byte point) 3931 public void SetAttachmentPoint(byte point)
3572 { 3932 {
3573 lock (m_parts) 3933 lockPartsForRead(true);
3574 { 3934 {
3575 foreach (SceneObjectPart part in m_parts.Values) 3935 foreach (SceneObjectPart part in m_parts.Values)
3576 part.SetAttachmentPoint(point); 3936 part.SetAttachmentPoint(point);
3577 } 3937 }
3938 lockPartsForRead(false);
3578 } 3939 }
3579 3940
3580 #region ISceneObject 3941 #region ISceneObject
@@ -3608,6 +3969,14 @@ namespace OpenSim.Region.Framework.Scenes
3608 SetFromItemID(uuid); 3969 SetFromItemID(uuid);
3609 } 3970 }
3610 3971
3972 public void ResetOwnerChangeFlag()
3973 {
3974 ForEachPart(delegate(SceneObjectPart part)
3975 {
3976 part.ResetOwnerChangeFlag();
3977 });
3978 }
3979
3611 #endregion 3980 #endregion
3612 } 3981 }
3613} 3982}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 13e4b56..f8ae321 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
@@ -277,6 +277,7 @@ namespace OpenSim.Region.Framework.Scenes
277 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 277 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
278 private Vector3 m_sitTargetPosition; 278 private Vector3 m_sitTargetPosition;
279 private string m_sitAnimation = "SIT"; 279 private string m_sitAnimation = "SIT";
280 private bool m_occupied; // KF if any av is sitting on this prim
280 private string m_text = String.Empty; 281 private string m_text = String.Empty;
281 private string m_touchName = String.Empty; 282 private string m_touchName = String.Empty;
282 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 283 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
@@ -360,7 +361,7 @@ namespace OpenSim.Region.Framework.Scenes
360 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 361 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
361 Quaternion rotationOffset, Vector3 offsetPosition) 362 Quaternion rotationOffset, Vector3 offsetPosition)
362 { 363 {
363 m_name = "Primitive"; 364 m_name = "Object";
364 365
365 Rezzed = DateTime.UtcNow; 366 Rezzed = DateTime.UtcNow;
366 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 367 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
@@ -456,12 +457,16 @@ namespace OpenSim.Region.Framework.Scenes
456 } 457 }
457 458
458 /// <value> 459 /// <value>
459 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 460 /// Get the inventory list
460 /// </value> 461 /// </value>
461 public TaskInventoryDictionary TaskInventory 462 public TaskInventoryDictionary TaskInventory
462 { 463 {
463 get { return m_inventory.Items; } 464 get {
464 set { m_inventory.Items = value; } 465 return m_inventory.Items;
466 }
467 set {
468 m_inventory.Items = value;
469 }
465 } 470 }
466 471
467 public uint ObjectFlags 472 public uint ObjectFlags
@@ -590,14 +595,12 @@ namespace OpenSim.Region.Framework.Scenes
590 set { m_LoopSoundSlavePrims = value; } 595 set { m_LoopSoundSlavePrims = value; }
591 } 596 }
592 597
593 [XmlIgnore]
594 public Byte[] TextureAnimation 598 public Byte[] TextureAnimation
595 { 599 {
596 get { return m_TextureAnimation; } 600 get { return m_TextureAnimation; }
597 set { m_TextureAnimation = value; } 601 set { m_TextureAnimation = value; }
598 } 602 }
599 603
600 [XmlIgnore]
601 public Byte[] ParticleSystem 604 public Byte[] ParticleSystem
602 { 605 {
603 get { return m_particleSystem; } 606 get { return m_particleSystem; }
@@ -651,7 +654,6 @@ namespace OpenSim.Region.Framework.Scenes
651 set 654 set
652 { 655 {
653 m_groupPosition = value; 656 m_groupPosition = value;
654
655 PhysicsActor actor = PhysActor; 657 PhysicsActor actor = PhysActor;
656 if (actor != null) 658 if (actor != null)
657 { 659 {
@@ -698,7 +700,7 @@ namespace OpenSim.Region.Framework.Scenes
698 get { return m_offsetPosition; } 700 get { return m_offsetPosition; }
699 set 701 set
700 { 702 {
701 StoreUndoState(); 703 StoreUndoState(UndoType.STATE_PRIM_POSITION);
702 m_offsetPosition = value; 704 m_offsetPosition = value;
703 705
704 if (ParentGroup != null && !ParentGroup.IsDeleted) 706 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -712,6 +714,12 @@ namespace OpenSim.Region.Framework.Scenes
712 // Tell the physics engines that this prim changed. 714 // Tell the physics engines that this prim changed.
713 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 715 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
714 } 716 }
717
718 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
719 foreach (ScenePresence av in avs)
720 {
721 av.SendFullUpdateToAllClients();
722 }
715 } 723 }
716 } 724 }
717 } 725 }
@@ -754,7 +762,7 @@ namespace OpenSim.Region.Framework.Scenes
754 762
755 set 763 set
756 { 764 {
757 StoreUndoState(); 765 StoreUndoState(UndoType.STATE_PRIM_ROTATION);
758 m_rotationOffset = value; 766 m_rotationOffset = value;
759 767
760 PhysicsActor actor = PhysActor; 768 PhysicsActor actor = PhysActor;
@@ -838,7 +846,16 @@ namespace OpenSim.Region.Framework.Scenes
838 /// <summary></summary> 846 /// <summary></summary>
839 public Vector3 Acceleration 847 public Vector3 Acceleration
840 { 848 {
841 get { return m_acceleration; } 849 get
850 {
851 PhysicsActor actor = PhysActor;
852 if (actor != null)
853 {
854 m_acceleration = actor.Acceleration;
855 }
856 return m_acceleration;
857 }
858
842 set { m_acceleration = value; } 859 set { m_acceleration = value; }
843 } 860 }
844 861
@@ -865,7 +882,6 @@ namespace OpenSim.Region.Framework.Scenes
865 set 882 set
866 { 883 {
867 m_color = value; 884 m_color = value;
868 TriggerScriptChangedEvent(Changed.COLOR);
869 885
870 /* ScheduleFullUpdate() need not be called b/c after 886 /* ScheduleFullUpdate() need not be called b/c after
871 * setting the color, the text will be set, so then 887 * setting the color, the text will be set, so then
@@ -944,7 +960,7 @@ namespace OpenSim.Region.Framework.Scenes
944 get { return m_shape.Scale; } 960 get { return m_shape.Scale; }
945 set 961 set
946 { 962 {
947 StoreUndoState(); 963 StoreUndoState(UndoType.STATE_PRIM_SCALE);
948 if (m_shape != null) 964 if (m_shape != null)
949 { 965 {
950 m_shape.Scale = value; 966 m_shape.Scale = value;
@@ -989,7 +1005,8 @@ namespace OpenSim.Region.Framework.Scenes
989 if (IsAttachment) 1005 if (IsAttachment)
990 return GroupPosition; 1006 return GroupPosition;
991 1007
992 return m_offsetPosition + m_groupPosition; } 1008// return m_offsetPosition + m_groupPosition; }
1009 return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored!
993 } 1010 }
994 1011
995 public SceneObjectGroup ParentGroup 1012 public SceneObjectGroup ParentGroup
@@ -1140,6 +1157,13 @@ namespace OpenSim.Region.Framework.Scenes
1140 get { return _flags; } 1157 get { return _flags; }
1141 set { _flags = value; } 1158 set { _flags = value; }
1142 } 1159 }
1160
1161 [XmlIgnore]
1162 public bool IsOccupied // KF If an av is sittingon this prim
1163 {
1164 get { return m_occupied; }
1165 set { m_occupied = value; }
1166 }
1143 1167
1144 [XmlIgnore] 1168 [XmlIgnore]
1145 public UUID SitTargetAvatar 1169 public UUID SitTargetAvatar
@@ -1215,14 +1239,6 @@ namespace OpenSim.Region.Framework.Scenes
1215 } 1239 }
1216 } 1240 }
1217 1241
1218 /// <summary>
1219 /// Clear all pending updates of parts to clients
1220 /// </summary>
1221 private void ClearUpdateSchedule()
1222 {
1223 m_updateFlag = 0;
1224 }
1225
1226 private void SendObjectPropertiesToClient(UUID AgentID) 1242 private void SendObjectPropertiesToClient(UUID AgentID)
1227 { 1243 {
1228 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1244 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1508,7 +1524,7 @@ namespace OpenSim.Region.Framework.Scenes
1508 { 1524 {
1509 m_redo.Clear(); 1525 m_redo.Clear();
1510 } 1526 }
1511 StoreUndoState(); 1527 StoreUndoState(UndoType.STATE_ALL);
1512 } 1528 }
1513 1529
1514 public byte ConvertScriptUintToByte(uint indata) 1530 public byte ConvertScriptUintToByte(uint indata)
@@ -1611,7 +1627,7 @@ namespace OpenSim.Region.Framework.Scenes
1611 PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); 1627 PrimitiveBaseShape shape = PrimitiveBaseShape.Create();
1612 part.Shape = shape; 1628 part.Shape = shape;
1613 1629
1614 part.Name = "Primitive"; 1630 part.Name = "Object";
1615 part._ownerID = UUID.Random(); 1631 part._ownerID = UUID.Random();
1616 1632
1617 return part; 1633 return part;
@@ -1734,7 +1750,7 @@ namespace OpenSim.Region.Framework.Scenes
1734 // which stops client-side interpolation of deactivated joint proxy objects. 1750 // which stops client-side interpolation of deactivated joint proxy objects.
1735 } 1751 }
1736 1752
1737 if (!UsePhysics && !isNew) 1753 if (!UsePhysics)
1738 { 1754 {
1739 // reset velocity to 0 on physics switch-off. Without that, the client thinks the 1755 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
1740 // prim still has velocity and continues to interpolate its position along the old 1756 // prim still has velocity and continues to interpolate its position along the old
@@ -1969,12 +1985,17 @@ namespace OpenSim.Region.Framework.Scenes
1969 public Vector3 GetWorldPosition() 1985 public Vector3 GetWorldPosition()
1970 { 1986 {
1971 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 1987 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1972
1973 Vector3 axPos = OffsetPosition; 1988 Vector3 axPos = OffsetPosition;
1974
1975 axPos *= parentRot; 1989 axPos *= parentRot;
1976 Vector3 translationOffsetPosition = axPos; 1990 Vector3 translationOffsetPosition = axPos;
1977 return GroupPosition + translationOffsetPosition; 1991 if(_parentID == 0)
1992 {
1993 return GroupPosition;
1994 }
1995 else
1996 {
1997 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
1998 }
1978 } 1999 }
1979 2000
1980 /// <summary> 2001 /// <summary>
@@ -1985,7 +2006,7 @@ namespace OpenSim.Region.Framework.Scenes
1985 { 2006 {
1986 Quaternion newRot; 2007 Quaternion newRot;
1987 2008
1988 if (this.LinkNum == 0) 2009 if (this.LinkNum < 2) //KF Single or root prim
1989 { 2010 {
1990 newRot = RotationOffset; 2011 newRot = RotationOffset;
1991 } 2012 }
@@ -2631,17 +2652,18 @@ namespace OpenSim.Region.Framework.Scenes
2631 //Trys to fetch sound id from prim's inventory. 2652 //Trys to fetch sound id from prim's inventory.
2632 //Prim's inventory doesn't support non script items yet 2653 //Prim's inventory doesn't support non script items yet
2633 2654
2634 lock (TaskInventory) 2655 TaskInventory.LockItemsForRead(true);
2656
2657 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2635 { 2658 {
2636 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2659 if (item.Value.Name == sound)
2637 { 2660 {
2638 if (item.Value.Name == sound) 2661 soundID = item.Value.ItemID;
2639 { 2662 break;
2640 soundID = item.Value.ItemID;
2641 break;
2642 }
2643 } 2663 }
2644 } 2664 }
2665
2666 TaskInventory.LockItemsForRead(false);
2645 } 2667 }
2646 2668
2647 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2669 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2701,7 +2723,7 @@ namespace OpenSim.Region.Framework.Scenes
2701 /// <param name="scale"></param> 2723 /// <param name="scale"></param>
2702 public void Resize(Vector3 scale) 2724 public void Resize(Vector3 scale)
2703 { 2725 {
2704 StoreUndoState(); 2726 StoreUndoState(UndoType.STATE_PRIM_SCALE);
2705 m_shape.Scale = scale; 2727 m_shape.Scale = scale;
2706 2728
2707 ParentGroup.HasGroupChanged = true; 2729 ParentGroup.HasGroupChanged = true;
@@ -2710,38 +2732,7 @@ namespace OpenSim.Region.Framework.Scenes
2710 2732
2711 public void RotLookAt(Quaternion target, float strength, float damping) 2733 public void RotLookAt(Quaternion target, float strength, float damping)
2712 { 2734 {
2713 rotLookAt(target, strength, damping); 2735 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2714 }
2715
2716 public void rotLookAt(Quaternion target, float strength, float damping)
2717 {
2718 if (IsAttachment)
2719 {
2720 /*
2721 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2722 if (avatar != null)
2723 {
2724 Rotate the Av?
2725 } */
2726 }
2727 else
2728 {
2729 APIDDamp = damping;
2730 APIDStrength = strength;
2731 APIDTarget = target;
2732 }
2733 }
2734
2735 public void startLookAt(Quaternion rot, float damp, float strength)
2736 {
2737 APIDDamp = damp;
2738 APIDStrength = strength;
2739 APIDTarget = rot;
2740 }
2741
2742 public void stopLookAt()
2743 {
2744 APIDTarget = Quaternion.Identity;
2745 } 2736 }
2746 2737
2747 /// <summary> 2738 /// <summary>
@@ -2753,7 +2744,10 @@ namespace OpenSim.Region.Framework.Scenes
2753 2744
2754 if (m_parentGroup != null) 2745 if (m_parentGroup != null)
2755 { 2746 {
2756 m_parentGroup.QueueForUpdateCheck(); 2747 if (!m_parentGroup.areUpdatesSuspended)
2748 {
2749 m_parentGroup.QueueForUpdateCheck();
2750 }
2757 } 2751 }
2758 2752
2759 int timeNow = Util.UnixTimeSinceEpoch(); 2753 int timeNow = Util.UnixTimeSinceEpoch();
@@ -2970,8 +2964,8 @@ namespace OpenSim.Region.Framework.Scenes
2970 { 2964 {
2971 const float ROTATION_TOLERANCE = 0.01f; 2965 const float ROTATION_TOLERANCE = 0.01f;
2972 const float VELOCITY_TOLERANCE = 0.001f; 2966 const float VELOCITY_TOLERANCE = 0.001f;
2973 const float POSITION_TOLERANCE = 0.05f; 2967 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2974 const int TIME_MS_TOLERANCE = 3000; 2968 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2975 2969
2976 if (m_updateFlag == 1) 2970 if (m_updateFlag == 1)
2977 { 2971 {
@@ -2985,7 +2979,7 @@ namespace OpenSim.Region.Framework.Scenes
2985 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 2979 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
2986 { 2980 {
2987 AddTerseUpdateToAllAvatars(); 2981 AddTerseUpdateToAllAvatars();
2988 ClearUpdateSchedule(); 2982
2989 2983
2990 // This causes the Scene to 'poll' physical objects every couple of frames 2984 // This causes the Scene to 'poll' physical objects every couple of frames
2991 // bad, so it's been replaced by an event driven method. 2985 // bad, so it's been replaced by an event driven method.
@@ -3003,16 +2997,18 @@ namespace OpenSim.Region.Framework.Scenes
3003 m_lastAngularVelocity = AngularVelocity; 2997 m_lastAngularVelocity = AngularVelocity;
3004 m_lastTerseSent = Environment.TickCount; 2998 m_lastTerseSent = Environment.TickCount;
3005 } 2999 }
3000 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
3001 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
3006 } 3002 }
3007 else 3003 else
3008 { 3004 {
3009 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 3005 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3010 { 3006 {
3011 AddFullUpdateToAllAvatars(); 3007 AddFullUpdateToAllAvatars();
3012 ClearUpdateSchedule(); 3008 m_updateFlag = 0; //Same here
3013 } 3009 }
3014 } 3010 }
3015 ClearUpdateSchedule(); 3011 m_updateFlag = 0;
3016 } 3012 }
3017 3013
3018 /// <summary> 3014 /// <summary>
@@ -3039,17 +3035,16 @@ namespace OpenSim.Region.Framework.Scenes
3039 if (!UUID.TryParse(sound, out soundID)) 3035 if (!UUID.TryParse(sound, out soundID))
3040 { 3036 {
3041 // search sound file from inventory 3037 // search sound file from inventory
3042 lock (TaskInventory) 3038 TaskInventory.LockItemsForRead(true);
3039 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3043 { 3040 {
3044 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3041 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3045 { 3042 {
3046 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3043 soundID = item.Value.ItemID;
3047 { 3044 break;
3048 soundID = item.Value.ItemID;
3049 break;
3050 }
3051 } 3045 }
3052 } 3046 }
3047 TaskInventory.LockItemsForRead(false);
3053 } 3048 }
3054 3049
3055 if (soundID == UUID.Zero) 3050 if (soundID == UUID.Zero)
@@ -3484,7 +3479,7 @@ namespace OpenSim.Region.Framework.Scenes
3484 3479
3485 public void StopLookAt() 3480 public void StopLookAt()
3486 { 3481 {
3487 m_parentGroup.stopLookAt(); 3482 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3488 3483
3489 m_parentGroup.ScheduleGroupForTerseUpdate(); 3484 m_parentGroup.ScheduleGroupForTerseUpdate();
3490 } 3485 }
@@ -3511,10 +3506,9 @@ namespace OpenSim.Region.Framework.Scenes
3511 m_parentGroup.ScheduleGroupForTerseUpdate(); 3506 m_parentGroup.ScheduleGroupForTerseUpdate();
3512 //m_parentGroup.ScheduleGroupForFullUpdate(); 3507 //m_parentGroup.ScheduleGroupForFullUpdate();
3513 } 3508 }
3514 3509 public void StoreUndoState(UndoType type)
3515 public void StoreUndoState()
3516 { 3510 {
3517 if (!Undoing) 3511 if (!Undoing && (m_parentGroup == null || m_parentGroup.RootPart == null || !m_parentGroup.RootPart.Undoing))
3518 { 3512 {
3519 if (!IgnoreUndoUpdate) 3513 if (!IgnoreUndoUpdate)
3520 { 3514 {
@@ -3525,17 +3519,25 @@ namespace OpenSim.Region.Framework.Scenes
3525 if (m_undo.Count > 0) 3519 if (m_undo.Count > 0)
3526 { 3520 {
3527 UndoState last = m_undo.Peek(); 3521 UndoState last = m_undo.Peek();
3528 if (last != null) 3522
3529 {
3530 if (last.Compare(this))
3531 return;
3532 }
3533 } 3523 }
3534 3524
3535 if (m_parentGroup.GetSceneMaxUndo() > 0) 3525 if (m_parentGroup.GetSceneMaxUndo() > 0)
3536 { 3526 {
3537 UndoState nUndo = new UndoState(this); 3527 UndoState lastUndo = m_undo.Peek();
3538 3528
3529 UndoState nUndo = new UndoState(this, type);
3530
3531 if (lastUndo != null)
3532 {
3533 TimeSpan ts = DateTime.Now.Subtract(lastUndo.LastUpdated);
3534 if (ts.TotalMilliseconds < 500)
3535 {
3536 //Delete the last entry since it was less than 500 milliseconds ago
3537 nUndo.Merge(lastUndo);
3538 m_undo.Pop();
3539 }
3540 }
3539 m_undo.Push(nUndo); 3541 m_undo.Push(nUndo);
3540 } 3542 }
3541 3543
@@ -4012,11 +4014,13 @@ namespace OpenSim.Region.Framework.Scenes
4012 if (m_undo.Count > 0) 4014 if (m_undo.Count > 0)
4013 { 4015 {
4014 UndoState nUndo = null; 4016 UndoState nUndo = null;
4017 UndoState goback = m_undo.Pop();
4015 if (m_parentGroup.GetSceneMaxUndo() > 0) 4018 if (m_parentGroup.GetSceneMaxUndo() > 0)
4016 { 4019 {
4017 nUndo = new UndoState(this); 4020 nUndo = new UndoState(this, goback.Type);
4018 } 4021 }
4019 UndoState goback = m_undo.Pop(); 4022
4023
4020 if (goback != null) 4024 if (goback != null)
4021 { 4025 {
4022 goback.PlaybackState(this); 4026 goback.PlaybackState(this);
@@ -4031,13 +4035,13 @@ namespace OpenSim.Region.Framework.Scenes
4031 { 4035 {
4032 lock (m_redo) 4036 lock (m_redo)
4033 { 4037 {
4038 UndoState gofwd = m_redo.Pop();
4034 if (m_parentGroup.GetSceneMaxUndo() > 0) 4039 if (m_parentGroup.GetSceneMaxUndo() > 0)
4035 { 4040 {
4036 UndoState nUndo = new UndoState(this); 4041 UndoState nUndo = new UndoState(this, gofwd.Type);
4037 4042
4038 m_undo.Push(nUndo); 4043 m_undo.Push(nUndo);
4039 } 4044 }
4040 UndoState gofwd = m_redo.Pop();
4041 if (gofwd != null) 4045 if (gofwd != null)
4042 gofwd.PlayfwdState(this); 4046 gofwd.PlayfwdState(this);
4043 } 4047 }
@@ -4482,8 +4486,9 @@ namespace OpenSim.Region.Framework.Scenes
4482 { 4486 {
4483 m_shape.TextureEntry = textureEntry; 4487 m_shape.TextureEntry = textureEntry;
4484 TriggerScriptChangedEvent(Changed.TEXTURE); 4488 TriggerScriptChangedEvent(Changed.TEXTURE);
4485 4489 m_updateFlag = 1;
4486 ParentGroup.HasGroupChanged = true; 4490 ParentGroup.HasGroupChanged = true;
4491
4487 //This is madness.. 4492 //This is madness..
4488 //ParentGroup.ScheduleGroupForFullUpdate(); 4493 //ParentGroup.ScheduleGroupForFullUpdate();
4489 //This is sparta 4494 //This is sparta
@@ -4728,5 +4733,17 @@ namespace OpenSim.Region.Framework.Scenes
4728 Color color = Color; 4733 Color color = Color;
4729 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4734 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4730 } 4735 }
4736
4737 public void ResetOwnerChangeFlag()
4738 {
4739 List<UUID> inv = Inventory.GetInventoryList();
4740
4741 foreach (UUID itemID in inv)
4742 {
4743 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4744 item.OwnerChanged = false;
4745 Inventory.UpdateInventoryItem(item);
4746 }
4747 }
4731 } 4748 }
4732} 4749}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index cabcf37..0066158 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,89 +1039,75 @@ 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)
954 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
955 }
956 item.CurrentPermissions &= item.NextPermissions;
957 item.BasePermissions &= item.NextPermissions;
958 item.EveryonePermissions &= item.NextPermissions;
959 item.OwnerChanged = true;
960 } 1085 }
1086 item.OwnerChanged = true;
1087 item.CurrentPermissions &= item.NextPermissions;
1088 item.BasePermissions &= item.NextPermissions;
1089 item.EveryonePermissions &= item.NextPermissions;
961 } 1090 }
962 } 1091 }
963 1092
964 public void ApplyGodPermissions(uint perms) 1093 public void ApplyGodPermissions(uint perms)
965 { 1094 {
966 lock (m_items) 1095 foreach (TaskInventoryItem item in m_items.Values)
967 { 1096 {
968 foreach (TaskInventoryItem item in m_items.Values) 1097 item.CurrentPermissions = perms;
969 { 1098 item.BasePermissions = perms;
970 item.CurrentPermissions = perms;
971 item.BasePermissions = perms;
972 }
973 } 1099 }
974 } 1100 }
975 1101
976 public bool ContainsScripts() 1102 public bool ContainsScripts()
977 { 1103 {
978 lock (m_items) 1104 foreach (TaskInventoryItem item in m_items.Values)
979 { 1105 {
980 foreach (TaskInventoryItem item in m_items.Values) 1106 if (item.InvType == (int)InventoryType.LSL)
981 { 1107 {
982 if (item.InvType == (int)InventoryType.LSL) 1108 return true;
983 {
984 return true;
985 }
986 } 1109 }
987 } 1110 }
988
989 return false; 1111 return false;
990 } 1112 }
991 1113
@@ -993,46 +1115,52 @@ namespace OpenSim.Region.Framework.Scenes
993 { 1115 {
994 List<UUID> ret = new List<UUID>(); 1116 List<UUID> ret = new List<UUID>();
995 1117
996 lock (m_items) 1118 foreach (TaskInventoryItem item in m_items.Values)
997 { 1119 ret.Add(item.ItemID);
998 foreach (TaskInventoryItem item in m_items.Values)
999 ret.Add(item.ItemID);
1000 }
1001 1120
1002 return ret; 1121 return ret;
1003 } 1122 }
1004 1123
1005 public Dictionary<UUID, string> GetScriptStates() 1124 public Dictionary<UUID, string> GetScriptStates()
1006 { 1125 {
1126 return GetScriptStates(false);
1127 }
1128
1129 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1130 {
1007 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 1131 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
1008 1132
1009 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1133 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1010 if (engines == null) // No engine at all 1134 if (engines == null) // No engine at all
1011 return ret; 1135 return ret;
1012 1136
1013 lock (m_items) 1137 foreach (TaskInventoryItem item in m_items.Values)
1014 { 1138 {
1015 foreach (TaskInventoryItem item in m_items.Values) 1139 if (item.InvType == (int)InventoryType.LSL)
1016 { 1140 {
1017 if (item.InvType == (int)InventoryType.LSL) 1141 foreach (IScriptModule e in engines)
1018 { 1142 {
1019 foreach (IScriptModule e in engines) 1143 if (e != null)
1020 { 1144 {
1021 if (e != null) 1145 string n = e.GetXMLState(item.ItemID);
1146 if (n != String.Empty)
1022 { 1147 {
1023 string n = e.GetXMLState(item.ItemID); 1148 if (oldIDs)
1024 if (n != String.Empty) 1149 {
1150 if (!ret.ContainsKey(item.OldItemID))
1151 ret[item.OldItemID] = n;
1152 }
1153 else
1025 { 1154 {
1026 if (!ret.ContainsKey(item.ItemID)) 1155 if (!ret.ContainsKey(item.ItemID))
1027 ret[item.ItemID] = n; 1156 ret[item.ItemID] = n;
1028 break;
1029 } 1157 }
1158 break;
1030 } 1159 }
1031 } 1160 }
1032 } 1161 }
1033 } 1162 }
1034 } 1163 }
1035
1036 return ret; 1164 return ret;
1037 } 1165 }
1038 1166
@@ -1042,25 +1170,27 @@ namespace OpenSim.Region.Framework.Scenes
1042 if (engines == null) 1170 if (engines == null)
1043 return; 1171 return;
1044 1172
1045 lock (m_items) 1173
1174 Items.LockItemsForRead(true);
1175
1176 foreach (TaskInventoryItem item in m_items.Values)
1046 { 1177 {
1047 foreach (TaskInventoryItem item in m_items.Values) 1178 if (item.InvType == (int)InventoryType.LSL)
1048 { 1179 {
1049 if (item.InvType == (int)InventoryType.LSL) 1180 foreach (IScriptModule engine in engines)
1050 { 1181 {
1051 foreach (IScriptModule engine in engines) 1182 if (engine != null)
1052 { 1183 {
1053 if (engine != null) 1184 if (item.OwnerChanged)
1054 { 1185 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1055 if (item.OwnerChanged) 1186 item.OwnerChanged = false;
1056 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1187 engine.ResumeScript(item.ItemID);
1057 item.OwnerChanged = false;
1058 engine.ResumeScript(item.ItemID);
1059 }
1060 } 1188 }
1061 } 1189 }
1062 } 1190 }
1063 } 1191 }
1192
1193 Items.LockItemsForRead(false);
1064 } 1194 }
1065 } 1195 }
1066} 1196}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 1e8ce22..efe3365 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;
@@ -72,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes
72// { 73// {
73// m_log.Debug("[ScenePresence] Destructor called"); 74// m_log.Debug("[ScenePresence] Destructor called");
74// } 75// }
75 76
76 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
77 78
78 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; 79 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
@@ -88,7 +89,9 @@ namespace OpenSim.Region.Framework.Scenes
88 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 89 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
89 /// issue #1716 90 /// issue #1716
90 /// </summary> 91 /// </summary>
91 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); 92// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
93 // Value revised by KF 091121 by comparison with SL.
94 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
92 95
93 public UUID currentParcelUUID = UUID.Zero; 96 public UUID currentParcelUUID = UUID.Zero;
94 97
@@ -122,8 +125,11 @@ namespace OpenSim.Region.Framework.Scenes
122 public Vector3 lastKnownAllowedPosition; 125 public Vector3 lastKnownAllowedPosition;
123 public bool sentMessageAboutRestrictedParcelFlyingDown; 126 public bool sentMessageAboutRestrictedParcelFlyingDown;
124 public Vector4 CollisionPlane = Vector4.UnitW; 127 public Vector4 CollisionPlane = Vector4.UnitW;
125 128
129 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
130 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
126 private Vector3 m_lastPosition; 131 private Vector3 m_lastPosition;
132 private Vector3 m_lastWorldPosition;
127 private Quaternion m_lastRotation; 133 private Quaternion m_lastRotation;
128 private Vector3 m_lastVelocity; 134 private Vector3 m_lastVelocity;
129 //private int m_lastTerseSent; 135 //private int m_lastTerseSent;
@@ -156,7 +162,6 @@ namespace OpenSim.Region.Framework.Scenes
156 private int m_perfMonMS; 162 private int m_perfMonMS;
157 163
158 private bool m_setAlwaysRun; 164 private bool m_setAlwaysRun;
159
160 private bool m_forceFly; 165 private bool m_forceFly;
161 private bool m_flyDisabled; 166 private bool m_flyDisabled;
162 167
@@ -180,7 +185,8 @@ namespace OpenSim.Region.Framework.Scenes
180 protected RegionInfo m_regionInfo; 185 protected RegionInfo m_regionInfo;
181 protected ulong crossingFromRegion; 186 protected ulong crossingFromRegion;
182 187
183 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 188 private readonly Vector3[] Dir_Vectors = new Vector3[11];
189 private bool m_isNudging = false;
184 190
185 // Position of agent's camera in world (region cordinates) 191 // Position of agent's camera in world (region cordinates)
186 protected Vector3 m_CameraCenter; 192 protected Vector3 m_CameraCenter;
@@ -205,17 +211,23 @@ namespace OpenSim.Region.Framework.Scenes
205 private bool m_autopilotMoving; 211 private bool m_autopilotMoving;
206 private Vector3 m_autoPilotTarget; 212 private Vector3 m_autoPilotTarget;
207 private bool m_sitAtAutoTarget; 213 private bool m_sitAtAutoTarget;
214 private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
208 215
209 private string m_nextSitAnimation = String.Empty; 216 private string m_nextSitAnimation = String.Empty;
210 217
211 //PauPaw:Proper PID Controler for autopilot************ 218 //PauPaw:Proper PID Controler for autopilot************
212 private bool m_moveToPositionInProgress; 219 private bool m_moveToPositionInProgress;
213 private Vector3 m_moveToPositionTarget; 220 private Vector3 m_moveToPositionTarget;
221 private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
214 222
215 private bool m_followCamAuto; 223 private bool m_followCamAuto;
216 224
217 private int m_movementUpdateCount; 225 private int m_movementUpdateCount;
226 private int m_lastColCount = -1; //KF: Look for Collision chnages
227 private int m_updateCount = 0; //KF: Update Anims for a while
228 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
218 private const int NumMovementsBetweenRayCast = 5; 229 private const int NumMovementsBetweenRayCast = 5;
230 private List<uint> m_lastColliders = new List<uint>();
219 231
220 private bool CameraConstraintActive; 232 private bool CameraConstraintActive;
221 //private int m_moveToPositionStateStatus; 233 //private int m_moveToPositionStateStatus;
@@ -242,7 +254,9 @@ namespace OpenSim.Region.Framework.Scenes
242 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 254 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
243 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 255 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
244 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 256 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
245 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 257 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
258 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
259 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
246 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 260 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
247 } 261 }
248 262
@@ -449,9 +463,18 @@ namespace OpenSim.Region.Framework.Scenes
449 get 463 get
450 { 464 {
451 PhysicsActor actor = m_physicsActor; 465 PhysicsActor actor = m_physicsActor;
452 if (actor != null) 466// if (actor != null)
467 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
453 m_pos = actor.Position; 468 m_pos = actor.Position;
454 469
470 // If we're sitting, we need to update our position
471 if (m_parentID != 0)
472 {
473 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
474 if (part != null)
475 m_parentPosition = part.AbsolutePosition;
476 }
477
455 return m_parentPosition + m_pos; 478 return m_parentPosition + m_pos;
456 } 479 }
457 set 480 set
@@ -470,7 +493,8 @@ namespace OpenSim.Region.Framework.Scenes
470 } 493 }
471 } 494 }
472 495
473 m_pos = value; 496 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
497 m_pos = value;
474 m_parentPosition = Vector3.Zero; 498 m_parentPosition = Vector3.Zero;
475 } 499 }
476 } 500 }
@@ -514,10 +538,39 @@ namespace OpenSim.Region.Framework.Scenes
514 } 538 }
515 } 539 }
516 540
541 public Quaternion OffsetRotation
542 {
543 get { return m_offsetRotation; }
544 set { m_offsetRotation = value; }
545 }
546
517 public Quaternion Rotation 547 public Quaternion Rotation
518 { 548 {
519 get { return m_bodyRot; } 549 get {
520 set { m_bodyRot = value; } 550 if (m_parentID != 0)
551 {
552 if (m_offsetRotation != null)
553 {
554 return m_offsetRotation;
555 }
556 else
557 {
558 return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
559 }
560
561 }
562 else
563 {
564 return m_bodyRot;
565 }
566 }
567 set {
568 m_bodyRot = value;
569 if (m_parentID != 0)
570 {
571 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
572 }
573 }
521 } 574 }
522 575
523 public Quaternion PreviousRotation 576 public Quaternion PreviousRotation
@@ -668,7 +721,7 @@ namespace OpenSim.Region.Framework.Scenes
668 CreateSceneViewer(); 721 CreateSceneViewer();
669 m_animator = new ScenePresenceAnimator(this); 722 m_animator = new ScenePresenceAnimator(this);
670 } 723 }
671 724
672 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() 725 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
673 { 726 {
674 m_rootRegionHandle = reginfo.RegionHandle; 727 m_rootRegionHandle = reginfo.RegionHandle;
@@ -700,16 +753,16 @@ namespace OpenSim.Region.Framework.Scenes
700 m_reprioritization_timer.AutoReset = false; 753 m_reprioritization_timer.AutoReset = false;
701 754
702 AdjustKnownSeeds(); 755 AdjustKnownSeeds();
703
704 // TODO: I think, this won't send anything, as we are still a child here...
705 Animator.TrySetMovementAnimation("STAND"); 756 Animator.TrySetMovementAnimation("STAND");
706
707 // we created a new ScenePresence (a new child agent) in a fresh region. 757 // we created a new ScenePresence (a new child agent) in a fresh region.
708 // Request info about all the (root) agents in this region 758 // Request info about all the (root) agents in this region
709 // Note: This won't send data *to* other clients in that region (children don't send) 759 // Note: This won't send data *to* other clients in that region (children don't send)
710 SendInitialFullUpdateToAllClients(); 760 SendInitialFullUpdateToAllClients();
711
712 RegisterToEvents(); 761 RegisterToEvents();
762 if (m_controllingClient != null)
763 {
764 m_controllingClient.ProcessPendingPackets();
765 }
713 SetDirectionVectors(); 766 SetDirectionVectors();
714 } 767 }
715 768
@@ -759,25 +812,47 @@ namespace OpenSim.Region.Framework.Scenes
759 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 812 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
760 Dir_Vectors[4] = Vector3.UnitZ; //UP 813 Dir_Vectors[4] = Vector3.UnitZ; //UP
761 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 814 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
762 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 815 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
763 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 816 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
764 Dir_Vectors[7] = -Vector3.UnitX; //BACK 817 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
818 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
819 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
765 } 820 }
766 821
767 private Vector3[] GetWalkDirectionVectors() 822 private Vector3[] GetWalkDirectionVectors()
768 { 823 {
769 Vector3[] vector = new Vector3[9]; 824 Vector3[] vector = new Vector3[11];
770 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 825 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
771 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 826 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
772 vector[2] = Vector3.UnitY; //LEFT 827 vector[2] = Vector3.UnitY; //LEFT
773 vector[3] = -Vector3.UnitY; //RIGHT 828 vector[3] = -Vector3.UnitY; //RIGHT
774 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 829 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
775 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 830 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
776 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 831 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
777 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 832 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
778 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 833 vector[8] = Vector3.UnitY; //LEFT_NUDGE
834 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
835 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
779 return vector; 836 return vector;
780 } 837 }
838
839 private bool[] GetDirectionIsNudge()
840 {
841 bool[] isNudge = new bool[11];
842 isNudge[0] = false; //FORWARD
843 isNudge[1] = false; //BACK
844 isNudge[2] = false; //LEFT
845 isNudge[3] = false; //RIGHT
846 isNudge[4] = false; //UP
847 isNudge[5] = false; //DOWN
848 isNudge[6] = true; //FORWARD_NUDGE
849 isNudge[7] = true; //BACK_NUDGE
850 isNudge[8] = true; //LEFT_NUDGE
851 isNudge[9] = true; //RIGHT_NUDGE
852 isNudge[10] = true; //DOWN_Nudge
853 return isNudge;
854 }
855
781 856
782 #endregion 857 #endregion
783 858
@@ -820,7 +895,6 @@ namespace OpenSim.Region.Framework.Scenes
820 m_grouptitle = gm.GetGroupTitle(m_uuid); 895 m_grouptitle = gm.GetGroupTitle(m_uuid);
821 896
822 m_rootRegionHandle = m_scene.RegionInfo.RegionHandle; 897 m_rootRegionHandle = m_scene.RegionInfo.RegionHandle;
823
824 m_scene.SetRootAgentScene(m_uuid); 898 m_scene.SetRootAgentScene(m_uuid);
825 899
826 // Moved this from SendInitialData to ensure that m_appearance is initialized 900 // Moved this from SendInitialData to ensure that m_appearance is initialized
@@ -839,6 +913,52 @@ namespace OpenSim.Region.Framework.Scenes
839 pos.Y = crossedBorder.BorderLine.Z - 1; 913 pos.Y = crossedBorder.BorderLine.Z - 1;
840 } 914 }
841 915
916 //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
917 //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
918 //they'll bypass the landing point. But I can't think of any decent way of fixing this.
919 if (KnownChildRegionHandles.Count == 0)
920 {
921 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
922 if (land != null)
923 {
924 //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
925 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)
926 {
927 pos = land.LandData.UserLocation;
928 }
929 }
930 }
931
932 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
933 {
934 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
935
936 if (pos.X < 0)
937 {
938 emergencyPos.X = (int)Constants.RegionSize + pos.X;
939 if (!(pos.Y < 0))
940 emergencyPos.Y = pos.Y;
941 if (!(pos.Z < 0))
942 emergencyPos.Z = pos.Z;
943 }
944 if (pos.Y < 0)
945 {
946 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
947 if (!(pos.X < 0))
948 emergencyPos.X = pos.X;
949 if (!(pos.Z < 0))
950 emergencyPos.Z = pos.Z;
951 }
952 if (pos.Z < 0)
953 {
954 emergencyPos.Z = 128;
955 if (!(pos.Y < 0))
956 emergencyPos.Y = pos.Y;
957 if (!(pos.X < 0))
958 emergencyPos.X = pos.X;
959 }
960 }
961
842 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 962 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
843 { 963 {
844 m_log.WarnFormat( 964 m_log.WarnFormat(
@@ -971,9 +1091,10 @@ namespace OpenSim.Region.Framework.Scenes
971 public void Teleport(Vector3 pos) 1091 public void Teleport(Vector3 pos)
972 { 1092 {
973 bool isFlying = false; 1093 bool isFlying = false;
1094
974 if (m_physicsActor != null) 1095 if (m_physicsActor != null)
975 isFlying = m_physicsActor.Flying; 1096 isFlying = m_physicsActor.Flying;
976 1097
977 RemoveFromPhysicalScene(); 1098 RemoveFromPhysicalScene();
978 Velocity = Vector3.Zero; 1099 Velocity = Vector3.Zero;
979 AbsolutePosition = pos; 1100 AbsolutePosition = pos;
@@ -985,6 +1106,7 @@ namespace OpenSim.Region.Framework.Scenes
985 } 1106 }
986 1107
987 SendTerseUpdateToAllClients(); 1108 SendTerseUpdateToAllClients();
1109
988 } 1110 }
989 1111
990 public void TeleportWithMomentum(Vector3 pos) 1112 public void TeleportWithMomentum(Vector3 pos)
@@ -1098,7 +1220,6 @@ namespace OpenSim.Region.Framework.Scenes
1098 pos.Z = ground + 1.5f; 1220 pos.Z = ground + 1.5f;
1099 AbsolutePosition = pos; 1221 AbsolutePosition = pos;
1100 } 1222 }
1101
1102 m_isChildAgent = false; 1223 m_isChildAgent = false;
1103 bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1224 bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1104 MakeRootAgent(AbsolutePosition, m_flying); 1225 MakeRootAgent(AbsolutePosition, m_flying);
@@ -1197,6 +1318,7 @@ namespace OpenSim.Region.Framework.Scenes
1197 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1318 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1198 1319
1199 m_pos = m_LastFinitePos; 1320 m_pos = m_LastFinitePos;
1321
1200 if (!m_pos.IsFinite()) 1322 if (!m_pos.IsFinite())
1201 { 1323 {
1202 m_pos.X = 127f; 1324 m_pos.X = 127f;
@@ -1263,7 +1385,6 @@ namespace OpenSim.Region.Framework.Scenes
1263 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1385 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1264 } 1386 }
1265 } 1387 }
1266
1267 lock (scriptedcontrols) 1388 lock (scriptedcontrols)
1268 { 1389 {
1269 if (scriptedcontrols.Count > 0) 1390 if (scriptedcontrols.Count > 0)
@@ -1278,6 +1399,9 @@ namespace OpenSim.Region.Framework.Scenes
1278 1399
1279 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1400 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1280 { 1401 {
1402 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1403 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1404
1281 // TODO: This doesn't prevent the user from walking yet. 1405 // TODO: This doesn't prevent the user from walking yet.
1282 // Setting parent ID would fix this, if we knew what value 1406 // Setting parent ID would fix this, if we knew what value
1283 // to use. Or we could add a m_isSitting variable. 1407 // to use. Or we could add a m_isSitting variable.
@@ -1332,6 +1456,11 @@ namespace OpenSim.Region.Framework.Scenes
1332 update_rotation = true; 1456 update_rotation = true;
1333 } 1457 }
1334 1458
1459 //guilty until proven innocent..
1460 bool Nudging = true;
1461 //Basically, if there is at least one non-nudge control then we don't need
1462 //to worry about stopping the avatar
1463
1335 if (m_parentID == 0) 1464 if (m_parentID == 0)
1336 { 1465 {
1337 bool bAllowUpdateMoveToPosition = false; 1466 bool bAllowUpdateMoveToPosition = false;
@@ -1346,9 +1475,12 @@ namespace OpenSim.Region.Framework.Scenes
1346 else 1475 else
1347 dirVectors = Dir_Vectors; 1476 dirVectors = Dir_Vectors;
1348 1477
1349 // The fact that m_movementflag is a byte needs to be fixed 1478 bool[] isNudge = GetDirectionIsNudge();
1350 // it really should be a uint 1479
1351 uint nudgehack = 250; 1480
1481
1482
1483
1352 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1484 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1353 { 1485 {
1354 if (((uint)flags & (uint)DCF) != 0) 1486 if (((uint)flags & (uint)DCF) != 0)
@@ -1358,40 +1490,28 @@ namespace OpenSim.Region.Framework.Scenes
1358 try 1490 try
1359 { 1491 {
1360 agent_control_v3 += dirVectors[i]; 1492 agent_control_v3 += dirVectors[i];
1361 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1493 if (isNudge[i] == false)
1494 {
1495 Nudging = false;
1496 }
1362 } 1497 }
1363 catch (IndexOutOfRangeException) 1498 catch (IndexOutOfRangeException)
1364 { 1499 {
1365 // Why did I get this? 1500 // Why did I get this?
1366 } 1501 }
1367 1502
1368 if ((m_movementflag & (byte)(uint)DCF) == 0) 1503 if ((m_movementflag & (uint)DCF) == 0)
1369 { 1504 {
1370 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1371 {
1372 m_movementflag |= (byte)nudgehack;
1373 }
1374 m_movementflag += (byte)(uint)DCF; 1505 m_movementflag += (byte)(uint)DCF;
1375 update_movementflag = true; 1506 update_movementflag = true;
1376 } 1507 }
1377 } 1508 }
1378 else 1509 else
1379 { 1510 {
1380 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1511 if ((m_movementflag & (uint)DCF) != 0)
1381 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1382 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1383 ) // This or is for Nudge forward
1384 { 1512 {
1385 m_movementflag -= ((byte)(uint)DCF); 1513 m_movementflag -= (byte)(uint)DCF;
1386
1387 update_movementflag = true; 1514 update_movementflag = true;
1388 /*
1389 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1390 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1391 {
1392 m_log.Debug("Removed Hack flag");
1393 }
1394 */
1395 } 1515 }
1396 else 1516 else
1397 { 1517 {
@@ -1400,7 +1520,6 @@ namespace OpenSim.Region.Framework.Scenes
1400 } 1520 }
1401 i++; 1521 i++;
1402 } 1522 }
1403
1404 //Paupaw:Do Proper PID for Autopilot here 1523 //Paupaw:Do Proper PID for Autopilot here
1405 if (bResetMoveToPosition) 1524 if (bResetMoveToPosition)
1406 { 1525 {
@@ -1435,6 +1554,9 @@ namespace OpenSim.Region.Framework.Scenes
1435 // Ignore z component of vector 1554 // Ignore z component of vector
1436 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1555 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1437 LocalVectorToTarget2D.Normalize(); 1556 LocalVectorToTarget2D.Normalize();
1557
1558 //We're not nudging
1559 Nudging = false;
1438 agent_control_v3 += LocalVectorToTarget2D; 1560 agent_control_v3 += LocalVectorToTarget2D;
1439 1561
1440 // update avatar movement flags. the avatar coordinate system is as follows: 1562 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1523,13 +1645,13 @@ namespace OpenSim.Region.Framework.Scenes
1523 // m_log.DebugFormat( 1645 // m_log.DebugFormat(
1524 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1646 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1525 1647
1526 AddNewMovement(agent_control_v3, q); 1648 AddNewMovement(agent_control_v3, q, Nudging);
1527 1649
1528 1650
1529 } 1651 }
1530 } 1652 }
1531 1653
1532 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1654 if (update_movementflag && !SitGround)
1533 Animator.UpdateMovementAnimations(); 1655 Animator.UpdateMovementAnimations();
1534 1656
1535 m_scene.EventManager.TriggerOnClientMovement(this); 1657 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1544,7 +1666,6 @@ namespace OpenSim.Region.Framework.Scenes
1544 m_sitAtAutoTarget = false; 1666 m_sitAtAutoTarget = false;
1545 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1667 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1546 //proxy.PCode = (byte)PCode.ParticleSystem; 1668 //proxy.PCode = (byte)PCode.ParticleSystem;
1547
1548 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1669 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1549 proxyObjectGroup.AttachToScene(m_scene); 1670 proxyObjectGroup.AttachToScene(m_scene);
1550 1671
@@ -1586,7 +1707,7 @@ namespace OpenSim.Region.Framework.Scenes
1586 } 1707 }
1587 m_moveToPositionInProgress = true; 1708 m_moveToPositionInProgress = true;
1588 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1709 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1589 } 1710 }
1590 catch (Exception ex) 1711 catch (Exception ex)
1591 { 1712 {
1592 //Why did I get this error? 1713 //Why did I get this error?
@@ -1608,7 +1729,7 @@ namespace OpenSim.Region.Framework.Scenes
1608 Velocity = Vector3.Zero; 1729 Velocity = Vector3.Zero;
1609 SendFullUpdateToAllClients(); 1730 SendFullUpdateToAllClients();
1610 1731
1611 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1732 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1612 } 1733 }
1613 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1734 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1614 m_requestedSitTargetUUID = UUID.Zero; 1735 m_requestedSitTargetUUID = UUID.Zero;
@@ -1645,50 +1766,84 @@ namespace OpenSim.Region.Framework.Scenes
1645 1766
1646 if (m_parentID != 0) 1767 if (m_parentID != 0)
1647 { 1768 {
1648 m_log.Debug("StandupCode Executed"); 1769 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1649 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1650 if (part != null) 1770 if (part != null)
1651 { 1771 {
1772 part.TaskInventory.LockItemsForRead(true);
1652 TaskInventoryDictionary taskIDict = part.TaskInventory; 1773 TaskInventoryDictionary taskIDict = part.TaskInventory;
1653 if (taskIDict != null) 1774 if (taskIDict != null)
1654 { 1775 {
1655 lock (taskIDict) 1776 foreach (UUID taskID in taskIDict.Keys)
1656 { 1777 {
1657 foreach (UUID taskID in taskIDict.Keys) 1778 UnRegisterControlEventsToScript(LocalId, taskID);
1658 { 1779 taskIDict[taskID].PermsMask &= ~(
1659 UnRegisterControlEventsToScript(LocalId, taskID); 1780 2048 | //PERMISSION_CONTROL_CAMERA
1660 taskIDict[taskID].PermsMask &= ~( 1781 4); // PERMISSION_TAKE_CONTROLS
1661 2048 | //PERMISSION_CONTROL_CAMERA
1662 4); // PERMISSION_TAKE_CONTROLS
1663 }
1664 } 1782 }
1665
1666 } 1783 }
1784 part.TaskInventory.LockItemsForRead(false);
1667 // Reset sit target. 1785 // Reset sit target.
1668 if (part.GetAvatarOnSitTarget() == UUID) 1786 if (part.GetAvatarOnSitTarget() == UUID)
1669 part.SetAvatarOnSitTarget(UUID.Zero); 1787 part.SetAvatarOnSitTarget(UUID.Zero);
1670
1671 m_parentPosition = part.GetWorldPosition(); 1788 m_parentPosition = part.GetWorldPosition();
1672 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1789 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1673 } 1790 }
1791 // part.GetWorldRotation() is the rotation of the object being sat on
1792 // Rotation is the sittiing Av's rotation
1793
1794 Quaternion partRot;
1795// if (part.LinkNum == 1)
1796// { // Root prim of linkset
1797// partRot = part.ParentGroup.RootPart.RotationOffset;
1798// }
1799// else
1800// { // single or child prim
1801
1802// }
1803 if (part == null) //CW: Part may be gone. llDie() for example.
1804 {
1805 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1806 }
1807 else
1808 {
1809 partRot = part.GetWorldRotation();
1810 }
1811
1812 Quaternion partIRot = Quaternion.Inverse(partRot);
1674 1813
1814 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1815 Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
1816
1817
1675 if (m_physicsActor == null) 1818 if (m_physicsActor == null)
1676 { 1819 {
1677 AddToPhysicalScene(false); 1820 AddToPhysicalScene(false);
1678 } 1821 }
1679 1822 //CW: If the part isn't null then we can set the current position
1680 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1823 if (part != null)
1681 m_parentPosition = Vector3.Zero; 1824 {
1682 1825 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
1683 m_parentID = 0; 1826 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1827 part.IsOccupied = false;
1828 part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
1829 }
1830 else
1831 {
1832 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1833 AbsolutePosition = m_lastWorldPosition;
1834 }
1835
1836 m_parentPosition = Vector3.Zero;
1837 m_parentID = 0;
1838 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1684 SendFullUpdateToAllClients(); 1839 SendFullUpdateToAllClients();
1685 m_requestedSitTargetID = 0; 1840 m_requestedSitTargetID = 0;
1841
1686 if ((m_physicsActor != null) && (m_avHeight > 0)) 1842 if ((m_physicsActor != null) && (m_avHeight > 0))
1687 { 1843 {
1688 SetHeight(m_avHeight); 1844 SetHeight(m_avHeight);
1689 } 1845 }
1690 } 1846 }
1691
1692 Animator.TrySetMovementAnimation("STAND"); 1847 Animator.TrySetMovementAnimation("STAND");
1693 } 1848 }
1694 1849
@@ -1719,13 +1874,9 @@ namespace OpenSim.Region.Framework.Scenes
1719 Vector3 avSitOffSet = part.SitTargetPosition; 1874 Vector3 avSitOffSet = part.SitTargetPosition;
1720 Quaternion avSitOrientation = part.SitTargetOrientation; 1875 Quaternion avSitOrientation = part.SitTargetOrientation;
1721 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1876 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1722 1877 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1723 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1878 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1724 bool SitTargetisSet = 1879 if (SitTargetisSet && !SitTargetOccupied)
1725 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1726 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1727
1728 if (SitTargetisSet && SitTargetUnOccupied)
1729 { 1880 {
1730 //switch the target to this prim 1881 //switch the target to this prim
1731 return part; 1882 return part;
@@ -1739,84 +1890,156 @@ namespace OpenSim.Region.Framework.Scenes
1739 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 1890 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1740 { 1891 {
1741 bool autopilot = true; 1892 bool autopilot = true;
1893 Vector3 autopilotTarget = new Vector3();
1894 Quaternion sitOrientation = Quaternion.Identity;
1742 Vector3 pos = new Vector3(); 1895 Vector3 pos = new Vector3();
1743 Quaternion sitOrientation = pSitOrientation;
1744 Vector3 cameraEyeOffset = Vector3.Zero; 1896 Vector3 cameraEyeOffset = Vector3.Zero;
1745 Vector3 cameraAtOffset = Vector3.Zero; 1897 Vector3 cameraAtOffset = Vector3.Zero;
1746 bool forceMouselook = false; 1898 bool forceMouselook = false;
1747 1899
1748 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1900 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1749 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1901 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1750 if (part != null) 1902 if (part == null) return;
1751 { 1903
1752 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1904 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1753 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 1905 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1754 1906
1755 // Is a sit target available? 1907 // part is the prim to sit on
1756 Vector3 avSitOffSet = part.SitTargetPosition; 1908 // offset is the world-ref vector distance from that prim center to the click-spot
1757 Quaternion avSitOrientation = part.SitTargetOrientation; 1909 // UUID is the UUID of the Avatar doing the clicking
1758 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1910
1759 1911 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1760 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1912
1761 bool SitTargetisSet = 1913 // Is a sit target available?
1762 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1914 Vector3 avSitOffSet = part.SitTargetPosition;
1763 ( 1915 Quaternion avSitOrientation = part.SitTargetOrientation;
1764 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1916
1765 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 1917 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1766 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 1918 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1767 ) 1919 Quaternion partRot;
1768 )); 1920// if (part.LinkNum == 1)
1769 1921// { // Root prim of linkset
1770 if (SitTargetisSet && SitTargetUnOccupied) 1922// partRot = part.ParentGroup.RootPart.RotationOffset;
1771 { 1923// }
1772 part.SetAvatarOnSitTarget(UUID); 1924// else
1773 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1925// { // single or child prim
1774 sitOrientation = avSitOrientation; 1926 partRot = part.GetWorldRotation();
1775 autopilot = false; 1927// }
1776 } 1928 Quaternion partIRot = Quaternion.Inverse(partRot);
1777 1929//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1778 pos = part.AbsolutePosition + offset; 1930 // Sit analysis rewritten by KF 091125
1779 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 1931 if (SitTargetisSet) // scipted sit
1780 //{ 1932 {
1781 // offset = pos; 1933 if (!part.IsOccupied)
1782 //autopilot = false; 1934 {
1783 //} 1935//Console.WriteLine("Scripted, unoccupied");
1784 if (m_physicsActor != null) 1936 part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
1785 { 1937 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1786 // If we're not using the client autopilot, we're immediately warping the avatar to the location 1938 sitOrientation = avSitOrientation; // Change rotatione to the scripted one
1787 // We can remove the physicsActor until they stand up. 1939 OffsetRotation = avSitOrientation;
1788 m_sitAvatarHeight = m_physicsActor.Size.Z; 1940 autopilot = false; // Jump direct to scripted llSitPos()
1789 1941 }
1790 if (autopilot) 1942 else
1791 { 1943 {
1792 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1944//Console.WriteLine("Scripted, occupied");
1793 { 1945 return;
1794 autopilot = false; 1946 }
1947 }
1948 else // Not Scripted
1949 {
1950 if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
1951 {
1952 // large prim & offset, ignore if other Avs sitting
1953// offset.Z -= 0.05f;
1954 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
1955 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
1956
1957//Console.WriteLine(" offset ={0}", offset);
1958//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
1959//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
1960
1961 }
1962 else // small offset
1963 {
1964//Console.WriteLine("Small offset");
1965 if (!part.IsOccupied)
1966 {
1967 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
1968 autopilotTarget = part.AbsolutePosition;
1969//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
1970 }
1971 else return; // occupied small
1972 } // end large/small
1973 } // end Scripted/not
1974 cameraAtOffset = part.GetCameraAtOffset();
1975 cameraEyeOffset = part.GetCameraEyeOffset();
1976 forceMouselook = part.GetForceMouselook();
1977 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
1978 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
1795 1979
1796 RemoveFromPhysicalScene(); 1980 if (m_physicsActor != null)
1797 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 1981 {
1798 } 1982 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1799 } 1983 // We can remove the physicsActor until they stand up.
1800 else 1984 m_sitAvatarHeight = m_physicsActor.Size.Z;
1985 if (autopilot)
1986 { // its not a scripted sit
1987// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
1988 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
1801 { 1989 {
1990 autopilot = false; // close enough
1991 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
1992 Not using the part's position because returning the AV to the last known standing
1993 position is likely to be more friendly, isn't it? */
1802 RemoveFromPhysicalScene(); 1994 RemoveFromPhysicalScene();
1803 } 1995 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
1996 } // else the autopilot will get us close
1997 }
1998 else
1999 { // its a scripted sit
2000 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2001 I *am* using the part's position this time because we have no real idea how far away
2002 the avatar is from the sit target. */
2003 RemoveFromPhysicalScene();
1804 } 2004 }
1805
1806 cameraAtOffset = part.GetCameraAtOffset();
1807 cameraEyeOffset = part.GetCameraEyeOffset();
1808 forceMouselook = part.GetForceMouselook();
1809 } 2005 }
1810 2006 else return; // physactor is null!
1811 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 2007
1812 m_requestedSitTargetUUID = targetID; 2008 Vector3 offsetr; // = offset * partIRot;
2009 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
2010 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
2011 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
2012 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
2013 offsetr = offset * partIRot;
2014//
2015 // else
2016 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
2017 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
2018 // (offset * partRot);
2019 // }
2020
2021//Console.WriteLine(" ");
2022//Console.WriteLine("link number ={0}", part.LinkNum);
2023//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2024//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2025//Console.WriteLine("Click offst ={0}", offset);
2026//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2027//Console.WriteLine("offsetr ={0}", offsetr);
2028//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2029//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2030
2031 //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
2032 ControllingClient.SendSitResponse(part.ParentGroup.UUID, offsetr + part.OffsetPosition, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2033
2034 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1813 // This calls HandleAgentSit twice, once from here, and the client calls 2035 // This calls HandleAgentSit twice, once from here, and the client calls
1814 // HandleAgentSit itself after it gets to the location 2036 // HandleAgentSit itself after it gets to the location
1815 // It doesn't get to the location until we've moved them there though 2037 // It doesn't get to the location until we've moved them there though
1816 // which happens in HandleAgentSit :P 2038 // which happens in HandleAgentSit :P
1817 m_autopilotMoving = autopilot; 2039 m_autopilotMoving = autopilot;
1818 m_autoPilotTarget = pos; 2040 m_autoPilotTarget = autopilotTarget;
1819 m_sitAtAutoTarget = autopilot; 2041 m_sitAtAutoTarget = autopilot;
2042 m_initialSitTarget = autopilotTarget;
1820 if (!autopilot) 2043 if (!autopilot)
1821 HandleAgentSit(remoteClient, UUID); 2044 HandleAgentSit(remoteClient, UUID);
1822 } 2045 }
@@ -2111,47 +2334,122 @@ namespace OpenSim.Region.Framework.Scenes
2111 { 2334 {
2112 if (part != null) 2335 if (part != null)
2113 { 2336 {
2337//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2114 if (part.GetAvatarOnSitTarget() == UUID) 2338 if (part.GetAvatarOnSitTarget() == UUID)
2115 { 2339 {
2340//Console.WriteLine("Scripted Sit");
2341 // Scripted sit
2116 Vector3 sitTargetPos = part.SitTargetPosition; 2342 Vector3 sitTargetPos = part.SitTargetPosition;
2117 Quaternion sitTargetOrient = part.SitTargetOrientation; 2343 Quaternion sitTargetOrient = part.SitTargetOrientation;
2118
2119 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2120 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2121
2122 //Quaternion result = (sitTargetOrient * vq) * nq;
2123
2124 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2344 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2125 m_pos += SIT_TARGET_ADJUSTMENT; 2345 m_pos += SIT_TARGET_ADJUSTMENT;
2126 m_bodyRot = sitTargetOrient; 2346 m_bodyRot = sitTargetOrient;
2127 //Rotation = sitTargetOrient;
2128 m_parentPosition = part.AbsolutePosition; 2347 m_parentPosition = part.AbsolutePosition;
2129 2348 part.IsOccupied = true;
2130 //SendTerseUpdateToAllClients(); 2349 part.ParentGroup.AddAvatar(agentID);
2350Console.WriteLine("Scripted Sit ofset {0}", m_pos);
2131 } 2351 }
2132 else 2352 else
2133 { 2353 {
2134 m_pos -= part.AbsolutePosition; 2354 // if m_avUnscriptedSitPos is zero then Av sits above center
2355 // Else Av sits at m_avUnscriptedSitPos
2356
2357 // Non-scripted sit by Kitto Flora 21Nov09
2358 // Calculate angle of line from prim to Av
2359 Quaternion partIRot;
2360// if (part.LinkNum == 1)
2361// { // Root prim of linkset
2362// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2363// }
2364// else
2365// { // single or child prim
2366 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2367// }
2368 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2369 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2370 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2371 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2372 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2373 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2374 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2375 // Av sits at world euler <0,0, z>, translated by part rotation
2376 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2377
2135 m_parentPosition = part.AbsolutePosition; 2378 m_parentPosition = part.AbsolutePosition;
2136 } 2379 part.IsOccupied = true;
2380 part.ParentGroup.AddAvatar(agentID);
2381 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2382 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2383 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2384 m_avUnscriptedSitPos; // adds click offset, if any
2385 //Set up raytrace to find top surface of prim
2386 Vector3 size = part.Scale;
2387 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2388 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2389 Vector3 down = new Vector3(0f, 0f, -1f);
2390//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2391 m_scene.PhysicsScene.RaycastWorld(
2392 start, // Vector3 position,
2393 down, // Vector3 direction,
2394 mag, // float length,
2395 SitAltitudeCallback); // retMethod
2396 } // end scripted/not
2137 } 2397 }
2138 else 2398 else // no Av
2139 { 2399 {
2140 return; 2400 return;
2141 } 2401 }
2142 } 2402 }
2143 m_parentID = m_requestedSitTargetID; 2403
2404 //We want our offsets to reference the root prim, not the child we may have sat on
2405 if (!part.IsRoot)
2406 {
2407 m_parentID = part.ParentGroup.RootPart.LocalId;
2408 m_pos += part.OffsetPosition;
2409 }
2410 else
2411 {
2412 m_parentID = m_requestedSitTargetID;
2413 }
2144 2414
2145 Velocity = Vector3.Zero; 2415 Velocity = Vector3.Zero;
2146 RemoveFromPhysicalScene(); 2416 RemoveFromPhysicalScene();
2147 2417
2148 Animator.TrySetMovementAnimation(sitAnimation); 2418 Animator.TrySetMovementAnimation(sitAnimation);
2149 SendFullUpdateToAllClients(); 2419 SendFullUpdateToAllClients();
2150 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2151 // So we're also sending a terse update (which has avatar rotation)
2152 // [Update] We do now.
2153 //SendTerseUpdateToAllClients();
2154 } 2420 }
2421
2422 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2423 {
2424 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2425 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2426 if(hitYN)
2427 {
2428 // m_pos = Av offset from prim center to make look like on center
2429 // m_parentPosition = Actual center pos of prim
2430 // collisionPoint = spot on prim where we want to sit
2431 // collisionPoint.Z = global sit surface height
2432 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2433 Quaternion partIRot;
2434// if (part.LinkNum == 1)
2435/// { // Root prim of linkset
2436// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2437// }
2438// else
2439// { // single or child prim
2440 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2441// }
2442 if (m_initialSitTarget != null)
2443 {
2444 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2445 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2446 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2447 m_pos += offset;
2448 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2449 }
2450
2451 }
2452 } // End SitAltitudeCallback KF.
2155 2453
2156 /// <summary> 2454 /// <summary>
2157 /// Event handler for the 'Always run' setting on the client 2455 /// Event handler for the 'Always run' setting on the client
@@ -2181,7 +2479,7 @@ namespace OpenSim.Region.Framework.Scenes
2181 /// </summary> 2479 /// </summary>
2182 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2480 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2183 /// <param name="rotation">The direction in which this avatar should now face. 2481 /// <param name="rotation">The direction in which this avatar should now face.
2184 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2482 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2185 { 2483 {
2186 if (m_isChildAgent) 2484 if (m_isChildAgent)
2187 { 2485 {
@@ -2222,10 +2520,11 @@ namespace OpenSim.Region.Framework.Scenes
2222 Rotation = rotation; 2520 Rotation = rotation;
2223 Vector3 direc = vec * rotation; 2521 Vector3 direc = vec * rotation;
2224 direc.Normalize(); 2522 direc.Normalize();
2523 PhysicsActor actor = m_physicsActor;
2524 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2225 2525
2226 direc *= 0.03f * 128f * m_speedModifier; 2526 direc *= 0.03f * 128f * m_speedModifier;
2227 2527
2228 PhysicsActor actor = m_physicsActor;
2229 if (actor != null) 2528 if (actor != null)
2230 { 2529 {
2231 if (actor.Flying) 2530 if (actor.Flying)
@@ -2247,18 +2546,25 @@ namespace OpenSim.Region.Framework.Scenes
2247 { 2546 {
2248 if (direc.Z > 2.0f) 2547 if (direc.Z > 2.0f)
2249 { 2548 {
2250 direc.Z *= 3.0f; 2549 if(m_animator.m_animTickJump == -1)
2251 2550 {
2252 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2551 direc.Z *= 3.0f; // jump
2253 Animator.TrySetMovementAnimation("PREJUMP"); 2552 }
2254 Animator.TrySetMovementAnimation("JUMP"); 2553 else
2554 {
2555 direc.Z *= 0.1f; // prejump
2556 }
2557 /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
2558 Animator.TrySetMovementAnimation("PREJUMP");
2559 Animator.TrySetMovementAnimation("JUMP");
2560 */
2255 } 2561 }
2256 } 2562 }
2257 } 2563 }
2258 2564
2259 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2565 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2260 m_forceToApply = direc; 2566 m_forceToApply = direc;
2261 2567 m_isNudging = Nudging;
2262 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2568 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2263 } 2569 }
2264 2570
@@ -2273,7 +2579,7 @@ namespace OpenSim.Region.Framework.Scenes
2273 const float POSITION_TOLERANCE = 0.05f; 2579 const float POSITION_TOLERANCE = 0.05f;
2274 //const int TIME_MS_TOLERANCE = 3000; 2580 //const int TIME_MS_TOLERANCE = 3000;
2275 2581
2276 SendPrimUpdates(); 2582
2277 2583
2278 if (m_isChildAgent == false) 2584 if (m_isChildAgent == false)
2279 { 2585 {
@@ -2303,6 +2609,9 @@ namespace OpenSim.Region.Framework.Scenes
2303 CheckForBorderCrossing(); 2609 CheckForBorderCrossing();
2304 CheckForSignificantMovement(); // sends update to the modules. 2610 CheckForSignificantMovement(); // sends update to the modules.
2305 } 2611 }
2612
2613 //Sending prim updates AFTER the avatar terse updates are sent
2614 SendPrimUpdates();
2306 } 2615 }
2307 2616
2308 #endregion 2617 #endregion
@@ -3087,6 +3396,7 @@ namespace OpenSim.Region.Framework.Scenes
3087 m_callbackURI = cAgent.CallbackURI; 3396 m_callbackURI = cAgent.CallbackURI;
3088 3397
3089 m_pos = cAgent.Position; 3398 m_pos = cAgent.Position;
3399
3090 m_velocity = cAgent.Velocity; 3400 m_velocity = cAgent.Velocity;
3091 m_CameraCenter = cAgent.Center; 3401 m_CameraCenter = cAgent.Center;
3092 //m_avHeight = cAgent.Size.Z; 3402 //m_avHeight = cAgent.Size.Z;
@@ -3197,14 +3507,25 @@ namespace OpenSim.Region.Framework.Scenes
3197 { 3507 {
3198 if (m_forceToApply.HasValue) 3508 if (m_forceToApply.HasValue)
3199 { 3509 {
3200 Vector3 force = m_forceToApply.Value;
3201 3510
3511 Vector3 force = m_forceToApply.Value;
3202 m_updateflag = true; 3512 m_updateflag = true;
3203// movementvector = force;
3204 Velocity = force; 3513 Velocity = force;
3205 3514
3206 m_forceToApply = null; 3515 m_forceToApply = null;
3207 } 3516 }
3517 else
3518 {
3519 if (m_isNudging)
3520 {
3521 Vector3 force = Vector3.Zero;
3522
3523 m_updateflag = true;
3524 Velocity = force;
3525 m_isNudging = false;
3526 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3527 }
3528 }
3208 } 3529 }
3209 3530
3210 public override void SetText(string text, Vector3 color, double alpha) 3531 public override void SetText(string text, Vector3 color, double alpha)
@@ -3255,18 +3576,29 @@ namespace OpenSim.Region.Framework.Scenes
3255 { 3576 {
3256 if (e == null) 3577 if (e == null)
3257 return; 3578 return;
3258 3579
3259 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3580 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3260 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3261 // as of this comment the interval is set in AddToPhysicalScene 3581 // as of this comment the interval is set in AddToPhysicalScene
3262 if (Animator!=null) 3582 if (Animator!=null)
3263 Animator.UpdateMovementAnimations(); 3583 {
3584 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3585 { // else its will lock out other animation changes, like ground sit.
3586 Animator.UpdateMovementAnimations();
3587 m_updateCount--;
3588 }
3589 }
3264 3590
3265 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3591 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3266 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3592 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3267 3593
3268 CollisionPlane = Vector4.UnitW; 3594 CollisionPlane = Vector4.UnitW;
3269 3595
3596 if (m_lastColCount != coldata.Count)
3597 {
3598 m_updateCount = UPDATE_COUNT;
3599 m_lastColCount = coldata.Count;
3600 }
3601
3270 if (coldata.Count != 0 && Animator != null) 3602 if (coldata.Count != 0 && Animator != null)
3271 { 3603 {
3272 switch (Animator.CurrentMovementAnimation) 3604 switch (Animator.CurrentMovementAnimation)
@@ -3296,6 +3628,148 @@ namespace OpenSim.Region.Framework.Scenes
3296 } 3628 }
3297 } 3629 }
3298 3630
3631 List<uint> thisHitColliders = new List<uint>();
3632 List<uint> endedColliders = new List<uint>();
3633 List<uint> startedColliders = new List<uint>();
3634
3635 foreach (uint localid in coldata.Keys)
3636 {
3637 thisHitColliders.Add(localid);
3638 if (!m_lastColliders.Contains(localid))
3639 {
3640 startedColliders.Add(localid);
3641 }
3642 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3643 }
3644
3645 // calculate things that ended colliding
3646 foreach (uint localID in m_lastColliders)
3647 {
3648 if (!thisHitColliders.Contains(localID))
3649 {
3650 endedColliders.Add(localID);
3651 }
3652 }
3653 //add the items that started colliding this time to the last colliders list.
3654 foreach (uint localID in startedColliders)
3655 {
3656 m_lastColliders.Add(localID);
3657 }
3658 // remove things that ended colliding from the last colliders list
3659 foreach (uint localID in endedColliders)
3660 {
3661 m_lastColliders.Remove(localID);
3662 }
3663
3664 // do event notification
3665 if (startedColliders.Count > 0)
3666 {
3667 ColliderArgs StartCollidingMessage = new ColliderArgs();
3668 List<DetectedObject> colliding = new List<DetectedObject>();
3669 foreach (uint localId in startedColliders)
3670 {
3671 if (localId == 0)
3672 continue;
3673
3674 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3675 string data = "";
3676 if (obj != null)
3677 {
3678 DetectedObject detobj = new DetectedObject();
3679 detobj.keyUUID = obj.UUID;
3680 detobj.nameStr = obj.Name;
3681 detobj.ownerUUID = obj.OwnerID;
3682 detobj.posVector = obj.AbsolutePosition;
3683 detobj.rotQuat = obj.GetWorldRotation();
3684 detobj.velVector = obj.Velocity;
3685 detobj.colliderType = 0;
3686 detobj.groupUUID = obj.GroupID;
3687 colliding.Add(detobj);
3688 }
3689 }
3690
3691 if (colliding.Count > 0)
3692 {
3693 StartCollidingMessage.Colliders = colliding;
3694
3695 foreach (SceneObjectGroup att in Attachments)
3696 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3697 }
3698 }
3699
3700 if (endedColliders.Count > 0)
3701 {
3702 ColliderArgs EndCollidingMessage = new ColliderArgs();
3703 List<DetectedObject> colliding = new List<DetectedObject>();
3704 foreach (uint localId in endedColliders)
3705 {
3706 if (localId == 0)
3707 continue;
3708
3709 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3710 string data = "";
3711 if (obj != null)
3712 {
3713 DetectedObject detobj = new DetectedObject();
3714 detobj.keyUUID = obj.UUID;
3715 detobj.nameStr = obj.Name;
3716 detobj.ownerUUID = obj.OwnerID;
3717 detobj.posVector = obj.AbsolutePosition;
3718 detobj.rotQuat = obj.GetWorldRotation();
3719 detobj.velVector = obj.Velocity;
3720 detobj.colliderType = 0;
3721 detobj.groupUUID = obj.GroupID;
3722 colliding.Add(detobj);
3723 }
3724 }
3725
3726 if (colliding.Count > 0)
3727 {
3728 EndCollidingMessage.Colliders = colliding;
3729
3730 foreach (SceneObjectGroup att in Attachments)
3731 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
3732 }
3733 }
3734
3735 if (thisHitColliders.Count > 0)
3736 {
3737 ColliderArgs CollidingMessage = new ColliderArgs();
3738 List<DetectedObject> colliding = new List<DetectedObject>();
3739 foreach (uint localId in thisHitColliders)
3740 {
3741 if (localId == 0)
3742 continue;
3743
3744 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3745 string data = "";
3746 if (obj != null)
3747 {
3748 DetectedObject detobj = new DetectedObject();
3749 detobj.keyUUID = obj.UUID;
3750 detobj.nameStr = obj.Name;
3751 detobj.ownerUUID = obj.OwnerID;
3752 detobj.posVector = obj.AbsolutePosition;
3753 detobj.rotQuat = obj.GetWorldRotation();
3754 detobj.velVector = obj.Velocity;
3755 detobj.colliderType = 0;
3756 detobj.groupUUID = obj.GroupID;
3757 colliding.Add(detobj);
3758 }
3759 }
3760
3761 if (colliding.Count > 0)
3762 {
3763 CollidingMessage.Colliders = colliding;
3764
3765 lock (m_attachments)
3766 {
3767 foreach (SceneObjectGroup att in m_attachments)
3768 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
3769 }
3770 }
3771 }
3772
3299 if (m_invulnerable) 3773 if (m_invulnerable)
3300 return; 3774 return;
3301 3775
@@ -3470,7 +3944,10 @@ namespace OpenSim.Region.Framework.Scenes
3470 m_scene = scene; 3944 m_scene = scene;
3471 3945
3472 RegisterToEvents(); 3946 RegisterToEvents();
3473 3947 if (m_controllingClient != null)
3948 {
3949 m_controllingClient.ProcessPendingPackets();
3950 }
3474 /* 3951 /*
3475 AbsolutePosition = client.StartPos; 3952 AbsolutePosition = client.StartPos;
3476 3953
@@ -3700,6 +4177,39 @@ namespace OpenSim.Region.Framework.Scenes
3700 return; 4177 return;
3701 } 4178 }
3702 4179
4180 XmlDocument doc = new XmlDocument();
4181 string stateData = String.Empty;
4182
4183 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
4184 if (attServ != null)
4185 {
4186 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
4187 stateData = attServ.Get(ControllingClient.AgentId.ToString());
4188 if (stateData != String.Empty)
4189 {
4190 try
4191 {
4192 doc.LoadXml(stateData);
4193 }
4194 catch { }
4195 }
4196 }
4197
4198 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
4199
4200 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
4201 if (nodes.Count > 0)
4202 {
4203 foreach (XmlNode n in nodes)
4204 {
4205 XmlElement elem = (XmlElement)n;
4206 string itemID = elem.GetAttribute("ItemID");
4207 string xml = elem.InnerXml;
4208
4209 itemData[new UUID(itemID)] = xml;
4210 }
4211 }
4212
3703 List<int> attPoints = m_appearance.GetAttachedPoints(); 4213 List<int> attPoints = m_appearance.GetAttachedPoints();
3704 foreach (int p in attPoints) 4214 foreach (int p in attPoints)
3705 { 4215 {
@@ -3719,9 +4229,26 @@ namespace OpenSim.Region.Framework.Scenes
3719 4229
3720 try 4230 try
3721 { 4231 {
3722 // Rez from inventory 4232 string xmlData;
3723 UUID asset 4233 XmlDocument d = new XmlDocument();
3724 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); 4234 UUID asset;
4235 if (itemData.TryGetValue(itemID, out xmlData))
4236 {
4237 d.LoadXml(xmlData);
4238 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
4239
4240 // Rez from inventory
4241 asset
4242 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
4243
4244 }
4245 else
4246 {
4247 // Rez from inventory (with a null doc to let
4248 // CHANGED_OWNER happen)
4249 asset
4250 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
4251 }
3725 4252
3726 m_log.InfoFormat( 4253 m_log.InfoFormat(
3727 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", 4254 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})",
@@ -3758,5 +4285,16 @@ namespace OpenSim.Region.Framework.Scenes
3758 m_reprioritization_called = false; 4285 m_reprioritization_called = false;
3759 } 4286 }
3760 } 4287 }
4288
4289 private Vector3 Quat2Euler(Quaternion rot){
4290 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4291 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4292 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4293 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4294 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4295 return(new Vector3(x,y,z));
4296 }
4297
4298
3761 } 4299 }
3762} 4300}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 5bdaa17..77e477f 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -105,7 +105,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
105 sceneObject.AddPart(part); 105 sceneObject.AddPart(part);
106 part.LinkNum = linkNum; 106 part.LinkNum = linkNum;
107 part.TrimPermissions(); 107 part.TrimPermissions();
108 part.StoreUndoState(); 108 part.StoreUndoState(UndoType.STATE_ALL);
109 reader.Close(); 109 reader.Close();
110 sr.Close(); 110 sr.Close();
111 } 111 }
@@ -231,7 +231,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
231 if (originalLinkNum != 0) 231 if (originalLinkNum != 0)
232 part.LinkNum = originalLinkNum; 232 part.LinkNum = originalLinkNum;
233 233
234 part.StoreUndoState(); 234 part.StoreUndoState(UndoType.STATE_ALL);
235 reader.Close(); 235 reader.Close();
236 sr.Close(); 236 sr.Close();
237 } 237 }
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 55e407e..f71b507 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -27,48 +27,125 @@
27 27
28using OpenMetaverse; 28using OpenMetaverse;
29using OpenSim.Region.Framework.Interfaces; 29using OpenSim.Region.Framework.Interfaces;
30using System;
30 31
31namespace OpenSim.Region.Framework.Scenes 32namespace OpenSim.Region.Framework.Scenes
32{ 33{
34 [Flags]
35 public enum UndoType
36 {
37 STATE_PRIM_POSITION = 1,
38 STATE_PRIM_ROTATION = 2,
39 STATE_PRIM_SCALE = 4,
40 STATE_PRIM_ALL = 7,
41 STATE_GROUP_POSITION = 8,
42 STATE_GROUP_ROTATION = 16,
43 STATE_GROUP_SCALE = 32,
44 STATE_GROUP_ALL = 56,
45 STATE_ALL = 63
46 }
47
33 public class UndoState 48 public class UndoState
34 { 49 {
35 public Vector3 Position = Vector3.Zero; 50 public Vector3 Position = Vector3.Zero;
36 public Vector3 Scale = Vector3.Zero; 51 public Vector3 Scale = Vector3.Zero;
37 public Quaternion Rotation = Quaternion.Identity; 52 public Quaternion Rotation = Quaternion.Identity;
53 public Vector3 GroupPosition = Vector3.Zero;
54 public Quaternion GroupRotation = Quaternion.Identity;
55 public Vector3 GroupScale = Vector3.Zero;
56 public DateTime LastUpdated = DateTime.Now;
57 public UndoType Type;
38 58
39 public UndoState(SceneObjectPart part) 59 public UndoState(SceneObjectPart part, UndoType type)
40 { 60 {
61 Type = type;
41 if (part != null) 62 if (part != null)
42 { 63 {
43 if (part.ParentID == 0) 64 if (part.ParentID == 0)
44 { 65 {
45 Position = part.ParentGroup.AbsolutePosition; 66 GroupScale = part.ParentGroup.RootPart.Shape.Scale;
67
68 //FUBAR WARNING: Do NOT get the group's absoluteposition here
69 //or you'll experience a loop and/or a stack issue
70 GroupPosition = part.ParentGroup.RootPart.AbsolutePosition;
71 GroupRotation = part.ParentGroup.GroupRotation;
72 Position = part.ParentGroup.RootPart.AbsolutePosition;
46 Rotation = part.RotationOffset; 73 Rotation = part.RotationOffset;
47 Scale = part.Shape.Scale; 74 Scale = part.Shape.Scale;
75 LastUpdated = DateTime.Now;
48 } 76 }
49 else 77 else
50 { 78 {
79 GroupScale = part.Shape.Scale;
80
81 //FUBAR WARNING: Do NOT get the group's absoluteposition here
82 //or you'll experience a loop and/or a stack issue
83 GroupPosition = part.ParentGroup.RootPart.AbsolutePosition;
84 GroupRotation = part.ParentGroup.Rotation;
51 Position = part.OffsetPosition; 85 Position = part.OffsetPosition;
52 Rotation = part.RotationOffset; 86 Rotation = part.RotationOffset;
53 Scale = part.Shape.Scale; 87 Scale = part.Shape.Scale;
88 LastUpdated = DateTime.Now;
54 } 89 }
55 } 90 }
56 } 91 }
57 92 public void Merge(UndoState last)
93 {
94 if ((Type & UndoType.STATE_GROUP_POSITION) == 0 || ((last.Type & UndoType.STATE_GROUP_POSITION) >= (Type & UndoType.STATE_GROUP_POSITION)))
95 {
96 GroupPosition = last.GroupPosition;
97 Position = last.Position;
98 }
99 if ((Type & UndoType.STATE_GROUP_SCALE) == 0 || ((last.Type & UndoType.STATE_GROUP_SCALE) >= (Type & UndoType.STATE_GROUP_SCALE)))
100 {
101 GroupScale = last.GroupScale;
102 Scale = last.Scale;
103 }
104 if ((Type & UndoType.STATE_GROUP_ROTATION) == 0 || ((last.Type & UndoType.STATE_GROUP_ROTATION) >= (Type & UndoType.STATE_GROUP_ROTATION)))
105 {
106 GroupRotation = last.GroupRotation;
107 Rotation = last.Rotation;
108 }
109 if ((Type & UndoType.STATE_PRIM_POSITION) == 0 || ((last.Type & UndoType.STATE_PRIM_POSITION) >= (Type & UndoType.STATE_PRIM_POSITION)))
110 {
111 Position = last.Position;
112 }
113 if ((Type & UndoType.STATE_PRIM_SCALE) == 0 || ((last.Type & UndoType.STATE_PRIM_SCALE) >= (Type & UndoType.STATE_PRIM_SCALE)))
114 {
115 Scale = last.Scale;
116 }
117 if ((Type & UndoType.STATE_PRIM_ROTATION) == 0 || ((last.Type & UndoType.STATE_PRIM_ROTATION) >= (Type & UndoType.STATE_PRIM_ROTATION)))
118 {
119 Rotation = last.Rotation;
120 }
121 Type = Type | last.Type;
122 }
123 public bool Compare(UndoState undo)
124 {
125 if (undo == null || Position == null) return false;
126 if (undo.Position == Position && undo.Rotation == Rotation && undo.Scale == Scale && undo.GroupPosition == GroupPosition && undo.GroupScale == GroupScale && undo.GroupRotation == GroupRotation)
127 {
128 return true;
129 }
130 else
131 {
132 return false;
133 }
134 }
58 public bool Compare(SceneObjectPart part) 135 public bool Compare(SceneObjectPart part)
59 { 136 {
60 if (part != null) 137 if (part != null)
61 { 138 {
62 if (part.ParentID == 0) 139 if (part.ParentID == 0)
63 { 140 {
64 if (Position == part.ParentGroup.AbsolutePosition && Rotation == part.ParentGroup.Rotation) 141 if (Position == part.ParentGroup.RootPart.AbsolutePosition && Rotation == part.ParentGroup.Rotation && GroupPosition == part.ParentGroup.RootPart.AbsolutePosition && part.ParentGroup.Rotation == GroupRotation && part.Shape.Scale == GroupScale)
65 return true; 142 return true;
66 else 143 else
67 return false; 144 return false;
68 } 145 }
69 else 146 else
70 { 147 {
71 if (Position == part.OffsetPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale) 148 if (Position == part.OffsetPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale && GroupPosition == part.ParentGroup.RootPart.AbsolutePosition && part.ParentGroup.Rotation == GroupRotation && part.Shape.Scale == GroupScale)
72 return true; 149 return true;
73 else 150 else
74 return false; 151 return false;
@@ -78,62 +155,70 @@ namespace OpenSim.Region.Framework.Scenes
78 return false; 155 return false;
79 } 156 }
80 157
81 public void PlaybackState(SceneObjectPart part) 158 private void RestoreState(SceneObjectPart part)
82 { 159 {
160 bool GroupChange = false;
161 if ((Type & UndoType.STATE_GROUP_POSITION) != 0
162 || (Type & UndoType.STATE_GROUP_ROTATION) != 0
163 || (Type & UndoType.STATE_GROUP_SCALE) != 0)
164 {
165 GroupChange = true;
166 }
167
83 if (part != null) 168 if (part != null)
84 { 169 {
85 part.Undoing = true; 170 part.Undoing = true;
86 171
87 if (part.ParentID == 0) 172 if (part.ParentID == 0 && GroupChange == false)
88 { 173 {
89 if (Position != Vector3.Zero) 174 if (Position != Vector3.Zero)
90 part.ParentGroup.AbsolutePosition = Position; 175
91 part.RotationOffset = Rotation; 176 part.ParentGroup.UpdateSinglePosition(Position, part.LocalId);
177 part.ParentGroup.UpdateSingleRotation(Rotation, part.LocalId);
92 if (Scale != Vector3.Zero) 178 if (Scale != Vector3.Zero)
93 part.Resize(Scale); 179 part.Resize(Scale);
94 part.ParentGroup.ScheduleGroupForTerseUpdate(); 180 part.ParentGroup.ScheduleGroupForTerseUpdate();
95 } 181 }
96 else 182 else
97 { 183 {
98 if (Position != Vector3.Zero) 184 if (GroupChange)
99 part.OffsetPosition = Position; 185 {
100 part.UpdateRotation(Rotation); 186 part.ParentGroup.RootPart.Undoing = true;
101 if (Scale != Vector3.Zero) 187 if (GroupPosition != Vector3.Zero)
102 part.Resize(Scale); part.ScheduleTerseUpdate(); 188 {
189 //Calculate the scale...
190 Vector3 gs = part.Shape.Scale;
191 float scale = GroupScale.Z / gs.Z;
192
193 //Scale first since it can affect our position
194 part.ParentGroup.GroupResize(gs * scale, part.LocalId);
195 part.ParentGroup.AbsolutePosition = GroupPosition;
196 part.ParentGroup.UpdateGroupRotationR(GroupRotation);
197
198 }
199 part.ParentGroup.RootPart.Undoing = false;
200 }
201 else
202 {
203 if (Position != Vector3.Zero) //We can use this for all the updates since all are set
204 {
205 part.OffsetPosition = Position;
206 part.UpdateRotation(Rotation);
207 part.Resize(Scale); part.ScheduleTerseUpdate();
208 }
209 }
103 } 210 }
104 part.Undoing = false; 211 part.Undoing = false;
105 212
106 } 213 }
107 } 214 }
215 public void PlaybackState(SceneObjectPart part)
216 {
217 RestoreState(part);
218 }
108 public void PlayfwdState(SceneObjectPart part) 219 public void PlayfwdState(SceneObjectPart part)
109 { 220 {
110 if (part != null) 221 RestoreState(part);
111 {
112 part.Undoing = true;
113
114 if (part.ParentID == 0)
115 {
116 if (Position != Vector3.Zero)
117 part.ParentGroup.AbsolutePosition = Position;
118 if (Rotation != Quaternion.Identity)
119 part.UpdateRotation(Rotation);
120 if (Scale != Vector3.Zero)
121 part.Resize(Scale);
122 part.ParentGroup.ScheduleGroupForTerseUpdate();
123 }
124 else
125 {
126 if (Position != Vector3.Zero)
127 part.OffsetPosition = Position;
128 if (Rotation != Quaternion.Identity)
129 part.UpdateRotation(Rotation);
130 if (Scale != Vector3.Zero)
131 part.Resize(Scale);
132 part.ScheduleTerseUpdate();
133 }
134 part.Undoing = false;
135
136 }
137 } 222 }
138 } 223 }
139 public class LandUndoState 224 public class LandUndoState
@@ -161,3 +246,4 @@ namespace OpenSim.Region.Framework.Scenes
161 } 246 }
162 } 247 }
163} 248}
249