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.cs5
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs2
-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.cs214
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs11
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs221
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs247
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs243
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs656
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs281
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs570
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs977
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs168
21 files changed, 2718 insertions, 987 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index b3576c5..788f42b 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>
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 64664ab..ed40da9 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -115,6 +115,8 @@ namespace OpenSim.Region.Framework.Interfaces
115 /// <param name="stateSource"></param> 115 /// <param name="stateSource"></param>
116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
117 117
118 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
119
118 /// <summary> 120 /// <summary>
119 /// Stop a script which is in this prim's inventory. 121 /// Stop a script which is in this prim's inventory.
120 /// </summary> 122 /// </summary>
@@ -236,5 +238,6 @@ namespace OpenSim.Region.Framework.Interfaces
236 /// A <see cref="Dictionary`2"/> 238 /// A <see cref="Dictionary`2"/>
237 /// </returns> 239 /// </returns>
238 Dictionary<UUID, string> GetScriptStates(); 240 Dictionary<UUID, string> GetScriptStates();
241 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
239 } 242 }
240} 243}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index e8738c4..45ca5c5 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Interfaces
40 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, 40 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position,
41 Vector3 lookAt, uint teleportFlags); 41 Vector3 lookAt, uint teleportFlags);
42 42
43 void TeleportHome(UUID id, IClientAPI client); 43 bool TeleportHome(UUID id, IClientAPI client);
44 44
45 void Cross(ScenePresence agent, bool isFlying); 45 void Cross(ScenePresence agent, bool isFlying);
46 46
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 a90e0f3..9c103cb 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -53,11 +53,17 @@ namespace OpenSim.Region.Framework.Scenes.Animation
53 { 53 {
54 get { return m_movementAnimation; } 54 get { return m_movementAnimation; }
55 } 55 }
56 protected string m_movementAnimation = "DEFAULT"; 56 // protected string m_movementAnimation = "DEFAULT"; //KF: 'DEFAULT' does not exist!
57 57 protected string m_movementAnimation = "CROUCH"; //KF: CROUCH ensures reliable Av Anim. init.
58 private int m_animTickFall; 58 private int m_animTickFall;
59 private int m_animTickJump; 59// private int m_animTickJump;
60 60 public int m_animTickJump; // ScenePresence has to see this to control +Z force
61 public bool m_jumping = false; // Add for jumping
62 public float m_jumpVelocity = 0f; // Add for jumping
63 private int m_landing = 0; // Add for jumping
64 public bool m_falling = false; // Add for falling
65 private float m_fallHeight; // Add for falling
66
61 /// <value> 67 /// <value>
62 /// The scene presence that this animator applies to 68 /// The scene presence that this animator applies to
63 /// </value> 69 /// </value>
@@ -114,7 +120,9 @@ namespace OpenSim.Region.Framework.Scenes.Animation
114 120
115 public void ResetAnimations() 121 public void ResetAnimations()
116 { 122 {
123Console.WriteLine("ResetA.............");
117 m_animations.Clear(); 124 m_animations.Clear();
125TrySetMovementAnimation("STAND");
118 } 126 }
119 127
120 /// <summary> 128 /// <summary>
@@ -123,8 +131,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation
123 /// </summary> 131 /// </summary>
124 public void TrySetMovementAnimation(string anim) 132 public void TrySetMovementAnimation(string anim)
125 { 133 {
126 //m_log.DebugFormat("Updating movement animation to {0}", anim);
127
128 if (!m_scenePresence.IsChildAgent) 134 if (!m_scenePresence.IsChildAgent)
129 { 135 {
130 if (m_animations.TrySetDefaultAnimation( 136 if (m_animations.TrySetDefaultAnimation(
@@ -142,14 +148,14 @@ namespace OpenSim.Region.Framework.Scenes.Animation
142 /// </summary> 148 /// </summary>
143 public string GetMovementAnimation() 149 public string GetMovementAnimation()
144 { 150 {
145 const float FALL_DELAY = 0.33f; 151//Console.WriteLine("GMA-------"); //##
146 const float PREJUMP_DELAY = 0.25f; 152//#@ const float FALL_DELAY = 0.33f;
147 153 const float FALL_DELAY = 800f; //## mS
154//rm for jumping const float PREJUMP_DELAY = 0.25f;
155 const float PREJUMP_DELAY = 200f; // mS add for jumping
156 const float JUMP_PERIOD = 800f; // mS add for jumping
148 #region Inputs 157 #region Inputs
149 if (m_scenePresence.SitGround) 158
150 {
151 return "SIT_GROUND_CONSTRAINED";
152 }
153 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; 159 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
154 PhysicsActor actor = m_scenePresence.PhysicsActor; 160 PhysicsActor actor = m_scenePresence.PhysicsActor;
155 161
@@ -159,11 +165,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
159 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 165 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
160 166
161 // Check control flags 167 // Check control flags
162 bool heldForward = 168 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)); 169 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; 170 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; 171 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; 172 //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; 173 //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; 174 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
@@ -182,8 +187,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
182 187
183 // Is the avatar trying to move? 188 // Is the avatar trying to move?
184// bool moving = (move != Vector3.Zero); 189// bool moving = (move != Vector3.Zero);
185 bool jumping = m_animTickJump != 0; 190// rm for jumping bool jumping = m_animTickJump != 0;
186
187 #endregion Inputs 191 #endregion Inputs
188 192
189 #region Flying 193 #region Flying
@@ -192,6 +196,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
192 { 196 {
193 m_animTickFall = 0; 197 m_animTickFall = 0;
194 m_animTickJump = 0; 198 m_animTickJump = 0;
199 m_jumping = false; //add for jumping
200 m_falling = true; //add for falling
201 m_jumpVelocity = 0f; //add for jumping
202 actor.Selected = false; //add for jumping flag
203 m_fallHeight = actor.Position.Z; // save latest flying height
195 204
196 if (move.X != 0f || move.Y != 0f) 205 if (move.X != 0f || move.Y != 0f)
197 { 206 {
@@ -203,8 +212,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
203 } 212 }
204 else if (move.Z < 0f) 213 else if (move.Z < 0f)
205 { 214 {
206 if (actor != null && actor.IsColliding) 215 if (actor != null && actor.IsColliding)
216 { //##
217//Console.WriteLine("LAND FLYING"); // ##
207 return "LAND"; 218 return "LAND";
219 } //#
208 else 220 else
209 return "HOVER_DOWN"; 221 return "HOVER_DOWN";
210 } 222 }
@@ -218,19 +230,28 @@ namespace OpenSim.Region.Framework.Scenes.Animation
218 230
219 #region Falling/Floating/Landing 231 #region Falling/Floating/Landing
220 232
221 if (actor == null || !actor.IsColliding) 233// rm for jumping if (actor == null || !actor.IsColliding)
234 if ((actor == null || !actor.IsColliding) && !m_jumping) // add for jumping
222 { 235 {
223 float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; 236// rm float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
237 float fallElapsed = (float)(Environment.TickCount - m_animTickFall); // add, in mS
224 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f; 238 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
239//Console.WriteLine("falling t={0} v={1}", fallElapsed, fallVelocity); //##
240
241// rm for fall if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f))
242 if (!m_jumping && (fallVelocity < -3.0f) ) m_falling = true; // add for falling and jumping
225 243
226 if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f)) 244 if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) // add for jumping
245 // not falling yet or going up
227 { 246 {
228 // Just started falling 247 // reset start of fall time
229 m_animTickFall = Environment.TickCount; 248 m_animTickFall = Environment.TickCount;
230 } 249 }
231 else if (!jumping && fallElapsed > FALL_DELAY) 250// else if (!jumping && fallElapsed > FALL_DELAY)
251 else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.m_wasFlying)) // add for falling and jumping
232 { 252 {
233 // Falling long enough to trigger the animation 253 // Falling long enough to trigger the animation
254//Console.WriteLine("FALLDOWN"); //##
234 return "FALLDOWN"; 255 return "FALLDOWN";
235 } 256 }
236 257
@@ -239,22 +260,97 @@ namespace OpenSim.Region.Framework.Scenes.Animation
239 260
240 #endregion Falling/Floating/Landing 261 #endregion Falling/Floating/Landing
241 262
263
264 #region Jumping // section added for jumping...
265
266 int jumptime;
267 jumptime = Environment.TickCount - m_animTickJump;
268
269
270 if ((move.Z > 0f) && (!m_jumping))
271 {
272//Console.WriteLine("PJ {0}", jumptime); //##
273 // Start jumping, prejump
274 m_animTickFall = 0;
275 m_jumping = true;
276 m_falling = false;
277 actor.Selected = true; // borrowed for jmping flag
278 m_animTickJump = Environment.TickCount;
279 m_jumpVelocity = 0.35f;
280 return "PREJUMP";
281 }
282
283 if(m_jumping)
284 {
285 if ( (jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding)
286 {
287//Console.WriteLine("LA {0}", jumptime); //##
288 // end jumping
289 m_jumping = false;
290 m_falling = false;
291 actor.Selected = false; // borrowed for jumping flag
292 m_jumpVelocity = 0f;
293 m_animTickFall = Environment.TickCount;
294 return "LAND";
295 }
296 else if (jumptime > JUMP_PERIOD)
297 {
298//Console.WriteLine("JD {0}", jumptime); //##
299 // jump down
300 m_jumpVelocity = 0f;
301 return "JUMP";
302 }
303 else if (jumptime > PREJUMP_DELAY)
304 {
305//Console.WriteLine("JU {0}", jumptime); //##
306 // jump up
307 m_jumping = true;
308 m_jumpVelocity = 10f;
309 return "JUMP";
310 }
311 }
312
313 #endregion Jumping // end added section
314
242 #region Ground Movement 315 #region Ground Movement
243 316
244 if (m_movementAnimation == "FALLDOWN") 317 if (m_movementAnimation == "FALLDOWN")
245 { 318 {
319 m_falling = false;
246 m_animTickFall = Environment.TickCount; 320 m_animTickFall = Environment.TickCount;
247
248 // TODO: SOFT_LAND support 321 // TODO: SOFT_LAND support
249 return "LAND"; 322 float fallHeight = m_fallHeight - actor.Position.Z;
323//Console.WriteLine("Hit from {0}", fallHeight); //##
324 if (fallHeight > 15.0f) // add for falling
325 return "STANDUP";
326 else if (fallHeight > 8.0f) // add for falling
327 return "SOFT_LAND"; // add for falling
328 else // add for falling
329 return "LAND"; // add for falling
250 } 330 }
251 else if (m_movementAnimation == "LAND") 331// rm jumping float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
332// rm jumping if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY))
333// rm for landing return "LAND";
334 else if ((m_movementAnimation == "LAND") || (m_movementAnimation == "SOFT_LAND") || (m_movementAnimation == "STANDUP"))
252 { 335 {
253 float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; 336 int landElapsed = Environment.TickCount - m_animTickFall; // add for jumping
254 if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY)) 337 int limit = 1000; // add for jumping
255 return "LAND"; 338 if(m_movementAnimation == "LAND") limit = 350; // add for jumping
256 } 339 // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client
257 340
341 if ((m_animTickFall != 0) && (landElapsed <= limit)) // add for jumping
342 {
343//Console.WriteLine("Lelapse {0}", m_movementAnimation); //##
344 return m_movementAnimation;
345 }
346 else
347 {
348//Console.WriteLine("end/STAND"); //##
349 m_fallHeight = actor.Position.Z; // save latest flying height
350 return "STAND";
351 }
352 }
353/* This section removed, replaced by jumping section
258 m_animTickFall = 0; 354 m_animTickFall = 0;
259 355
260 if (move.Z > 0f) 356 if (move.Z > 0f)
@@ -266,7 +362,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
266 m_animTickJump = Environment.TickCount; 362 m_animTickJump = Environment.TickCount;
267 return "PREJUMP"; 363 return "PREJUMP";
268 } 364 }
269 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f) 365 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 800.0f)
270 { 366 {
271 // Start actual jump 367 // Start actual jump
272 if (m_animTickJump == -1) 368 if (m_animTickJump == -1)
@@ -284,29 +380,34 @@ namespace OpenSim.Region.Framework.Scenes.Animation
284 { 380 {
285 // Not jumping 381 // Not jumping
286 m_animTickJump = 0; 382 m_animTickJump = 0;
287 383 */
288 if (move.X != 0f || move.Y != 0f) 384 // next section moved outside paren. and realigned for jumping
289 { 385 if (move.X != 0f || move.Y != 0f)
290 // Walking / crouchwalking / running 386 {
291 if (move.Z < 0f) 387 m_fallHeight = actor.Position.Z; // save latest flying height
292 return "CROUCHWALK"; 388 m_falling = false; // Add for falling
293 else if (m_scenePresence.SetAlwaysRun) 389 // Walking / crouchwalking / running
294 return "RUN"; 390 if (move.Z < 0f)
295 else 391 return "CROUCHWALK";
296 return "WALK"; 392 else if (m_scenePresence.SetAlwaysRun)
297 } 393 return "RUN";
298 else 394 else
299 { 395 return "WALK";
300 // Not walking
301 if (move.Z < 0f)
302 return "CROUCH";
303 else
304 return "STAND";
305 }
306 } 396 }
307 397// rm for jumping else
398 else if (!m_jumping) // add for jumping
399 {
400 m_falling = false; // Add for falling
401 // Not walking
402 if (move.Z < 0f)
403 return "CROUCH";
404 else
405 return "STAND";
406 }
407 // end section realign for jumping
308 #endregion Ground Movement 408 #endregion Ground Movement
309 409
410 m_falling = false; // Add for falling
310 return m_movementAnimation; 411 return m_movementAnimation;
311 } 412 }
312 413
@@ -316,16 +417,15 @@ namespace OpenSim.Region.Framework.Scenes.Animation
316 public void UpdateMovementAnimations() 417 public void UpdateMovementAnimations()
317 { 418 {
318 m_movementAnimation = GetMovementAnimation(); 419 m_movementAnimation = GetMovementAnimation();
319 420/* if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
320 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
321 { 421 {
322 // This was the previous behavior before PREJUMP 422 // This was the previous behavior before PREJUMP
323 TrySetMovementAnimation("JUMP"); 423 TrySetMovementAnimation("JUMP");
324 } 424 }
325 else 425 else
326 { 426 { removed for jumping */
327 TrySetMovementAnimation(m_movementAnimation); 427 TrySetMovementAnimation(m_movementAnimation);
328 } 428// rm for jumping }
329 } 429 }
330 430
331 public UUID[] GetAnimationArray() 431 public UUID[] GetAnimationArray()
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index 64567db..a8d24fd 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -104,8 +104,15 @@ namespace OpenSim.Region.Framework.Scenes
104 // better than losing the object for now. 104 // better than losing the object for now.
105 if (permissionToDelete) 105 if (permissionToDelete)
106 { 106 {
107 List<uint> killIDs = new List<uint>();
108
107 foreach (SceneObjectGroup g in objectGroups) 109 foreach (SceneObjectGroup g in objectGroups)
110 {
111 killIDs.Add(g.LocalId);
108 g.DeleteGroupFromScene(false); 112 g.DeleteGroupFromScene(false);
113 }
114
115 m_scene.SendKillObject(killIDs);
109 } 116 }
110 } 117 }
111 118
@@ -137,7 +144,7 @@ namespace OpenSim.Region.Framework.Scenes
137 x = m_inventoryDeletes.Dequeue(); 144 x = m_inventoryDeletes.Dequeue();
138 145
139 m_log.DebugFormat( 146 m_log.DebugFormat(
140 "[ASYNC DELETER]: Sending object to user's inventory, {0} item(s) remaining.", left); 147 "[ASYNC DELETER]: Sending object to user's inventory, action {1}, count {2}, {0} item(s) remaining.", left, x.action, x.objectGroups.Count);
141 148
142 try 149 try
143 { 150 {
@@ -177,4 +184,4 @@ namespace OpenSim.Region.Framework.Scenes
177 return false; 184 return false;
178 } 185 }
179 } 186 }
180} \ No newline at end of file 187}
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index c321a15..f24c53c 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(ISimulationDataService datastore, bool forceBackup); 64 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
61 65
62 public event OnBackupDelegate OnBackup; 66 public event OnBackupDelegate OnBackup;
@@ -757,6 +761,26 @@ namespace OpenSim.Region.Framework.Scenes
757 } 761 }
758 } 762 }
759 } 763 }
764 public void TriggerTerrainUpdate()
765 {
766 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
767 if (handlerTerrainUpdate != null)
768 {
769 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
770 {
771 try
772 {
773 d();
774 }
775 catch (Exception e)
776 {
777 m_log.ErrorFormat(
778 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
779 e.Message, e.StackTrace);
780 }
781 }
782 }
783 }
760 784
761 public void TriggerTerrainTick() 785 public void TriggerTerrainTick()
762 { 786 {
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index 19f8180..c75f8ba 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -167,6 +167,7 @@ namespace OpenSim.Region.Framework.Scenes
167 167
168 private double GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) 168 private double GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
169 { 169 {
170 if (entity == null) return double.NaN;
170 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 171 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
171 if (presence != null) 172 if (presence != null)
172 { 173 {
@@ -226,9 +227,9 @@ namespace OpenSim.Region.Framework.Scenes
226 return 0.0; 227 return 0.0;
227 228
228 // Use group position for child prims 229 // Use group position for child prims
229 Vector3 entityPos = entity.AbsolutePosition; 230 Vector3 entityPos;
230 if (entity is SceneObjectPart) 231 if (entity is SceneObjectPart)
231 entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition; 232 entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition;
232 else 233 else
233 entityPos = entity.AbsolutePosition; 234 entityPos = entity.AbsolutePosition;
234 235
@@ -251,12 +252,19 @@ namespace OpenSim.Region.Framework.Scenes
251 252
252 if (entity is SceneObjectPart) 253 if (entity is SceneObjectPart)
253 { 254 {
254 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
255 if (physActor == null || !physActor.IsPhysical)
256 priority += 100;
257
258 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) 255 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
256 {
259 priority = 1.0; 257 priority = 1.0;
258 }
259 else
260 {
261 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
262 if (physActor == null || !physActor.IsPhysical)
263 priority += 100;
264 }
265
266 if (((SceneObjectPart)entity).ParentGroup.RootPart != (SceneObjectPart)entity)
267 priority +=1;
260 } 268 }
261 return priority; 269 return priority;
262 } 270 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 4cc797b..1d8b988 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -99,34 +99,22 @@ namespace OpenSim.Region.Framework.Scenes
99 /// <param name="item"></param> 99 /// <param name="item"></param>
100 public bool AddInventoryItem(InventoryItemBase item) 100 public bool AddInventoryItem(InventoryItemBase item)
101 { 101 {
102 if (UUID.Zero == item.Folder) 102 InventoryFolderBase folder;
103
104 if (item.Folder == UUID.Zero)
103 { 105 {
104 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); 106 folder = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
105 if (f != null) 107 if (folder == null)
106 {
107// m_log.DebugFormat(
108// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}",
109// f.Name, (AssetType)f.Type, item.Name);
110
111 item.Folder = f.ID;
112 }
113 else
114 { 108 {
115 f = InventoryService.GetRootFolder(item.Owner); 109 folder = InventoryService.GetRootFolder(item.Owner);
116 if (f != null) 110
117 { 111 if (folder == null)
118 item.Folder = f.ID;
119 }
120 else
121 {
122 m_log.WarnFormat(
123 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
124 item.Owner, item.Name);
125 return false; 112 return false;
126 }
127 } 113 }
114
115 item.Folder = folder.ID;
128 } 116 }
129 117
130 if (InventoryService.AddItem(item)) 118 if (InventoryService.AddItem(item))
131 { 119 {
132 int userlevel = 0; 120 int userlevel = 0;
@@ -252,8 +240,7 @@ namespace OpenSim.Region.Framework.Scenes
252 240
253 // Update item with new asset 241 // Update item with new asset
254 item.AssetID = asset.FullID; 242 item.AssetID = asset.FullID;
255 if (group.UpdateInventoryItem(item)) 243 group.UpdateInventoryItem(item);
256 remoteClient.SendAgentAlertMessage("Script saved", false);
257 244
258 part.GetProperties(remoteClient); 245 part.GetProperties(remoteClient);
259 246
@@ -264,12 +251,7 @@ namespace OpenSim.Region.Framework.Scenes
264 { 251 {
265 // Needs to determine which engine was running it and use that 252 // Needs to determine which engine was running it and use that
266 // 253 //
267 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 254 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
268 errors = part.Inventory.GetScriptErrors(item.ItemID);
269 }
270 else
271 {
272 remoteClient.SendAgentAlertMessage("Script saved", false);
273 } 255 }
274 part.ParentGroup.ResumeScripts(); 256 part.ParentGroup.ResumeScripts();
275 return errors; 257 return errors;
@@ -683,6 +665,8 @@ namespace OpenSim.Region.Framework.Scenes
683 return; 665 return;
684 } 666 }
685 667
668 if (newName == null) newName = item.Name;
669
686 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 670 AssetBase asset = AssetService.Get(item.AssetID.ToString());
687 671
688 if (asset != null) 672 if (asset != null)
@@ -730,6 +714,24 @@ namespace OpenSim.Region.Framework.Scenes
730 } 714 }
731 715
732 /// <summary> 716 /// <summary>
717 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
718 /// </summary>
719 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
720 {
721 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
722 foreach (InventoryItemBase b in items)
723 {
724 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
725 InventoryItemBase n = InventoryService.GetItem(b);
726 n.Folder = destfolder;
727 moveitems.Add(n);
728 remoteClient.SendInventoryItemCreateUpdate(n, 0);
729 }
730
731 MoveInventoryItem(remoteClient, moveitems);
732 }
733
734 /// <summary>
733 /// Move an item within the agent's inventory. 735 /// Move an item within the agent's inventory.
734 /// </summary> 736 /// </summary>
735 /// <param name="remoteClient"></param> 737 /// <param name="remoteClient"></param>
@@ -972,8 +974,12 @@ namespace OpenSim.Region.Framework.Scenes
972 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 974 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
973 { 975 {
974 SceneObjectPart part = GetSceneObjectPart(localID); 976 SceneObjectPart part = GetSceneObjectPart(localID);
975 SceneObjectGroup group = part.ParentGroup; 977 SceneObjectGroup group = null;
976 if (group != null) 978 if (part != null)
979 {
980 group = part.ParentGroup;
981 }
982 if (part != null && group != null)
977 { 983 {
978 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) 984 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
979 return; 985 return;
@@ -1420,13 +1426,6 @@ namespace OpenSim.Region.Framework.Scenes
1420 { 1426 {
1421 agentTransactions.HandleTaskItemUpdateFromTransaction( 1427 agentTransactions.HandleTaskItemUpdateFromTransaction(
1422 remoteClient, part, transactionID, currentItem); 1428 remoteClient, part, transactionID, currentItem);
1423
1424 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1425 remoteClient.SendAgentAlertMessage("Notecard saved", false);
1426 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1427 remoteClient.SendAgentAlertMessage("Script saved", false);
1428 else
1429 remoteClient.SendAgentAlertMessage("Item saved", false);
1430 } 1429 }
1431 1430
1432 // Base ALWAYS has move 1431 // Base ALWAYS has move
@@ -1544,7 +1543,7 @@ namespace OpenSim.Region.Framework.Scenes
1544 return; 1543 return;
1545 1544
1546 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1545 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1547 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1546 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1548 remoteClient.AgentId); 1547 remoteClient.AgentId);
1549 AssetService.Store(asset); 1548 AssetService.Store(asset);
1550 1549
@@ -1696,23 +1695,32 @@ namespace OpenSim.Region.Framework.Scenes
1696 // build a list of eligible objects 1695 // build a list of eligible objects
1697 List<uint> deleteIDs = new List<uint>(); 1696 List<uint> deleteIDs = new List<uint>();
1698 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1697 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1699 1698 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1700 // Start with true for both, then remove the flags if objects
1701 // that we can't derez are part of the selection
1702 bool permissionToTake = true;
1703 bool permissionToTakeCopy = true;
1704 bool permissionToDelete = true;
1705 1699
1706 foreach (uint localID in localIDs) 1700 foreach (uint localID in localIDs)
1707 { 1701 {
1702 // Start with true for both, then remove the flags if objects
1703 // that we can't derez are part of the selection
1704 bool permissionToTake = true;
1705 bool permissionToTakeCopy = true;
1706 bool permissionToDelete = true;
1707
1708 // Invalid id 1708 // Invalid id
1709 SceneObjectPart part = GetSceneObjectPart(localID); 1709 SceneObjectPart part = GetSceneObjectPart(localID);
1710 if (part == null) 1710 if (part == null)
1711 {
1712 //Client still thinks the object exists, kill it
1713 deleteIDs.Add(localID);
1711 continue; 1714 continue;
1715 }
1712 1716
1713 // Already deleted by someone else 1717 // Already deleted by someone else
1714 if (part.ParentGroup == null || part.ParentGroup.IsDeleted) 1718 if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
1719 {
1720 //Client still thinks the object exists, kill it
1721 deleteIDs.Add(localID);
1715 continue; 1722 continue;
1723 }
1716 1724
1717 // Can't delete child prims 1725 // Can't delete child prims
1718 if (part != part.ParentGroup.RootPart) 1726 if (part != part.ParentGroup.RootPart)
@@ -1720,9 +1728,6 @@ namespace OpenSim.Region.Framework.Scenes
1720 1728
1721 SceneObjectGroup grp = part.ParentGroup; 1729 SceneObjectGroup grp = part.ParentGroup;
1722 1730
1723 deleteIDs.Add(localID);
1724 deleteGroups.Add(grp);
1725
1726 if (remoteClient == null) 1731 if (remoteClient == null)
1727 { 1732 {
1728 // Autoreturn has a null client. Nothing else does. So 1733 // Autoreturn has a null client. Nothing else does. So
@@ -1734,8 +1739,15 @@ namespace OpenSim.Region.Framework.Scenes
1734 } 1739 }
1735 else 1740 else
1736 { 1741 {
1737 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1742 if (action == DeRezAction.TakeCopy)
1743 {
1744 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1745 permissionToTakeCopy = false;
1746 }
1747 else
1748 {
1738 permissionToTakeCopy = false; 1749 permissionToTakeCopy = false;
1750 }
1739 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1751 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1740 permissionToTake = false; 1752 permissionToTake = false;
1741 1753
@@ -1743,71 +1755,88 @@ namespace OpenSim.Region.Framework.Scenes
1743 permissionToDelete = false; 1755 permissionToDelete = false;
1744 } 1756 }
1745 1757
1746 } 1758 // Handle god perms
1747 1759 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1748 // Handle god perms 1760 {
1749 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1761 permissionToTake = true;
1750 { 1762 permissionToTakeCopy = true;
1751 permissionToTake = true; 1763 permissionToDelete = true;
1752 permissionToTakeCopy = true; 1764 }
1753 permissionToDelete = true;
1754 }
1755 1765
1756 // If we're re-saving, we don't even want to delete 1766 // If we're re-saving, we don't even want to delete
1757 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1767 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1758 permissionToDelete = false; 1768 permissionToDelete = false;
1759 1769
1760 // if we want to take a copy, we also don't want to delete 1770 // if we want to take a copy, we also don't want to delete
1761 // Note: after this point, the permissionToTakeCopy flag 1771 // Note: after this point, the permissionToTakeCopy flag
1762 // becomes irrelevant. It already includes the permissionToTake 1772 // becomes irrelevant. It already includes the permissionToTake
1763 // permission and after excluding no copy items here, we can 1773 // permission and after excluding no copy items here, we can
1764 // just use that. 1774 // just use that.
1765 if (action == DeRezAction.TakeCopy) 1775 if (action == DeRezAction.TakeCopy)
1766 { 1776 {
1767 // If we don't have permission, stop right here 1777 // If we don't have permission, stop right here
1768 if (!permissionToTakeCopy) 1778 if (!permissionToTakeCopy)
1769 return; 1779 return;
1770 1780
1771 permissionToTake = true; 1781 permissionToTake = true;
1772 // Don't delete 1782 // Don't delete
1773 permissionToDelete = false; 1783 permissionToDelete = false;
1774 } 1784 }
1775 1785
1776 if (action == DeRezAction.Return) 1786 if (action == DeRezAction.Return)
1777 {
1778 if (remoteClient != null)
1779 { 1787 {
1780 if (Permissions.CanReturnObjects( 1788 if (remoteClient != null)
1781 null,
1782 remoteClient.AgentId,
1783 deleteGroups))
1784 { 1789 {
1785 permissionToTake = true; 1790 if (Permissions.CanReturnObjects(
1786 permissionToDelete = true; 1791 null,
1787 1792 remoteClient.AgentId,
1788 foreach (SceneObjectGroup g in deleteGroups) 1793 deleteGroups))
1789 { 1794 {
1790 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1795 permissionToTake = true;
1796 permissionToDelete = true;
1797
1798 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1791 } 1799 }
1792 } 1800 }
1801 else // Auto return passes through here with null agent
1802 {
1803 permissionToTake = true;
1804 permissionToDelete = true;
1805 }
1793 } 1806 }
1794 else // Auto return passes through here with null agent 1807
1808 if (permissionToTake && (!permissionToDelete))
1809 takeGroups.Add(grp);
1810
1811 if (permissionToDelete)
1795 { 1812 {
1796 permissionToTake = true; 1813 if (permissionToTake)
1797 permissionToDelete = true; 1814 deleteGroups.Add(grp);
1815 deleteIDs.Add(grp.LocalId);
1798 } 1816 }
1799 } 1817 }
1800 1818
1801 if (permissionToTake) 1819 SendKillObject(deleteIDs);
1820
1821 if (deleteGroups.Count > 0)
1802 { 1822 {
1823 foreach (SceneObjectGroup g in deleteGroups)
1824 deleteIDs.Remove(g.LocalId);
1825
1803 m_asyncSceneObjectDeleter.DeleteToInventory( 1826 m_asyncSceneObjectDeleter.DeleteToInventory(
1804 action, destinationID, deleteGroups, remoteClient, 1827 action, destinationID, deleteGroups, remoteClient,
1805 permissionToDelete); 1828 true);
1829 }
1830 if (takeGroups.Count > 0)
1831 {
1832 m_asyncSceneObjectDeleter.DeleteToInventory(
1833 action, destinationID, takeGroups, remoteClient,
1834 false);
1806 } 1835 }
1807 else if (permissionToDelete) 1836 if (deleteIDs.Count > 0)
1808 { 1837 {
1809 foreach (SceneObjectGroup g in deleteGroups) 1838 foreach (SceneObjectGroup g in deleteGroups)
1810 DeleteSceneObject(g, false); 1839 DeleteSceneObject(g, true);
1811 } 1840 }
1812 } 1841 }
1813 1842
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 96a9f99..3ae8a38 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -84,6 +84,7 @@ namespace OpenSim.Region.Framework.Scenes
84 // TODO: need to figure out how allow client agents but deny 84 // TODO: need to figure out how allow client agents but deny
85 // root agents when ACL denies access to root agent 85 // root agents when ACL denies access to root agent
86 public bool m_strictAccessControl = true; 86 public bool m_strictAccessControl = true;
87 public bool m_seeIntoBannedRegion = false;
87 public int MaxUndoCount = 5; 88 public int MaxUndoCount = 5;
88 public bool LoginsDisabled = true; 89 public bool LoginsDisabled = true;
89 public bool LoadingPrims; 90 public bool LoadingPrims;
@@ -102,6 +103,7 @@ namespace OpenSim.Region.Framework.Scenes
102 protected ModuleLoader m_moduleLoader; 103 protected ModuleLoader m_moduleLoader;
103 protected AgentCircuitManager m_authenticateHandler; 104 protected AgentCircuitManager m_authenticateHandler;
104 protected SceneCommunicationService m_sceneGridService; 105 protected SceneCommunicationService m_sceneGridService;
106 protected ISnmpModule m_snmpService = null;
105 107
106 protected ISimulationDataService m_SimulationDataService; 108 protected ISimulationDataService m_SimulationDataService;
107 protected IEstateDataService m_EstateDataService; 109 protected IEstateDataService m_EstateDataService;
@@ -163,6 +165,7 @@ namespace OpenSim.Region.Framework.Scenes
163 private int landMS; 165 private int landMS;
164 private int lastCompletedFrame; 166 private int lastCompletedFrame;
165 167
168 public bool CombineRegions = false;
166 private bool m_physics_enabled = true; 169 private bool m_physics_enabled = true;
167 private bool m_scripts_enabled = true; 170 private bool m_scripts_enabled = true;
168 private string m_defaultScriptEngine; 171 private string m_defaultScriptEngine;
@@ -218,6 +221,19 @@ namespace OpenSim.Region.Framework.Scenes
218 get { return m_sceneGridService; } 221 get { return m_sceneGridService; }
219 } 222 }
220 223
224 public ISnmpModule SnmpService
225 {
226 get
227 {
228 if (m_snmpService == null)
229 {
230 m_snmpService = RequestModuleInterface<ISnmpModule>();
231 }
232
233 return m_snmpService;
234 }
235 }
236
221 public ISimulationDataService SimulationDataService 237 public ISimulationDataService SimulationDataService
222 { 238 {
223 get 239 get
@@ -562,6 +578,8 @@ namespace OpenSim.Region.Framework.Scenes
562 #region Region Settings 578 #region Region Settings
563 579
564 // Load region settings 580 // Load region settings
581 m_regInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(m_regInfo.RegionID);
582
565 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID); 583 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID);
566 if (estateDataService != null) 584 if (estateDataService != null)
567 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false); 585 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -621,9 +639,10 @@ namespace OpenSim.Region.Framework.Scenes
621 //Animation states 639 //Animation states
622 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 640 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
623 // TODO: Change default to true once the feature is supported 641 // TODO: Change default to true once the feature is supported
624 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 642 m_usePreJump = startupConfig.GetBoolean("enableprejump", true);
625
626 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 643 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
644
645 m_log.DebugFormat("[SCENE]: prejump is {0}", m_usePreJump ? "ON" : "OFF");
627 if (RegionInfo.NonphysPrimMax > 0) 646 if (RegionInfo.NonphysPrimMax > 0)
628 { 647 {
629 m_maxNonphys = RegionInfo.NonphysPrimMax; 648 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -655,6 +674,7 @@ namespace OpenSim.Region.Framework.Scenes
655 m_persistAfter *= 10000000; 674 m_persistAfter *= 10000000;
656 675
657 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 676 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
677 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
658 678
659 IConfig packetConfig = m_config.Configs["PacketPool"]; 679 IConfig packetConfig = m_config.Configs["PacketPool"];
660 if (packetConfig != null) 680 if (packetConfig != null)
@@ -664,6 +684,8 @@ namespace OpenSim.Region.Framework.Scenes
664 } 684 }
665 685
666 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 686 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
687 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
688 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
667 689
668 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 690 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
669 if (m_generateMaptiles) 691 if (m_generateMaptiles)
@@ -688,9 +710,9 @@ namespace OpenSim.Region.Framework.Scenes
688 } 710 }
689 } 711 }
690 } 712 }
691 catch 713 catch (Exception e)
692 { 714 {
693 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 715 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
694 } 716 }
695 717
696 #endregion Region Config 718 #endregion Region Config
@@ -927,6 +949,15 @@ namespace OpenSim.Region.Framework.Scenes
927 /// <param name="seconds">float indicating duration before restart.</param> 949 /// <param name="seconds">float indicating duration before restart.</param>
928 public virtual void Restart(float seconds) 950 public virtual void Restart(float seconds)
929 { 951 {
952 Restart(seconds, true);
953 }
954
955 /// <summary>
956 /// Given float seconds, this will restart the region. showDialog will optionally alert the users.
957 /// </summary>
958 /// <param name="seconds">float indicating duration before restart.</param>
959 public virtual void Restart(float seconds, bool showDialog)
960 {
930 // notifications are done in 15 second increments 961 // notifications are done in 15 second increments
931 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request 962 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request
932 // It's a 'Cancel restart' request. 963 // It's a 'Cancel restart' request.
@@ -947,8 +978,11 @@ namespace OpenSim.Region.Framework.Scenes
947 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed); 978 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed);
948 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes"); 979 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes");
949 m_restartTimer.Start(); 980 m_restartTimer.Start();
950 m_dialogModule.SendNotificationToUsersInRegion( 981 if (showDialog)
982 {
983 m_dialogModule.SendNotificationToUsersInRegion(
951 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0))); 984 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0)));
985 }
952 } 986 }
953 } 987 }
954 988
@@ -1144,6 +1178,7 @@ namespace OpenSim.Region.Framework.Scenes
1144 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1178 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1145 if (HeartbeatThread != null) 1179 if (HeartbeatThread != null)
1146 { 1180 {
1181 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1147 HeartbeatThread.Abort(); 1182 HeartbeatThread.Abort();
1148 HeartbeatThread = null; 1183 HeartbeatThread = null;
1149 } 1184 }
@@ -1815,14 +1850,24 @@ namespace OpenSim.Region.Framework.Scenes
1815 /// <returns></returns> 1850 /// <returns></returns>
1816 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1851 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1817 { 1852 {
1853
1854 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1855 Vector3 wpos = Vector3.Zero;
1856 // Check for water surface intersection from above
1857 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1858 {
1859 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1860 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1861 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1862 wpos.Z = wheight;
1863 }
1864
1818 Vector3 pos = Vector3.Zero; 1865 Vector3 pos = Vector3.Zero;
1819 if (RayEndIsIntersection == (byte)1) 1866 if (RayEndIsIntersection == (byte)1)
1820 { 1867 {
1821 pos = RayEnd; 1868 pos = RayEnd;
1822 return pos;
1823 } 1869 }
1824 1870 else if (RayTargetID != UUID.Zero)
1825 if (RayTargetID != UUID.Zero)
1826 { 1871 {
1827 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1872 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1828 1873
@@ -1844,7 +1889,7 @@ namespace OpenSim.Region.Framework.Scenes
1844 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1889 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1845 1890
1846 // Un-comment out the following line to Get Raytrace results printed to the console. 1891 // Un-comment out the following line to Get Raytrace results printed to the console.
1847 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1892 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1848 float ScaleOffset = 0.5f; 1893 float ScaleOffset = 0.5f;
1849 1894
1850 // If we hit something 1895 // If we hit something
@@ -1867,13 +1912,10 @@ namespace OpenSim.Region.Framework.Scenes
1867 //pos.Z -= 0.25F; 1912 //pos.Z -= 0.25F;
1868 1913
1869 } 1914 }
1870
1871 return pos;
1872 } 1915 }
1873 else 1916 else
1874 { 1917 {
1875 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1918 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1876
1877 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1919 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1878 1920
1879 // Un-comment the following line to print the raytrace results to the console. 1921 // Un-comment the following line to print the raytrace results to the console.
@@ -1882,13 +1924,12 @@ namespace OpenSim.Region.Framework.Scenes
1882 if (ei.HitTF) 1924 if (ei.HitTF)
1883 { 1925 {
1884 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1926 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1885 } else 1927 }
1928 else
1886 { 1929 {
1887 // fall back to our stupid functionality 1930 // fall back to our stupid functionality
1888 pos = RayEnd; 1931 pos = RayEnd;
1889 } 1932 }
1890
1891 return pos;
1892 } 1933 }
1893 } 1934 }
1894 else 1935 else
@@ -1899,8 +1940,12 @@ namespace OpenSim.Region.Framework.Scenes
1899 //increase height so its above the ground. 1940 //increase height so its above the ground.
1900 //should be getting the normal of the ground at the rez point and using that? 1941 //should be getting the normal of the ground at the rez point and using that?
1901 pos.Z += scale.Z / 2f; 1942 pos.Z += scale.Z / 2f;
1902 return pos; 1943// return pos;
1903 } 1944 }
1945
1946 // check against posible water intercept
1947 if (wpos.Z > pos.Z) pos = wpos;
1948 return pos;
1904 } 1949 }
1905 1950
1906 1951
@@ -1980,7 +2025,10 @@ namespace OpenSim.Region.Framework.Scenes
1980 public bool AddRestoredSceneObject( 2025 public bool AddRestoredSceneObject(
1981 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 2026 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1982 { 2027 {
1983 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 2028 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
2029 if (result)
2030 sceneObject.IsDeleted = false;
2031 return result;
1984 } 2032 }
1985 2033
1986 /// <summary> 2034 /// <summary>
@@ -2057,6 +2105,15 @@ namespace OpenSim.Region.Framework.Scenes
2057 /// </summary> 2105 /// </summary>
2058 public void DeleteAllSceneObjects() 2106 public void DeleteAllSceneObjects()
2059 { 2107 {
2108 DeleteAllSceneObjects(false);
2109 }
2110
2111 /// <summary>
2112 /// Delete every object from the scene. This does not include attachments worn by avatars.
2113 /// </summary>
2114 public void DeleteAllSceneObjects(bool exceptNoCopy)
2115 {
2116 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2060 lock (Entities) 2117 lock (Entities)
2061 { 2118 {
2062 EntityBase[] entities = Entities.GetEntities(); 2119 EntityBase[] entities = Entities.GetEntities();
@@ -2065,11 +2122,24 @@ namespace OpenSim.Region.Framework.Scenes
2065 if (e is SceneObjectGroup) 2122 if (e is SceneObjectGroup)
2066 { 2123 {
2067 SceneObjectGroup sog = (SceneObjectGroup)e; 2124 SceneObjectGroup sog = (SceneObjectGroup)e;
2068 if (!sog.IsAttachment) 2125 if (sog != null && !sog.IsAttachment)
2069 DeleteSceneObject((SceneObjectGroup)e, false); 2126 {
2127 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2128 {
2129 DeleteSceneObject((SceneObjectGroup)e, false);
2130 }
2131 else
2132 {
2133 toReturn.Add((SceneObjectGroup)e);
2134 }
2135 }
2070 } 2136 }
2071 } 2137 }
2072 } 2138 }
2139 if (toReturn.Count > 0)
2140 {
2141 returnObjects(toReturn.ToArray(), UUID.Zero);
2142 }
2073 } 2143 }
2074 2144
2075 /// <summary> 2145 /// <summary>
@@ -2118,6 +2188,8 @@ namespace OpenSim.Region.Framework.Scenes
2118 } 2188 }
2119 2189
2120 group.DeleteGroupFromScene(silent); 2190 group.DeleteGroupFromScene(silent);
2191 if (!silent)
2192 SendKillObject(new List<uint>() { group.LocalId });
2121 2193
2122// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2194// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2123 } 2195 }
@@ -2447,6 +2519,12 @@ namespace OpenSim.Region.Framework.Scenes
2447 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2519 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2448 public bool AddSceneObject(SceneObjectGroup sceneObject) 2520 public bool AddSceneObject(SceneObjectGroup sceneObject)
2449 { 2521 {
2522 if (sceneObject.OwnerID == UUID.Zero)
2523 {
2524 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2525 return false;
2526 }
2527
2450 // If the user is banned, we won't let any of their objects 2528 // If the user is banned, we won't let any of their objects
2451 // enter. Period. 2529 // enter. Period.
2452 // 2530 //
@@ -2494,15 +2572,28 @@ namespace OpenSim.Region.Framework.Scenes
2494 2572
2495 if (AttachmentsModule != null) 2573 if (AttachmentsModule != null)
2496 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); 2574 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
2575
2576 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was found, attaching", sceneObject.UUID);
2497 } 2577 }
2498 else 2578 else
2499 { 2579 {
2580 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2500 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2581 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2501 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2582 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2502 } 2583 }
2584 if (sceneObject.OwnerID == UUID.Zero)
2585 {
2586 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2587 return false;
2588 }
2503 } 2589 }
2504 else 2590 else
2505 { 2591 {
2592 if (sceneObject.OwnerID == UUID.Zero)
2593 {
2594 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2595 return false;
2596 }
2506 AddRestoredSceneObject(sceneObject, true, false); 2597 AddRestoredSceneObject(sceneObject, true, false);
2507 2598
2508 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2599 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2775,6 +2866,7 @@ namespace OpenSim.Region.Framework.Scenes
2775 client.OnFetchInventory += HandleFetchInventory; 2866 client.OnFetchInventory += HandleFetchInventory;
2776 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2867 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2777 client.OnCopyInventoryItem += CopyInventoryItem; 2868 client.OnCopyInventoryItem += CopyInventoryItem;
2869 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2778 client.OnMoveInventoryItem += MoveInventoryItem; 2870 client.OnMoveInventoryItem += MoveInventoryItem;
2779 client.OnRemoveInventoryItem += RemoveInventoryItem; 2871 client.OnRemoveInventoryItem += RemoveInventoryItem;
2780 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2872 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2953,15 +3045,16 @@ namespace OpenSim.Region.Framework.Scenes
2953 /// </summary> 3045 /// </summary>
2954 /// <param name="agentId">The avatar's Unique ID</param> 3046 /// <param name="agentId">The avatar's Unique ID</param>
2955 /// <param name="client">The IClientAPI for the client</param> 3047 /// <param name="client">The IClientAPI for the client</param>
2956 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3048 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2957 { 3049 {
2958 if (m_teleportModule != null) 3050 if (m_teleportModule != null)
2959 m_teleportModule.TeleportHome(agentId, client); 3051 return m_teleportModule.TeleportHome(agentId, client);
2960 else 3052 else
2961 { 3053 {
2962 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3054 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2963 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3055 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2964 } 3056 }
3057 return false;
2965 } 3058 }
2966 3059
2967 /// <summary> 3060 /// <summary>
@@ -3060,6 +3153,16 @@ namespace OpenSim.Region.Framework.Scenes
3060 /// <param name="flags"></param> 3153 /// <param name="flags"></param>
3061 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3154 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3062 { 3155 {
3156 //Add half the avatar's height so that the user doesn't fall through prims
3157 ScenePresence presence;
3158 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3159 {
3160 if (presence.Appearance != null)
3161 {
3162 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3163 }
3164 }
3165
3063 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3166 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3064 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3167 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3065 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3168 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3153,7 +3256,9 @@ namespace OpenSim.Region.Framework.Scenes
3153 regions.Remove(RegionInfo.RegionHandle); 3256 regions.Remove(RegionInfo.RegionHandle);
3154 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3257 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3155 } 3258 }
3259 m_log.Debug("[Scene] Beginning ClientClosed");
3156 m_eventManager.TriggerClientClosed(agentID, this); 3260 m_eventManager.TriggerClientClosed(agentID, this);
3261 m_log.Debug("[Scene] Finished ClientClosed");
3157 } 3262 }
3158 catch (NullReferenceException) 3263 catch (NullReferenceException)
3159 { 3264 {
@@ -3161,7 +3266,12 @@ namespace OpenSim.Region.Framework.Scenes
3161 // Avatar is already disposed :/ 3266 // Avatar is already disposed :/
3162 } 3267 }
3163 3268
3269 m_log.Debug("[Scene] Beginning OnRemovePresence");
3164 m_eventManager.TriggerOnRemovePresence(agentID); 3270 m_eventManager.TriggerOnRemovePresence(agentID);
3271 m_log.Debug("[Scene] Finished OnRemovePresence");
3272
3273 if (avatar != null && (!avatar.IsChildAgent))
3274 avatar.SaveChangedAttachments();
3165 3275
3166 if (avatar != null && (!avatar.IsChildAgent)) 3276 if (avatar != null && (!avatar.IsChildAgent))
3167 avatar.SaveChangedAttachments(); 3277 avatar.SaveChangedAttachments();
@@ -3170,7 +3280,7 @@ namespace OpenSim.Region.Framework.Scenes
3170 delegate(IClientAPI client) 3280 delegate(IClientAPI client)
3171 { 3281 {
3172 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3282 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3173 try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); } 3283 try { client.SendKillObject(avatar.RegionHandle, new List<uint>() { avatar.LocalId}); }
3174 catch (NullReferenceException) { } 3284 catch (NullReferenceException) { }
3175 }); 3285 });
3176 3286
@@ -3181,8 +3291,11 @@ namespace OpenSim.Region.Framework.Scenes
3181 } 3291 }
3182 3292
3183 // Remove the avatar from the scene 3293 // Remove the avatar from the scene
3294 m_log.Debug("[Scene] Begin RemoveScenePresence");
3184 m_sceneGraph.RemoveScenePresence(agentID); 3295 m_sceneGraph.RemoveScenePresence(agentID);
3296 m_log.Debug("[Scene] Finished RemoveScenePresence. Removing the client manager");
3185 m_clientManager.Remove(agentID); 3297 m_clientManager.Remove(agentID);
3298 m_log.Debug("[Scene] Removed the client manager. Firing avatar.close");
3186 3299
3187 try 3300 try
3188 { 3301 {
@@ -3196,9 +3309,10 @@ namespace OpenSim.Region.Framework.Scenes
3196 { 3309 {
3197 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString()); 3310 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString());
3198 } 3311 }
3199 3312 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3200 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3313 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3201 CleanDroppedAttachments(); 3314 CleanDroppedAttachments();
3315 m_log.Debug("[Scene] The avatar has left the building");
3202 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3316 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3203 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3317 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3204 } 3318 }
@@ -3229,18 +3343,24 @@ namespace OpenSim.Region.Framework.Scenes
3229 3343
3230 #region Entities 3344 #region Entities
3231 3345
3232 public void SendKillObject(uint localID) 3346 public void SendKillObject(List<uint> localIDs)
3233 { 3347 {
3234 SceneObjectPart part = GetSceneObjectPart(localID); 3348 List<uint> deleteIDs = new List<uint>();
3235 if (part != null) // It is a prim 3349
3350 foreach (uint localID in localIDs)
3236 { 3351 {
3237 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid 3352 SceneObjectPart part = GetSceneObjectPart(localID);
3353 if (part != null) // It is a prim
3238 { 3354 {
3239 if (part.ParentGroup.RootPart != part) // Child part 3355 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid
3240 return; 3356 {
3357 if (part.ParentGroup.RootPart != part) // Child part
3358 continue;
3359 }
3241 } 3360 }
3361 deleteIDs.Add(localID);
3242 } 3362 }
3243 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); }); 3363 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); });
3244 } 3364 }
3245 3365
3246 #endregion 3366 #endregion
@@ -3258,7 +3378,6 @@ namespace OpenSim.Region.Framework.Scenes
3258 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; 3378 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
3259 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; 3379 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
3260 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; 3380 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
3261 m_sceneGridService.KiPrimitive += SendKillObject;
3262 m_sceneGridService.OnGetLandData += GetLandData; 3381 m_sceneGridService.OnGetLandData += GetLandData;
3263 } 3382 }
3264 3383
@@ -3267,7 +3386,6 @@ namespace OpenSim.Region.Framework.Scenes
3267 /// </summary> 3386 /// </summary>
3268 public void UnRegisterRegionWithComms() 3387 public void UnRegisterRegionWithComms()
3269 { 3388 {
3270 m_sceneGridService.KiPrimitive -= SendKillObject;
3271 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; 3389 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid;
3272 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; 3390 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar;
3273 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; 3391 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;
@@ -3354,6 +3472,7 @@ namespace OpenSim.Region.Framework.Scenes
3354 { 3472 {
3355 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3473 if (land != null && !TestLandRestrictions(agent, land, out reason))
3356 { 3474 {
3475 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3357 return false; 3476 return false;
3358 } 3477 }
3359 } 3478 }
@@ -3471,6 +3590,8 @@ namespace OpenSim.Region.Framework.Scenes
3471 } 3590 }
3472 } 3591 }
3473 // Honor parcel landing type and position. 3592 // Honor parcel landing type and position.
3593 /*
3594 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3474 if (land != null) 3595 if (land != null)
3475 { 3596 {
3476 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3597 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3478,6 +3599,7 @@ namespace OpenSim.Region.Framework.Scenes
3478 agent.startpos = land.LandData.UserLocation; 3599 agent.startpos = land.LandData.UserLocation;
3479 } 3600 }
3480 } 3601 }
3602 */// This is now handled properly in ScenePresence.MakeRootAgent
3481 } 3603 }
3482 3604
3483 return true; 3605 return true;
@@ -3573,7 +3695,7 @@ namespace OpenSim.Region.Framework.Scenes
3573 3695
3574 if (m_regInfo.EstateSettings != null) 3696 if (m_regInfo.EstateSettings != null)
3575 { 3697 {
3576 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3698 if ((!m_seeIntoBannedRegion) && m_regInfo.EstateSettings.IsBanned(agent.AgentID))
3577 { 3699 {
3578 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3700 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3579 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3701 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3763,6 +3885,12 @@ namespace OpenSim.Region.Framework.Scenes
3763 3885
3764 // We have to wait until the viewer contacts this region after receiving EAC. 3886 // We have to wait until the viewer contacts this region after receiving EAC.
3765 // That calls AddNewClient, which finally creates the ScenePresence 3887 // That calls AddNewClient, which finally creates the ScenePresence
3888 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID))
3889 {
3890 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3891 return false;
3892 }
3893
3766 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3894 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3767 if (nearestParcel == null) 3895 if (nearestParcel == null)
3768 { 3896 {
@@ -3770,6 +3898,14 @@ namespace OpenSim.Region.Framework.Scenes
3770 return false; 3898 return false;
3771 } 3899 }
3772 3900
3901 int num = m_sceneGraph.GetNumberOfScenePresences();
3902
3903 if (num >= RegionInfo.RegionSettings.AgentLimit)
3904 {
3905 if (!Permissions.IsAdministrator(cAgentData.AgentID))
3906 return false;
3907 }
3908
3773 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 3909 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
3774 if (childAgentUpdate != null) 3910 if (childAgentUpdate != null)
3775 { 3911 {
@@ -3835,12 +3971,22 @@ namespace OpenSim.Region.Framework.Scenes
3835 return false; 3971 return false;
3836 } 3972 }
3837 3973
3974 public bool IncomingCloseAgent(UUID agentID)
3975 {
3976 return IncomingCloseAgent(agentID, false);
3977 }
3978
3979 public bool IncomingCloseChildAgent(UUID agentID)
3980 {
3981 return IncomingCloseAgent(agentID, true);
3982 }
3983
3838 /// <summary> 3984 /// <summary>
3839 /// Tell a single agent to disconnect from the region. 3985 /// Tell a single agent to disconnect from the region.
3840 /// </summary> 3986 /// </summary>
3841 /// <param name="regionHandle"></param>
3842 /// <param name="agentID"></param> 3987 /// <param name="agentID"></param>
3843 public bool IncomingCloseAgent(UUID agentID) 3988 /// <param name="childOnly"></param>
3989 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3844 { 3990 {
3845 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3991 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3846 3992
@@ -3852,7 +3998,7 @@ namespace OpenSim.Region.Framework.Scenes
3852 { 3998 {
3853 m_sceneGraph.removeUserCount(false); 3999 m_sceneGraph.removeUserCount(false);
3854 } 4000 }
3855 else 4001 else if (!childOnly)
3856 { 4002 {
3857 m_sceneGraph.removeUserCount(true); 4003 m_sceneGraph.removeUserCount(true);
3858 } 4004 }
@@ -3868,9 +4014,12 @@ namespace OpenSim.Region.Framework.Scenes
3868 } 4014 }
3869 else 4015 else
3870 presence.ControllingClient.SendShutdownConnectionNotice(); 4016 presence.ControllingClient.SendShutdownConnectionNotice();
4017 presence.ControllingClient.Close(false);
4018 }
4019 else if (!childOnly)
4020 {
4021 presence.ControllingClient.Close(true);
3871 } 4022 }
3872
3873 presence.ControllingClient.Close();
3874 return true; 4023 return true;
3875 } 4024 }
3876 4025
@@ -4492,7 +4641,7 @@ namespace OpenSim.Region.Framework.Scenes
4492 // 4641 //
4493 int health=1; // Start at 1, means we're up 4642 int health=1; // Start at 1, means we're up
4494 4643
4495 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4644 if (m_firstHeartbeat || ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000))
4496 health+=1; 4645 health+=1;
4497 else 4646 else
4498 return health; 4647 return health;
@@ -4955,8 +5104,17 @@ namespace OpenSim.Region.Framework.Scenes
4955 { 5104 {
4956 float ominX, ominY, ominZ, omaxX, omaxY, omaxZ; 5105 float ominX, ominY, ominZ, omaxX, omaxY, omaxZ;
4957 5106
5107 Vector3 vec = g.AbsolutePosition;
5108
4958 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); 5109 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ);
4959 5110
5111 ominX += vec.X;
5112 omaxX += vec.X;
5113 ominY += vec.Y;
5114 omaxY += vec.Y;
5115 ominZ += vec.Z;
5116 omaxZ += vec.Z;
5117
4960 if (minX > ominX) 5118 if (minX > ominX)
4961 minX = ominX; 5119 minX = ominX;
4962 if (minY > ominY) 5120 if (minY > ominY)
@@ -5026,10 +5184,15 @@ namespace OpenSim.Region.Framework.Scenes
5026 }); 5184 });
5027 } 5185 }
5028 5186
5029 foreach (SceneObjectGroup grp in objectsToDelete) 5187 if (objectsToDelete.Count > 0)
5030 { 5188 {
5031 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID); 5189 m_log.DebugFormat("[SCENE]: Starting delete of {0} dropped attachments", objectsToDelete.Count);
5032 DeleteSceneObject(grp, true); 5190 foreach (SceneObjectGroup grp in objectsToDelete)
5191 {
5192 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5193 DeleteSceneObject(grp, true);
5194 }
5195 m_log.Debug("[SCENE]: Finished dropped attachment deletion");
5033 } 5196 }
5034 } 5197 }
5035 } 5198 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 88e084e..632646d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -44,8 +44,6 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
44 44
45namespace OpenSim.Region.Framework.Scenes 45namespace OpenSim.Region.Framework.Scenes
46{ 46{
47 public delegate void KiPrimitiveDelegate(uint localID);
48
49 public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst); 47 public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst);
50 48
51 /// <summary> 49 /// <summary>
@@ -113,8 +111,6 @@ namespace OpenSim.Region.Framework.Scenes
113// private LogOffUser handlerLogOffUser = null; 111// private LogOffUser handlerLogOffUser = null;
114// private GetLandData handlerGetLandData = null; // OnGetLandData 112// private GetLandData handlerGetLandData = null; // OnGetLandData
115 113
116 public KiPrimitiveDelegate KiPrimitive;
117
118 public SceneCommunicationService() 114 public SceneCommunicationService()
119 { 115 {
120 } 116 }
@@ -168,7 +164,7 @@ namespace OpenSim.Region.Framework.Scenes
168 164
169 if (neighbour != null) 165 if (neighbour != null)
170 { 166 {
171 m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); 167 // m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize);
172 m_scene.EventManager.TriggerOnRegionUp(neighbour); 168 m_scene.EventManager.TriggerOnRegionUp(neighbour);
173 } 169 }
174 else 170 else
@@ -183,7 +179,7 @@ namespace OpenSim.Region.Framework.Scenes
183 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); 179 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
184 180
185 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); 181 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
186 m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); 182 //m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count);
187 foreach (GridRegion n in neighbours) 183 foreach (GridRegion n in neighbours)
188 { 184 {
189 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; 185 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
@@ -267,14 +263,14 @@ namespace OpenSim.Region.Framework.Scenes
267 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle) 263 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
268 { 264 {
269 265
270 m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle); 266 //m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle);
271 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 267 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
272 268
273 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); 269 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
274 uint x = 0, y = 0; 270 uint x = 0, y = 0;
275 Utils.LongToUInts(regionHandle, out x, out y); 271 Utils.LongToUInts(regionHandle, out x, out y);
276 GridRegion destination = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y); 272 GridRegion destination = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
277 m_scene.SimulationService.CloseAgent(destination, agentID); 273 m_scene.SimulationService.CloseChildAgent(destination, agentID);
278 } 274 }
279 275
280 private void SendCloseChildAgentCompleted(IAsyncResult iar) 276 private void SendCloseChildAgentCompleted(IAsyncResult iar)
@@ -293,7 +289,7 @@ namespace OpenSim.Region.Framework.Scenes
293 d); 289 d);
294 } 290 }
295 } 291 }
296 292
297 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 293 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
298 { 294 {
299 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 295 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 032c859..b2d9358 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
@@ -124,13 +133,18 @@ namespace OpenSim.Region.Framework.Scenes
124 133
125 protected internal void Close() 134 protected internal void Close()
126 { 135 {
127 lock (m_presenceLock) 136 m_scenePresencesLock.EnterWriteLock();
137 try
128 { 138 {
129 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 139 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
130 List<ScenePresence> newlist = new List<ScenePresence>(); 140 List<ScenePresence> newlist = new List<ScenePresence>();
131 m_scenePresenceMap = newmap; 141 m_scenePresenceMap = newmap;
132 m_scenePresenceArray = newlist; 142 m_scenePresenceArray = newlist;
133 } 143 }
144 finally
145 {
146 m_scenePresencesLock.ExitWriteLock();
147 }
134 148
135 lock (SceneObjectGroupsByFullID) 149 lock (SceneObjectGroupsByFullID)
136 SceneObjectGroupsByFullID.Clear(); 150 SceneObjectGroupsByFullID.Clear();
@@ -209,27 +223,8 @@ namespace OpenSim.Region.Framework.Scenes
209 if (sp.IsChildAgent) 223 if (sp.IsChildAgent)
210 return; 224 return;
211 225
212 if (sp.ParentID != 0) 226 coarseLocations.Add(sp.AbsolutePosition);
213 { 227 avatarUUIDs.Add(sp.UUID);
214 // sitting avatar
215 SceneObjectPart sop = m_parentScene.GetSceneObjectPart(sp.ParentID);
216 if (sop != null)
217 {
218 coarseLocations.Add(sop.AbsolutePosition + sp.AbsolutePosition);
219 avatarUUIDs.Add(sp.UUID);
220 }
221 else
222 {
223 // we can't find the parent.. ! arg!
224 coarseLocations.Add(sp.AbsolutePosition);
225 avatarUUIDs.Add(sp.UUID);
226 }
227 }
228 else
229 {
230 coarseLocations.Add(sp.AbsolutePosition);
231 avatarUUIDs.Add(sp.UUID);
232 }
233 } 228 }
234 } 229 }
235 230
@@ -259,6 +254,33 @@ namespace OpenSim.Region.Framework.Scenes
259 protected internal bool AddRestoredSceneObject( 254 protected internal bool AddRestoredSceneObject(
260 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 255 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
261 { 256 {
257 if (!m_parentScene.CombineRegions)
258 {
259 // KF: Check for out-of-region, move inside and make static.
260 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
261 sceneObject.RootPart.GroupPosition.Y,
262 sceneObject.RootPart.GroupPosition.Z);
263 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 ||
264 npos.X > Constants.RegionSize ||
265 npos.Y > Constants.RegionSize))
266 {
267 if (npos.X < 0.0) npos.X = 1.0f;
268 if (npos.Y < 0.0) npos.Y = 1.0f;
269 if (npos.Z < 0.0) npos.Z = 0.0f;
270 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
271 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
272
273 foreach (SceneObjectPart part in sceneObject.Parts)
274 {
275 part.GroupPosition = npos;
276 }
277 sceneObject.RootPart.Velocity = Vector3.Zero;
278 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
279 sceneObject.RootPart.Acceleration = Vector3.Zero;
280 sceneObject.RootPart.Velocity = Vector3.Zero;
281 }
282 }
283
262 if (attachToBackup && (!alreadyPersisted)) 284 if (attachToBackup && (!alreadyPersisted))
263 { 285 {
264 sceneObject.ForceInventoryPersistence(); 286 sceneObject.ForceInventoryPersistence();
@@ -458,6 +480,30 @@ namespace OpenSim.Region.Framework.Scenes
458 m_updateList[obj.UUID] = obj; 480 m_updateList[obj.UUID] = obj;
459 } 481 }
460 482
483 public void FireAttachToBackup(SceneObjectGroup obj)
484 {
485 if (OnAttachToBackup != null)
486 {
487 OnAttachToBackup(obj);
488 }
489 }
490
491 public void FireDetachFromBackup(SceneObjectGroup obj)
492 {
493 if (OnDetachFromBackup != null)
494 {
495 OnDetachFromBackup(obj);
496 }
497 }
498
499 public void FireChangeBackup(SceneObjectGroup obj)
500 {
501 if (OnChangeBackup != null)
502 {
503 OnChangeBackup(obj);
504 }
505 }
506
461 /// <summary> 507 /// <summary>
462 /// Process all pending updates 508 /// Process all pending updates
463 /// </summary> 509 /// </summary>
@@ -592,7 +638,8 @@ namespace OpenSim.Region.Framework.Scenes
592 638
593 Entities[presence.UUID] = presence; 639 Entities[presence.UUID] = presence;
594 640
595 lock (m_presenceLock) 641 m_scenePresencesLock.EnterWriteLock();
642 try
596 { 643 {
597 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 644 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
598 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 645 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -616,6 +663,10 @@ namespace OpenSim.Region.Framework.Scenes
616 m_scenePresenceMap = newmap; 663 m_scenePresenceMap = newmap;
617 m_scenePresenceArray = newlist; 664 m_scenePresenceArray = newlist;
618 } 665 }
666 finally
667 {
668 m_scenePresencesLock.ExitWriteLock();
669 }
619 } 670 }
620 671
621 /// <summary> 672 /// <summary>
@@ -630,7 +681,8 @@ namespace OpenSim.Region.Framework.Scenes
630 agentID); 681 agentID);
631 } 682 }
632 683
633 lock (m_presenceLock) 684 m_scenePresencesLock.EnterWriteLock();
685 try
634 { 686 {
635 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 687 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
636 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 688 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -652,6 +704,10 @@ namespace OpenSim.Region.Framework.Scenes
652 m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 704 m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
653 } 705 }
654 } 706 }
707 finally
708 {
709 m_scenePresencesLock.ExitWriteLock();
710 }
655 } 711 }
656 712
657 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 713 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -775,6 +831,11 @@ namespace OpenSim.Region.Framework.Scenes
775 return m_scenePresenceArray; 831 return m_scenePresenceArray;
776 } 832 }
777 833
834 public int GetNumberOfScenePresences()
835 {
836 return m_scenePresenceArray.Count;
837 }
838
778 /// <summary> 839 /// <summary>
779 /// Request a scene presence by UUID. Fast, indexed lookup. 840 /// Request a scene presence by UUID. Fast, indexed lookup.
780 /// </summary> 841 /// </summary>
@@ -1068,9 +1129,11 @@ namespace OpenSim.Region.Framework.Scenes
1068 /// <param name="action"></param> 1129 /// <param name="action"></param>
1069 protected internal void ForEachSOG(Action<SceneObjectGroup> action) 1130 protected internal void ForEachSOG(Action<SceneObjectGroup> action)
1070 { 1131 {
1071 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); 1132 EntityBase[] objlist = Entities.GetAllByType<SceneObjectGroup>();
1072 foreach (SceneObjectGroup obj in objlist) 1133 foreach (EntityBase ent in objlist)
1073 { 1134 {
1135 SceneObjectGroup obj = (SceneObjectGroup)ent;
1136
1074 try 1137 try
1075 { 1138 {
1076 action(obj); 1139 action(obj);
@@ -1531,10 +1594,13 @@ namespace OpenSim.Region.Framework.Scenes
1531 /// <param name="childPrims"></param> 1594 /// <param name="childPrims"></param>
1532 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1595 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1533 { 1596 {
1597 SceneObjectGroup parentGroup = root.ParentGroup;
1598 if (parentGroup == null) return;
1534 Monitor.Enter(m_updateLock); 1599 Monitor.Enter(m_updateLock);
1600
1535 try 1601 try
1536 { 1602 {
1537 SceneObjectGroup parentGroup = root.ParentGroup; 1603 parentGroup.areUpdatesSuspended = true;
1538 1604
1539 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1605 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1540 if (parentGroup != null) 1606 if (parentGroup != null)
@@ -1546,11 +1612,6 @@ namespace OpenSim.Region.Framework.Scenes
1546 1612
1547 if (child != null) 1613 if (child != null)
1548 { 1614 {
1549 // Make sure no child prim is set for sale
1550 // So that, on delink, no prims are unwittingly
1551 // left for sale and sold off
1552 child.RootPart.ObjectSaleType = 0;
1553 child.RootPart.SalePrice = 10;
1554 childGroups.Add(child); 1615 childGroups.Add(child);
1555 } 1616 }
1556 } 1617 }
@@ -1573,12 +1634,12 @@ namespace OpenSim.Region.Framework.Scenes
1573 // occur on link to invoke this elsewhere (such as object selection) 1634 // occur on link to invoke this elsewhere (such as object selection)
1574 parentGroup.RootPart.CreateSelected = true; 1635 parentGroup.RootPart.CreateSelected = true;
1575 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1636 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1576 parentGroup.HasGroupChanged = true;
1577 parentGroup.ScheduleGroupForFullUpdate();
1578
1579 } 1637 }
1580 finally 1638 finally
1581 { 1639 {
1640 parentGroup.areUpdatesSuspended = false;
1641 parentGroup.HasGroupChanged = true;
1642 parentGroup.ScheduleGroupForFullUpdate();
1582 Monitor.Exit(m_updateLock); 1643 Monitor.Exit(m_updateLock);
1583 } 1644 }
1584 } 1645 }
@@ -1610,21 +1671,24 @@ namespace OpenSim.Region.Framework.Scenes
1610 1671
1611 SceneObjectGroup group = part.ParentGroup; 1672 SceneObjectGroup group = part.ParentGroup;
1612 if (!affectedGroups.Contains(group)) 1673 if (!affectedGroups.Contains(group))
1674 {
1675 group.areUpdatesSuspended = true;
1613 affectedGroups.Add(group); 1676 affectedGroups.Add(group);
1677 }
1614 } 1678 }
1615 } 1679 }
1616 } 1680 }
1617 1681
1618 foreach (SceneObjectPart child in childParts) 1682 if (childParts.Count > 0)
1619 { 1683 {
1620 // Unlink all child parts from their groups 1684 foreach (SceneObjectPart child in childParts)
1621 // 1685 {
1622 child.ParentGroup.DelinkFromGroup(child, true); 1686 // Unlink all child parts from their groups
1623 1687 //
1624 // These are not in affected groups and will not be 1688 child.ParentGroup.DelinkFromGroup(child, true);
1625 // handled further. Do the honors here. 1689 child.ParentGroup.HasGroupChanged = true;
1626 child.ParentGroup.HasGroupChanged = true; 1690 child.ParentGroup.ScheduleGroupForFullUpdate();
1627 child.ParentGroup.ScheduleGroupForFullUpdate(); 1691 }
1628 } 1692 }
1629 1693
1630 foreach (SceneObjectPart root in rootParts) 1694 foreach (SceneObjectPart root in rootParts)
@@ -1634,56 +1698,68 @@ namespace OpenSim.Region.Framework.Scenes
1634 // However, editing linked parts and unlinking may be different 1698 // However, editing linked parts and unlinking may be different
1635 // 1699 //
1636 SceneObjectGroup group = root.ParentGroup; 1700 SceneObjectGroup group = root.ParentGroup;
1701 group.areUpdatesSuspended = true;
1637 1702
1638 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1703 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1639 int numChildren = newSet.Count; 1704 int numChildren = newSet.Count;
1640 1705
1706 if (numChildren == 1)
1707 break;
1708
1641 // If there are prims left in a link set, but the root is 1709 // If there are prims left in a link set, but the root is
1642 // slated for unlink, we need to do this 1710 // slated for unlink, we need to do this
1711 // Unlink the remaining set
1643 // 1712 //
1644 if (numChildren != 1) 1713 bool sendEventsToRemainder = true;
1645 { 1714 if (numChildren > 1)
1646 // Unlink the remaining set 1715 sendEventsToRemainder = false;
1647 //
1648 bool sendEventsToRemainder = true;
1649 if (numChildren > 1)
1650 sendEventsToRemainder = false;
1651 1716
1652 foreach (SceneObjectPart p in newSet) 1717 foreach (SceneObjectPart p in newSet)
1718 {
1719 if (p != group.RootPart)
1653 { 1720 {
1654 if (p != group.RootPart) 1721 group.DelinkFromGroup(p, sendEventsToRemainder);
1655 group.DelinkFromGroup(p, sendEventsToRemainder); 1722 if (numChildren > 2)
1723 {
1724 p.ParentGroup.areUpdatesSuspended = true;
1725 }
1726 else
1727 {
1728 p.ParentGroup.HasGroupChanged = true;
1729 p.ParentGroup.ScheduleGroupForFullUpdate();
1730 }
1656 } 1731 }
1732 }
1733
1734 // If there is more than one prim remaining, we
1735 // need to re-link
1736 //
1737 if (numChildren > 2)
1738 {
1739 // Remove old root
1740 //
1741 if (newSet.Contains(root))
1742 newSet.Remove(root);
1657 1743
1658 // If there is more than one prim remaining, we 1744 // Preserve link ordering
1659 // need to re-link
1660 // 1745 //
1661 if (numChildren > 2) 1746 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1662 { 1747 {
1663 // Remove old root 1748 return a.LinkNum.CompareTo(b.LinkNum);
1664 // 1749 });
1665 if (newSet.Contains(root))
1666 newSet.Remove(root);
1667
1668 // Preserve link ordering
1669 //
1670 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1671 {
1672 return a.LinkNum.CompareTo(b.LinkNum);
1673 });
1674 1750
1675 // Determine new root 1751 // Determine new root
1676 // 1752 //
1677 SceneObjectPart newRoot = newSet[0]; 1753 SceneObjectPart newRoot = newSet[0];
1678 newSet.RemoveAt(0); 1754 newSet.RemoveAt(0);
1679 1755
1680 foreach (SceneObjectPart newChild in newSet) 1756 foreach (SceneObjectPart newChild in newSet)
1681 newChild.UpdateFlag = 0; 1757 newChild.UpdateFlag = 0;
1682 1758
1683 LinkObjects(newRoot, newSet); 1759 newRoot.ParentGroup.areUpdatesSuspended = true;
1684 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1760 LinkObjects(newRoot, newSet);
1685 affectedGroups.Add(newRoot.ParentGroup); 1761 if (!affectedGroups.Contains(newRoot.ParentGroup))
1686 } 1762 affectedGroups.Add(newRoot.ParentGroup);
1687 } 1763 }
1688 } 1764 }
1689 1765
@@ -1691,8 +1767,14 @@ namespace OpenSim.Region.Framework.Scenes
1691 // 1767 //
1692 foreach (SceneObjectGroup g in affectedGroups) 1768 foreach (SceneObjectGroup g in affectedGroups)
1693 { 1769 {
1770 // Child prims that have been unlinked and deleted will
1771 // return unless the root is deleted. This will remove them
1772 // from the database. They will be rewritten immediately,
1773 // minus the rows for the unlinked child prims.
1774 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1694 g.TriggerScriptChangedEvent(Changed.LINK); 1775 g.TriggerScriptChangedEvent(Changed.LINK);
1695 g.HasGroupChanged = true; // Persist 1776 g.HasGroupChanged = true; // Persist
1777 g.areUpdatesSuspended = false;
1696 g.ScheduleGroupForFullUpdate(); 1778 g.ScheduleGroupForFullUpdate();
1697 } 1779 }
1698 } 1780 }
@@ -1807,9 +1889,6 @@ namespace OpenSim.Region.Framework.Scenes
1807 child.ApplyNextOwnerPermissions(); 1889 child.ApplyNextOwnerPermissions();
1808 } 1890 }
1809 } 1891 }
1810
1811 copy.RootPart.ObjectSaleType = 0;
1812 copy.RootPart.SalePrice = 10;
1813 } 1892 }
1814 1893
1815 Entities.Add(copy); 1894 Entities.Add(copy);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index a86223c..6cc7231 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -69,10 +69,6 @@ namespace OpenSim.Region.Framework.Scenes
69 /// <summary> 69 /// <summary>
70 /// Stop the scripts contained in all the prims in this group 70 /// Stop the scripts contained in all the prims in this group
71 /// </summary> 71 /// </summary>
72 /// <param name="sceneObjectBeingDeleted">
73 /// Should be true if these scripts are being removed because the scene
74 /// object is being deleted. This will prevent spurious updates to the client.
75 /// </param>
76 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 72 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
77 { 73 {
78 SceneObjectPart[] parts = m_parts.GetArray(); 74 SceneObjectPart[] parts = m_parts.GetArray();
@@ -419,6 +415,9 @@ namespace OpenSim.Region.Framework.Scenes
419 415
420 public void ResumeScripts() 416 public void ResumeScripts()
421 { 417 {
418 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
419 return;
420
422 SceneObjectPart[] parts = m_parts.GetArray(); 421 SceneObjectPart[] parts = m_parts.GetArray();
423 for (int i = 0; i < parts.Length; i++) 422 for (int i = 0; i < parts.Length; i++)
424 parts[i].Inventory.ResumeScripts(); 423 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index c2810b2..ee08072 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Drawing; 30using System.Drawing;
31using System.IO; 31using System.IO;
32using System.Diagnostics;
32using System.Linq; 33using System.Linq;
33using System.Threading; 34using System.Threading;
34using System.Xml; 35using System.Xml;
@@ -105,8 +106,29 @@ namespace OpenSim.Region.Framework.Scenes
105 /// since the group's last persistent backup 106 /// since the group's last persistent backup
106 /// </summary> 107 /// </summary>
107 private bool m_hasGroupChanged = false; 108 private bool m_hasGroupChanged = false;
108 private long timeFirstChanged; 109 private long timeFirstChanged = 0;
109 private long timeLastChanged; 110 private long timeLastChanged = 0;
111 private long m_maxPersistTime = 0;
112 private long m_minPersistTime = 0;
113 private Random m_rand;
114 private bool m_suspendUpdates;
115 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
116
117 public bool areUpdatesSuspended
118 {
119 get
120 {
121 return m_suspendUpdates;
122 }
123 set
124 {
125 m_suspendUpdates = value;
126 if (!value)
127 {
128 QueueForUpdateCheck();
129 }
130 }
131 }
110 132
111 public bool HasGroupChanged 133 public bool HasGroupChanged
112 { 134 {
@@ -114,9 +136,39 @@ namespace OpenSim.Region.Framework.Scenes
114 { 136 {
115 if (value) 137 if (value)
116 { 138 {
139 if (m_isBackedUp)
140 {
141 m_scene.SceneGraph.FireChangeBackup(this);
142 }
117 timeLastChanged = DateTime.Now.Ticks; 143 timeLastChanged = DateTime.Now.Ticks;
118 if (!m_hasGroupChanged) 144 if (!m_hasGroupChanged)
119 timeFirstChanged = DateTime.Now.Ticks; 145 timeFirstChanged = DateTime.Now.Ticks;
146 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
147 {
148 if (m_rand == null)
149 {
150 byte[] val = new byte[16];
151 m_rootPart.UUID.ToBytes(val, 0);
152 m_rand = new Random(BitConverter.ToInt32(val, 0));
153 }
154
155 if (m_scene.GetRootAgentCount() == 0)
156 {
157 //If the region is empty, this change has been made by an automated process
158 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
159
160 float factor = 1.5f + (float)(m_rand.NextDouble());
161 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
162 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
163 }
164 else
165 {
166 //If the region is not empty, we want to obey the minimum and maximum persist times
167 //but add a random factor so we stagger the object persistance a little
168 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
169 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
170 }
171 }
120 } 172 }
121 m_hasGroupChanged = value; 173 m_hasGroupChanged = value;
122 } 174 }
@@ -132,8 +184,19 @@ namespace OpenSim.Region.Framework.Scenes
132 return false; 184 return false;
133 if (m_scene.ShuttingDown) 185 if (m_scene.ShuttingDown)
134 return true; 186 return true;
187
188 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
189 {
190 m_maxPersistTime = m_scene.m_persistAfter;
191 m_minPersistTime = m_scene.m_dontPersistBefore;
192 }
193
135 long currentTime = DateTime.Now.Ticks; 194 long currentTime = DateTime.Now.Ticks;
136 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 195
196 if (timeLastChanged == 0) timeLastChanged = currentTime;
197 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
198
199 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
137 return true; 200 return true;
138 return false; 201 return false;
139 } 202 }
@@ -176,10 +239,10 @@ namespace OpenSim.Region.Framework.Scenes
176 239
177 private bool m_scriptListens_atTarget; 240 private bool m_scriptListens_atTarget;
178 private bool m_scriptListens_notAtTarget; 241 private bool m_scriptListens_notAtTarget;
179
180 private bool m_scriptListens_atRotTarget; 242 private bool m_scriptListens_atRotTarget;
181 private bool m_scriptListens_notAtRotTarget; 243 private bool m_scriptListens_notAtRotTarget;
182 244
245 public bool m_dupeInProgress = false;
183 internal Dictionary<UUID, string> m_savedScriptState; 246 internal Dictionary<UUID, string> m_savedScriptState;
184 247
185 #region Properties 248 #region Properties
@@ -219,7 +282,13 @@ namespace OpenSim.Region.Framework.Scenes
219 public virtual Quaternion Rotation 282 public virtual Quaternion Rotation
220 { 283 {
221 get { return m_rotation; } 284 get { return m_rotation; }
222 set { m_rotation = value; } 285 set {
286 foreach(SceneObjectPart p in m_parts.GetArray())
287 {
288 p.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
289 }
290 m_rotation = value;
291 }
223 } 292 }
224 293
225 public Quaternion GroupRotation 294 public Quaternion GroupRotation
@@ -293,7 +362,11 @@ namespace OpenSim.Region.Framework.Scenes
293 { 362 {
294 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 363 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
295 } 364 }
296 365
366 foreach (SceneObjectPart part in m_parts.GetArray())
367 {
368 part.IgnoreUndoUpdate = true;
369 }
297 if (RootPart.GetStatusSandbox()) 370 if (RootPart.GetStatusSandbox())
298 { 371 {
299 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 372 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -304,10 +377,31 @@ namespace OpenSim.Region.Framework.Scenes
304 return; 377 return;
305 } 378 }
306 } 379 }
307
308 SceneObjectPart[] parts = m_parts.GetArray(); 380 SceneObjectPart[] parts = m_parts.GetArray();
309 for (int i = 0; i < parts.Length; i++) 381 foreach (SceneObjectPart part in parts)
310 parts[i].GroupPosition = val; 382 {
383 part.IgnoreUndoUpdate = false;
384 part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
385 part.GroupPosition = val;
386 if (!m_dupeInProgress)
387 {
388 part.TriggerScriptChangedEvent(Changed.POSITION);
389 }
390 }
391 if (!m_dupeInProgress)
392 {
393 foreach (ScenePresence av in m_linkedAvatars)
394 {
395 SceneObjectPart p;
396 if (m_parts.TryGetValue(av.LinkedPrim, out p))
397 {
398 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
399 av.AbsolutePosition += offset;
400 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
401 av.SendFullUpdateToAllClients();
402 }
403 }
404 }
311 405
312 //if (m_rootPart.PhysActor != null) 406 //if (m_rootPart.PhysActor != null)
313 //{ 407 //{
@@ -458,6 +552,7 @@ namespace OpenSim.Region.Framework.Scenes
458 /// </summary> 552 /// </summary>
459 public SceneObjectGroup() 553 public SceneObjectGroup()
460 { 554 {
555
461 } 556 }
462 557
463 /// <summary> 558 /// <summary>
@@ -474,7 +569,7 @@ namespace OpenSim.Region.Framework.Scenes
474 /// Constructor. This object is added to the scene later via AttachToScene() 569 /// Constructor. This object is added to the scene later via AttachToScene()
475 /// </summary> 570 /// </summary>
476 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 571 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
477 { 572 {
478 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 573 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
479 } 574 }
480 575
@@ -522,6 +617,9 @@ namespace OpenSim.Region.Framework.Scenes
522 /// </summary> 617 /// </summary>
523 public virtual void AttachToBackup() 618 public virtual void AttachToBackup()
524 { 619 {
620 if (IsAttachment) return;
621 m_scene.SceneGraph.FireAttachToBackup(this);
622
525 if (InSceneBackup) 623 if (InSceneBackup)
526 { 624 {
527 //m_log.DebugFormat( 625 //m_log.DebugFormat(
@@ -637,9 +735,9 @@ namespace OpenSim.Region.Framework.Scenes
637 result.normal = inter.normal; 735 result.normal = inter.normal;
638 result.distance = inter.distance; 736 result.distance = inter.distance;
639 } 737 }
738
640 } 739 }
641 } 740 }
642
643 return result; 741 return result;
644 } 742 }
645 743
@@ -659,17 +757,19 @@ namespace OpenSim.Region.Framework.Scenes
659 minZ = 8192f; 757 minZ = 8192f;
660 758
661 SceneObjectPart[] parts = m_parts.GetArray(); 759 SceneObjectPart[] parts = m_parts.GetArray();
662 for (int i = 0; i < parts.Length; i++) 760 foreach (SceneObjectPart part in parts)
663 { 761 {
664 SceneObjectPart part = parts[i];
665
666 Vector3 worldPos = part.GetWorldPosition(); 762 Vector3 worldPos = part.GetWorldPosition();
667 Vector3 offset = worldPos - AbsolutePosition; 763 Vector3 offset = worldPos - AbsolutePosition;
668 Quaternion worldRot; 764 Quaternion worldRot;
669 if (part.ParentID == 0) 765 if (part.ParentID == 0)
766 {
670 worldRot = part.RotationOffset; 767 worldRot = part.RotationOffset;
768 }
671 else 769 else
770 {
672 worldRot = part.GetWorldRotation(); 771 worldRot = part.GetWorldRotation();
772 }
673 773
674 Vector3 frontTopLeft; 774 Vector3 frontTopLeft;
675 Vector3 frontTopRight; 775 Vector3 frontTopRight;
@@ -681,6 +781,8 @@ namespace OpenSim.Region.Framework.Scenes
681 Vector3 backBottomLeft; 781 Vector3 backBottomLeft;
682 Vector3 backBottomRight; 782 Vector3 backBottomRight;
683 783
784 // Vector3[] corners = new Vector3[8];
785
684 Vector3 orig = Vector3.Zero; 786 Vector3 orig = Vector3.Zero;
685 787
686 frontTopLeft.X = orig.X - (part.Scale.X / 2); 788 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -715,6 +817,38 @@ namespace OpenSim.Region.Framework.Scenes
715 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 817 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
716 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 818 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
717 819
820
821
822 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
823 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
824 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
825 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
826 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
827 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
828 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
829 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
830
831 //for (int i = 0; i < 8; i++)
832 //{
833 // corners[i] = corners[i] * worldRot;
834 // corners[i] += offset;
835
836 // if (corners[i].X > maxX)
837 // maxX = corners[i].X;
838 // if (corners[i].X < minX)
839 // minX = corners[i].X;
840
841 // if (corners[i].Y > maxY)
842 // maxY = corners[i].Y;
843 // if (corners[i].Y < minY)
844 // minY = corners[i].Y;
845
846 // if (corners[i].Z > maxZ)
847 // maxZ = corners[i].Y;
848 // if (corners[i].Z < minZ)
849 // minZ = corners[i].Z;
850 //}
851
718 frontTopLeft = frontTopLeft * worldRot; 852 frontTopLeft = frontTopLeft * worldRot;
719 frontTopRight = frontTopRight * worldRot; 853 frontTopRight = frontTopRight * worldRot;
720 frontBottomLeft = frontBottomLeft * worldRot; 854 frontBottomLeft = frontBottomLeft * worldRot;
@@ -736,6 +870,15 @@ namespace OpenSim.Region.Framework.Scenes
736 backTopLeft += offset; 870 backTopLeft += offset;
737 backTopRight += offset; 871 backTopRight += offset;
738 872
873 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
874 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
875 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
876 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
877 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
878 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
879 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
880 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
881
739 if (frontTopRight.X > maxX) 882 if (frontTopRight.X > maxX)
740 maxX = frontTopRight.X; 883 maxX = frontTopRight.X;
741 if (frontTopLeft.X > maxX) 884 if (frontTopLeft.X > maxX)
@@ -881,15 +1024,20 @@ namespace OpenSim.Region.Framework.Scenes
881 1024
882 public void SaveScriptedState(XmlTextWriter writer) 1025 public void SaveScriptedState(XmlTextWriter writer)
883 { 1026 {
1027 SaveScriptedState(writer, false);
1028 }
1029
1030 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1031 {
884 XmlDocument doc = new XmlDocument(); 1032 XmlDocument doc = new XmlDocument();
885 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1033 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
886 1034
887 SceneObjectPart[] parts = m_parts.GetArray(); 1035 SceneObjectPart[] parts = m_parts.GetArray();
888 for (int i = 0; i < parts.Length; i++) 1036 for (int i = 0; i < parts.Length; i++)
889 { 1037 {
890 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1038 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
891 foreach (KeyValuePair<UUID, string> kvp in pstates) 1039 foreach (KeyValuePair<UUID, string> kvp in pstates)
892 states.Add(kvp.Key, kvp.Value); 1040 states[kvp.Key] = kvp.Value;
893 } 1041 }
894 1042
895 if (states.Count > 0) 1043 if (states.Count > 0)
@@ -908,6 +1056,118 @@ namespace OpenSim.Region.Framework.Scenes
908 } 1056 }
909 } 1057 }
910 1058
1059 /// <summary>
1060 /// Add the avatar to this linkset (avatar is sat).
1061 /// </summary>
1062 /// <param name="agentID"></param>
1063 public void AddAvatar(UUID agentID)
1064 {
1065 ScenePresence presence;
1066 if (m_scene.TryGetScenePresence(agentID, out presence))
1067 {
1068 if (!m_linkedAvatars.Contains(presence))
1069 {
1070 m_linkedAvatars.Add(presence);
1071 }
1072 }
1073 }
1074
1075 /// <summary>
1076 /// Delete the avatar from this linkset (avatar is unsat).
1077 /// </summary>
1078 /// <param name="agentID"></param>
1079 public void DeleteAvatar(UUID agentID)
1080 {
1081 ScenePresence presence;
1082 if (m_scene.TryGetScenePresence(agentID, out presence))
1083 {
1084 if (m_linkedAvatars.Contains(presence))
1085 {
1086 m_linkedAvatars.Remove(presence);
1087 }
1088 }
1089 }
1090
1091 /// <summary>
1092 /// Returns the list of linked presences (avatars sat on this group)
1093 /// </summary>
1094 /// <param name="agentID"></param>
1095 public List<ScenePresence> GetLinkedAvatars()
1096 {
1097 return m_linkedAvatars;
1098 }
1099
1100 /// <summary>
1101 /// Attach this scene object to the given avatar.
1102 /// </summary>
1103 /// <param name="agentID"></param>
1104 /// <param name="attachmentpoint"></param>
1105 /// <param name="AttachOffset"></param>
1106 public void AttachToAgent(UUID agentID, uint attachmentpoint, Vector3 AttachOffset, bool silent)
1107 {
1108 ScenePresence avatar = m_scene.GetScenePresence(agentID);
1109 if (avatar != null)
1110 {
1111 // don't attach attachments to child agents
1112 if (avatar.IsChildAgent) return;
1113
1114// m_log.DebugFormat("[SOG]: Adding attachment {0} to avatar {1}", Name, avatar.Name);
1115
1116 DetachFromBackup();
1117
1118 // Remove from database and parcel prim count
1119 m_scene.DeleteFromStorage(UUID);
1120 m_scene.EventManager.TriggerParcelPrimCountTainted();
1121
1122 m_rootPart.AttachedAvatar = agentID;
1123
1124 //Anakin Lohner bug #3839
1125 lock (m_parts)
1126 {
1127 foreach (SceneObjectPart p in m_parts.GetArray())
1128 {
1129 p.AttachedAvatar = agentID;
1130 }
1131 }
1132
1133 if (m_rootPart.PhysActor != null)
1134 {
1135 m_scene.PhysicsScene.RemovePrim(m_rootPart.PhysActor);
1136 m_rootPart.PhysActor = null;
1137 }
1138
1139 AbsolutePosition = AttachOffset;
1140 m_rootPart.AttachedPos = AttachOffset;
1141 m_rootPart.IsAttachment = true;
1142
1143 m_rootPart.SetParentLocalId(avatar.LocalId);
1144 SetAttachmentPoint(Convert.ToByte(attachmentpoint));
1145
1146 avatar.AddAttachment(this);
1147
1148 if (!silent)
1149 {
1150 // Killing it here will cause the client to deselect it
1151 // It then reappears on the avatar, deselected
1152 // through the full update below
1153 //
1154 if (IsSelected)
1155 {
1156 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1157 }
1158
1159 IsSelected = false; // fudge....
1160 ScheduleGroupForFullUpdate();
1161 }
1162 }
1163 else
1164 {
1165 m_log.WarnFormat(
1166 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1167 UUID, agentID, Scene.RegionInfo.RegionName);
1168 }
1169 }
1170
911 public byte GetAttachmentPoint() 1171 public byte GetAttachmentPoint()
912 { 1172 {
913 return m_rootPart.Shape.State; 1173 return m_rootPart.Shape.State;
@@ -1034,7 +1294,10 @@ namespace OpenSim.Region.Framework.Scenes
1034 public void AddPart(SceneObjectPart part) 1294 public void AddPart(SceneObjectPart part)
1035 { 1295 {
1036 part.SetParent(this); 1296 part.SetParent(this);
1037 part.LinkNum = m_parts.Add(part.UUID, part); 1297 m_parts.Add(part.UUID, part);
1298
1299 part.LinkNum = m_parts.Count;
1300
1038 if (part.LinkNum == 2 && RootPart != null) 1301 if (part.LinkNum == 2 && RootPart != null)
1039 RootPart.LinkNum = 1; 1302 RootPart.LinkNum = 1;
1040 } 1303 }
@@ -1118,7 +1381,7 @@ namespace OpenSim.Region.Framework.Scenes
1118 1381
1119 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1382 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1120 { 1383 {
1121 part.StoreUndoState(); 1384 part.StoreUndoState(UndoType.STATE_PRIM_ALL);
1122 part.OnGrab(offsetPos, remoteClient); 1385 part.OnGrab(offsetPos, remoteClient);
1123 } 1386 }
1124 1387
@@ -1138,6 +1401,11 @@ namespace OpenSim.Region.Framework.Scenes
1138 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1401 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1139 public void DeleteGroupFromScene(bool silent) 1402 public void DeleteGroupFromScene(bool silent)
1140 { 1403 {
1404 // We need to keep track of this state in case this group is still queued for backup.
1405 m_isDeleted = true;
1406
1407 DetachFromBackup();
1408
1141 SceneObjectPart[] parts = m_parts.GetArray(); 1409 SceneObjectPart[] parts = m_parts.GetArray();
1142 for (int i = 0; i < parts.Length; i++) 1410 for (int i = 0; i < parts.Length; i++)
1143 { 1411 {
@@ -1149,13 +1417,11 @@ namespace OpenSim.Region.Framework.Scenes
1149 avatar.StandUp(); 1417 avatar.StandUp();
1150 1418
1151 if (!silent) 1419 if (!silent)
1152 {
1153 part.UpdateFlag = 0; 1420 part.UpdateFlag = 0;
1154 if (part == m_rootPart)
1155 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1156 }
1157 }); 1421 });
1158 } 1422 }
1423
1424
1159 } 1425 }
1160 1426
1161 public void AddScriptLPS(int count) 1427 public void AddScriptLPS(int count)
@@ -1252,7 +1518,12 @@ namespace OpenSim.Region.Framework.Scenes
1252 1518
1253 public void SetOwnerId(UUID userId) 1519 public void SetOwnerId(UUID userId)
1254 { 1520 {
1255 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1521 ForEachPart(delegate(SceneObjectPart part)
1522 {
1523
1524 part.OwnerID = userId;
1525
1526 });
1256 } 1527 }
1257 1528
1258 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1529 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1284,11 +1555,17 @@ namespace OpenSim.Region.Framework.Scenes
1284 return; 1555 return;
1285 } 1556 }
1286 1557
1558 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1559 return;
1560
1287 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1561 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1288 // any exception propogate upwards. 1562 // any exception propogate upwards.
1289 try 1563 try
1290 { 1564 {
1291 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1565 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1566 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1567 m_scene.LoadingPrims) // Land may not be valid yet
1568
1292 { 1569 {
1293 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1570 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1294 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1571 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1313,6 +1590,7 @@ namespace OpenSim.Region.Framework.Scenes
1313 } 1590 }
1314 } 1591 }
1315 } 1592 }
1593
1316 } 1594 }
1317 1595
1318 if (HasGroupChanged) 1596 if (HasGroupChanged)
@@ -1320,6 +1598,20 @@ namespace OpenSim.Region.Framework.Scenes
1320 // don't backup while it's selected or you're asking for changes mid stream. 1598 // don't backup while it's selected or you're asking for changes mid stream.
1321 if (isTimeToPersist() || forcedBackup) 1599 if (isTimeToPersist() || forcedBackup)
1322 { 1600 {
1601 if (m_rootPart.PhysActor != null &&
1602 (!m_rootPart.PhysActor.IsPhysical))
1603 {
1604 // Possible ghost prim
1605 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1606 {
1607 foreach (SceneObjectPart part in m_parts.GetArray())
1608 {
1609 // Re-set physics actor positions and
1610 // orientations
1611 part.GroupPosition = m_rootPart.GroupPosition;
1612 }
1613 }
1614 }
1323// m_log.DebugFormat( 1615// m_log.DebugFormat(
1324// "[SCENE]: Storing {0}, {1} in {2}", 1616// "[SCENE]: Storing {0}, {1} in {2}",
1325// Name, UUID, m_scene.RegionInfo.RegionName); 1617// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1382,81 +1674,89 @@ namespace OpenSim.Region.Framework.Scenes
1382 /// <returns></returns> 1674 /// <returns></returns>
1383 public SceneObjectGroup Copy(bool userExposed) 1675 public SceneObjectGroup Copy(bool userExposed)
1384 { 1676 {
1385 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1677 SceneObjectGroup dupe;
1386 dupe.m_isBackedUp = false; 1678 try
1387 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 1679 {
1388 1680 m_dupeInProgress = true;
1389 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 1681 dupe = (SceneObjectGroup)MemberwiseClone();
1390 // attachments do not bordercross while they're being duplicated. This is hacktastic! 1682 dupe.m_isBackedUp = false;
1391 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! 1683 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1392 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1393 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1394 // then restore it's attachment state
1395
1396 // This is only necessary when userExposed is false!
1397 1684
1398 bool previousAttachmentStatus = dupe.RootPart.IsAttachment; 1685 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1399 1686 // attachments do not bordercross while they're being duplicated. This is hacktastic!
1400 if (!userExposed) 1687 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
1401 dupe.RootPart.IsAttachment = true; 1688 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1689 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1690 // then restore it's attachment state
1402 1691
1403 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 1692 // This is only necessary when userExposed is false!
1404 1693
1405 if (!userExposed) 1694 bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
1406 {
1407 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1408 }
1409 1695
1410 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 1696 if (!userExposed)
1411 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 1697 dupe.RootPart.IsAttachment = true;
1412 1698
1413 if (userExposed) 1699 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
1414 dupe.m_rootPart.TrimPermissions();
1415 1700
1416 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1701 if (!userExposed)
1417
1418 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1419 { 1702 {
1420 return p1.LinkNum.CompareTo(p2.LinkNum); 1703 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1421 } 1704 }
1422 );
1423 1705
1424 foreach (SceneObjectPart part in partList) 1706 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1425 { 1707 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1426 if (part.UUID != m_rootPart.UUID) 1708
1709 if (userExposed)
1710 dupe.m_rootPart.TrimPermissions();
1711
1712 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1713
1714 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1715 {
1716 return p1.LinkNum.CompareTo(p2.LinkNum);
1717 }
1718 );
1719
1720 foreach (SceneObjectPart part in partList)
1427 { 1721 {
1428 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 1722 if (part.UUID != m_rootPart.UUID)
1429 newPart.LinkNum = part.LinkNum; 1723 {
1430 } 1724 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1431 1725
1432 // Need to duplicate the physics actor as well 1726 newPart.LinkNum = part.LinkNum;
1433 if (part.PhysActor != null && userExposed) 1727 }
1728
1729 // Need to duplicate the physics actor as well
1730 if (part.PhysActor != null && userExposed)
1731 {
1732 PrimitiveBaseShape pbs = part.Shape;
1733
1734 part.PhysActor
1735 = m_scene.PhysicsScene.AddPrimShape(
1736 string.Format("{0}/{1}", part.Name, part.UUID),
1737 pbs,
1738 part.AbsolutePosition,
1739 part.Scale,
1740 part.RotationOffset,
1741 part.PhysActor.IsPhysical);
1742
1743 part.PhysActor.LocalID = part.LocalId;
1744 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1745 }
1746 }
1747 if (userExposed)
1434 { 1748 {
1435 PrimitiveBaseShape pbs = part.Shape; 1749 dupe.UpdateParentIDs();
1436 1750 dupe.HasGroupChanged = true;
1437 part.PhysActor 1751 dupe.AttachToBackup();
1438 = m_scene.PhysicsScene.AddPrimShape( 1752
1439 string.Format("{0}/{1}", part.Name, part.UUID), 1753 ScheduleGroupForFullUpdate();
1440 pbs,
1441 part.AbsolutePosition,
1442 part.Scale,
1443 part.RotationOffset,
1444 part.PhysActor.IsPhysical);
1445
1446 part.PhysActor.LocalID = part.LocalId;
1447 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1448 } 1754 }
1449 } 1755 }
1450 1756 finally
1451 if (userExposed)
1452 { 1757 {
1453 dupe.UpdateParentIDs(); 1758 m_dupeInProgress = false;
1454 dupe.HasGroupChanged = true;
1455 dupe.AttachToBackup();
1456
1457 ScheduleGroupForFullUpdate();
1458 } 1759 }
1459
1460 return dupe; 1760 return dupe;
1461 } 1761 }
1462 1762
@@ -1647,13 +1947,40 @@ namespace OpenSim.Region.Framework.Scenes
1647 } 1947 }
1648 } 1948 }
1649 1949
1950 public void rotLookAt(Quaternion target, float strength, float damping)
1951 {
1952 SceneObjectPart rootpart = m_rootPart;
1953 if (rootpart != null)
1954 {
1955 if (IsAttachment)
1956 {
1957 /*
1958 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1959 if (avatar != null)
1960 {
1961 Rotate the Av?
1962 } */
1963 }
1964 else
1965 {
1966 if (rootpart.PhysActor != null)
1967 { // APID must be implemented in your physics system for this to function.
1968 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1969 rootpart.PhysActor.APIDStrength = strength;
1970 rootpart.PhysActor.APIDDamping = damping;
1971 rootpart.PhysActor.APIDActive = true;
1972 }
1973 }
1974 }
1975 }
1976
1650 public void stopLookAt() 1977 public void stopLookAt()
1651 { 1978 {
1652 SceneObjectPart rootpart = m_rootPart; 1979 SceneObjectPart rootpart = m_rootPart;
1653 if (rootpart != null) 1980 if (rootpart != null)
1654 { 1981 {
1655 if (rootpart.PhysActor != null) 1982 if (rootpart.PhysActor != null)
1656 { 1983 { // APID must be implemented in your physics system for this to function.
1657 rootpart.PhysActor.APIDActive = false; 1984 rootpart.PhysActor.APIDActive = false;
1658 } 1985 }
1659 } 1986 }
@@ -1719,6 +2046,8 @@ namespace OpenSim.Region.Framework.Scenes
1719 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2046 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1720 { 2047 {
1721 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2048 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2049 newPart.SetParent(this);
2050
1722 AddPart(newPart); 2051 AddPart(newPart);
1723 2052
1724 SetPartAsNonRoot(newPart); 2053 SetPartAsNonRoot(newPart);
@@ -1865,11 +2194,11 @@ namespace OpenSim.Region.Framework.Scenes
1865 /// Immediately send a full update for this scene object. 2194 /// Immediately send a full update for this scene object.
1866 /// </summary> 2195 /// </summary>
1867 public void SendGroupFullUpdate() 2196 public void SendGroupFullUpdate()
1868 { 2197 {
1869 if (IsDeleted) 2198 if (IsDeleted)
1870 return; 2199 return;
1871 2200
1872// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2201// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1873 2202
1874 RootPart.SendFullUpdateToAllClients(); 2203 RootPart.SendFullUpdateToAllClients();
1875 2204
@@ -2058,12 +2387,15 @@ namespace OpenSim.Region.Framework.Scenes
2058 part.LinkNum += objectGroup.PrimCount; 2387 part.LinkNum += objectGroup.PrimCount;
2059 } 2388 }
2060 } 2389 }
2390 }
2061 2391
2062 linkPart.LinkNum = 2; 2392 linkPart.LinkNum = 2;
2063 2393
2064 linkPart.SetParent(this); 2394 linkPart.SetParent(this);
2065 linkPart.CreateSelected = true; 2395 linkPart.CreateSelected = true;
2066 2396
2397 lock (m_parts.SyncRoot)
2398 {
2067 //if (linkPart.PhysActor != null) 2399 //if (linkPart.PhysActor != null)
2068 //{ 2400 //{
2069 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2401 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
@@ -2220,6 +2552,8 @@ namespace OpenSim.Region.Framework.Scenes
2220 /// <param name="objectGroup"></param> 2552 /// <param name="objectGroup"></param>
2221 public virtual void DetachFromBackup() 2553 public virtual void DetachFromBackup()
2222 { 2554 {
2555 m_scene.SceneGraph.FireDetachFromBackup(this);
2556
2223 if (m_isBackedUp) 2557 if (m_isBackedUp)
2224 m_scene.EventManager.OnBackup -= ProcessBackup; 2558 m_scene.EventManager.OnBackup -= ProcessBackup;
2225 2559
@@ -2524,6 +2858,17 @@ namespace OpenSim.Region.Framework.Scenes
2524 } 2858 }
2525 } 2859 }
2526 2860
2861
2862
2863 /// <summary>
2864 /// Gets the number of parts
2865 /// </summary>
2866 /// <returns></returns>
2867 public int GetPartCount()
2868 {
2869 return Parts.Count();
2870 }
2871
2527 /// <summary> 2872 /// <summary>
2528 /// Update the texture entry for this part 2873 /// Update the texture entry for this part
2529 /// </summary> 2874 /// </summary>
@@ -2585,11 +2930,9 @@ namespace OpenSim.Region.Framework.Scenes
2585 scale.Y = m_scene.m_maxNonphys; 2930 scale.Y = m_scene.m_maxNonphys;
2586 if (scale.Z > m_scene.m_maxNonphys) 2931 if (scale.Z > m_scene.m_maxNonphys)
2587 scale.Z = m_scene.m_maxNonphys; 2932 scale.Z = m_scene.m_maxNonphys;
2588
2589 SceneObjectPart part = GetChildPart(localID); 2933 SceneObjectPart part = GetChildPart(localID);
2590 if (part != null) 2934 if (part != null)
2591 { 2935 {
2592 part.Resize(scale);
2593 if (part.PhysActor != null) 2936 if (part.PhysActor != null)
2594 { 2937 {
2595 if (part.PhysActor.IsPhysical) 2938 if (part.PhysActor.IsPhysical)
@@ -2604,7 +2947,7 @@ namespace OpenSim.Region.Framework.Scenes
2604 part.PhysActor.Size = scale; 2947 part.PhysActor.Size = scale;
2605 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2948 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2606 } 2949 }
2607 //if (part.UUID != m_rootPart.UUID) 2950 part.Resize(scale);
2608 2951
2609 HasGroupChanged = true; 2952 HasGroupChanged = true;
2610 ScheduleGroupForFullUpdate(); 2953 ScheduleGroupForFullUpdate();
@@ -2626,7 +2969,6 @@ namespace OpenSim.Region.Framework.Scenes
2626 SceneObjectPart part = GetChildPart(localID); 2969 SceneObjectPart part = GetChildPart(localID);
2627 if (part != null) 2970 if (part != null)
2628 { 2971 {
2629 part.IgnoreUndoUpdate = true;
2630 if (scale.X > m_scene.m_maxNonphys) 2972 if (scale.X > m_scene.m_maxNonphys)
2631 scale.X = m_scene.m_maxNonphys; 2973 scale.X = m_scene.m_maxNonphys;
2632 if (scale.Y > m_scene.m_maxNonphys) 2974 if (scale.Y > m_scene.m_maxNonphys)
@@ -2663,7 +3005,7 @@ namespace OpenSim.Region.Framework.Scenes
2663 3005
2664 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3006 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2665 { 3007 {
2666 if (oldSize.X * x > m_scene.m_maxPhys) 3008 if (oldSize.X*x > m_scene.m_maxPhys)
2667 { 3009 {
2668 f = m_scene.m_maxPhys / oldSize.X; 3010 f = m_scene.m_maxPhys / oldSize.X;
2669 a = f / x; 3011 a = f / x;
@@ -2671,7 +3013,7 @@ namespace OpenSim.Region.Framework.Scenes
2671 y *= a; 3013 y *= a;
2672 z *= a; 3014 z *= a;
2673 } 3015 }
2674 if (oldSize.Y * y > m_scene.m_maxPhys) 3016 if (oldSize.Y*y > m_scene.m_maxPhys)
2675 { 3017 {
2676 f = m_scene.m_maxPhys / oldSize.Y; 3018 f = m_scene.m_maxPhys / oldSize.Y;
2677 a = f / y; 3019 a = f / y;
@@ -2679,7 +3021,7 @@ namespace OpenSim.Region.Framework.Scenes
2679 y *= a; 3021 y *= a;
2680 z *= a; 3022 z *= a;
2681 } 3023 }
2682 if (oldSize.Z * z > m_scene.m_maxPhys) 3024 if (oldSize.Z*z > m_scene.m_maxPhys)
2683 { 3025 {
2684 f = m_scene.m_maxPhys / oldSize.Z; 3026 f = m_scene.m_maxPhys / oldSize.Z;
2685 a = f / z; 3027 a = f / z;
@@ -2690,7 +3032,7 @@ namespace OpenSim.Region.Framework.Scenes
2690 } 3032 }
2691 else 3033 else
2692 { 3034 {
2693 if (oldSize.X * x > m_scene.m_maxNonphys) 3035 if (oldSize.X*x > m_scene.m_maxNonphys)
2694 { 3036 {
2695 f = m_scene.m_maxNonphys / oldSize.X; 3037 f = m_scene.m_maxNonphys / oldSize.X;
2696 a = f / x; 3038 a = f / x;
@@ -2698,7 +3040,7 @@ namespace OpenSim.Region.Framework.Scenes
2698 y *= a; 3040 y *= a;
2699 z *= a; 3041 z *= a;
2700 } 3042 }
2701 if (oldSize.Y * y > m_scene.m_maxNonphys) 3043 if (oldSize.Y*y > m_scene.m_maxNonphys)
2702 { 3044 {
2703 f = m_scene.m_maxNonphys / oldSize.Y; 3045 f = m_scene.m_maxNonphys / oldSize.Y;
2704 a = f / y; 3046 a = f / y;
@@ -2706,7 +3048,7 @@ namespace OpenSim.Region.Framework.Scenes
2706 y *= a; 3048 y *= a;
2707 z *= a; 3049 z *= a;
2708 } 3050 }
2709 if (oldSize.Z * z > m_scene.m_maxNonphys) 3051 if (oldSize.Z*z > m_scene.m_maxNonphys)
2710 { 3052 {
2711 f = m_scene.m_maxNonphys / oldSize.Z; 3053 f = m_scene.m_maxNonphys / oldSize.Z;
2712 a = f / z; 3054 a = f / z;
@@ -2716,7 +3058,6 @@ namespace OpenSim.Region.Framework.Scenes
2716 } 3058 }
2717 } 3059 }
2718 obPart.IgnoreUndoUpdate = false; 3060 obPart.IgnoreUndoUpdate = false;
2719 obPart.StoreUndoState();
2720 } 3061 }
2721 } 3062 }
2722 } 3063 }
@@ -2724,8 +3065,13 @@ namespace OpenSim.Region.Framework.Scenes
2724 Vector3 prevScale = part.Scale; 3065 Vector3 prevScale = part.Scale;
2725 prevScale.X *= x; 3066 prevScale.X *= x;
2726 prevScale.Y *= y; 3067 prevScale.Y *= y;
2727 prevScale.Z *= z; 3068 prevScale.Z *= z;;
3069
3070 part.IgnoreUndoUpdate = false;
3071 part.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3072 part.IgnoreUndoUpdate = true;
2728 part.Resize(prevScale); 3073 part.Resize(prevScale);
3074 part.IgnoreUndoUpdate = false;
2729 3075
2730 parts = m_parts.GetArray(); 3076 parts = m_parts.GetArray();
2731 for (int i = 0; i < parts.Length; i++) 3077 for (int i = 0; i < parts.Length; i++)
@@ -2734,19 +3080,26 @@ namespace OpenSim.Region.Framework.Scenes
2734 obPart.IgnoreUndoUpdate = true; 3080 obPart.IgnoreUndoUpdate = true;
2735 if (obPart.UUID != m_rootPart.UUID) 3081 if (obPart.UUID != m_rootPart.UUID)
2736 { 3082 {
2737 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3083 if (obPart.UUID != m_rootPart.UUID)
2738 currentpos.X *= x; 3084 {
2739 currentpos.Y *= y; 3085 obPart.IgnoreUndoUpdate = false;
2740 currentpos.Z *= z; 3086 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
2741 Vector3 newSize = new Vector3(obPart.Scale); 3087 obPart.IgnoreUndoUpdate = true;
2742 newSize.X *= x; 3088
2743 newSize.Y *= y; 3089 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2744 newSize.Z *= z; 3090 currentpos.X *= x;
2745 obPart.Resize(newSize); 3091 currentpos.Y *= y;
2746 obPart.UpdateOffSet(currentpos); 3092 currentpos.Z *= z;
3093 Vector3 newSize = new Vector3(obPart.Scale);
3094 newSize.X *= x;
3095 newSize.Y *= y;
3096 newSize.Z *= z;
3097 obPart.Resize(newSize);
3098 obPart.UpdateOffSet(currentpos);
3099 }
3100 obPart.IgnoreUndoUpdate = false;
2747 } 3101 }
2748 obPart.IgnoreUndoUpdate = false; 3102 obPart.IgnoreUndoUpdate = false;
2749 obPart.StoreUndoState();
2750 } 3103 }
2751 3104
2752 if (part.PhysActor != null) 3105 if (part.PhysActor != null)
@@ -2756,7 +3109,6 @@ namespace OpenSim.Region.Framework.Scenes
2756 } 3109 }
2757 3110
2758 part.IgnoreUndoUpdate = false; 3111 part.IgnoreUndoUpdate = false;
2759 part.StoreUndoState();
2760 HasGroupChanged = true; 3112 HasGroupChanged = true;
2761 ScheduleGroupForTerseUpdate(); 3113 ScheduleGroupForTerseUpdate();
2762 } 3114 }
@@ -2772,14 +3124,11 @@ namespace OpenSim.Region.Framework.Scenes
2772 /// <param name="pos"></param> 3124 /// <param name="pos"></param>
2773 public void UpdateGroupPosition(Vector3 pos) 3125 public void UpdateGroupPosition(Vector3 pos)
2774 { 3126 {
2775 SceneObjectPart[] parts = m_parts.GetArray();
2776 for (int i = 0; i < parts.Length; i++)
2777 parts[i].StoreUndoState();
2778
2779 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3127 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2780 { 3128 {
2781 if (IsAttachment) 3129 if (IsAttachment)
2782 { 3130 {
3131 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
2783 m_rootPart.AttachedPos = pos; 3132 m_rootPart.AttachedPos = pos;
2784 } 3133 }
2785 if (RootPart.GetStatusSandbox()) 3134 if (RootPart.GetStatusSandbox())
@@ -2813,7 +3162,7 @@ namespace OpenSim.Region.Framework.Scenes
2813 3162
2814 SceneObjectPart[] parts = m_parts.GetArray(); 3163 SceneObjectPart[] parts = m_parts.GetArray();
2815 for (int i = 0; i < parts.Length; i++) 3164 for (int i = 0; i < parts.Length; i++)
2816 parts[i].StoreUndoState(); 3165 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2817 3166
2818 if (part != null) 3167 if (part != null)
2819 { 3168 {
@@ -2838,7 +3187,7 @@ namespace OpenSim.Region.Framework.Scenes
2838 { 3187 {
2839 SceneObjectPart[] parts = m_parts.GetArray(); 3188 SceneObjectPart[] parts = m_parts.GetArray();
2840 for (int i = 0; i < parts.Length; i++) 3189 for (int i = 0; i < parts.Length; i++)
2841 parts[i].StoreUndoState(); 3190 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2842 3191
2843 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3192 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2844 Vector3 oldPos = 3193 Vector3 oldPos =
@@ -2859,10 +3208,27 @@ namespace OpenSim.Region.Framework.Scenes
2859 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3208 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2860 } 3209 }
2861 3210
2862 AbsolutePosition = newPos; 3211 //We have to set undoing here because otherwise an undo state will be saved
3212 if (!m_rootPart.Undoing)
3213 {
3214 m_rootPart.Undoing = true;
3215 AbsolutePosition = newPos;
3216 m_rootPart.Undoing = false;
3217 }
3218 else
3219 {
3220 AbsolutePosition = newPos;
3221 }
2863 3222
2864 HasGroupChanged = true; 3223 HasGroupChanged = true;
2865 ScheduleGroupForTerseUpdate(); 3224 if (m_rootPart.Undoing)
3225 {
3226 ScheduleGroupForFullUpdate();
3227 }
3228 else
3229 {
3230 ScheduleGroupForTerseUpdate();
3231 }
2866 } 3232 }
2867 3233
2868 public void OffsetForNewRegion(Vector3 offset) 3234 public void OffsetForNewRegion(Vector3 offset)
@@ -2882,7 +3248,7 @@ namespace OpenSim.Region.Framework.Scenes
2882 { 3248 {
2883 SceneObjectPart[] parts = m_parts.GetArray(); 3249 SceneObjectPart[] parts = m_parts.GetArray();
2884 for (int i = 0; i < parts.Length; i++) 3250 for (int i = 0; i < parts.Length; i++)
2885 parts[i].StoreUndoState(); 3251 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2886 3252
2887 m_rootPart.UpdateRotation(rot); 3253 m_rootPart.UpdateRotation(rot);
2888 3254
@@ -2906,7 +3272,7 @@ namespace OpenSim.Region.Framework.Scenes
2906 { 3272 {
2907 SceneObjectPart[] parts = m_parts.GetArray(); 3273 SceneObjectPart[] parts = m_parts.GetArray();
2908 for (int i = 0; i < parts.Length; i++) 3274 for (int i = 0; i < parts.Length; i++)
2909 parts[i].StoreUndoState(); 3275 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2910 3276
2911 m_rootPart.UpdateRotation(rot); 3277 m_rootPart.UpdateRotation(rot);
2912 3278
@@ -2931,10 +3297,9 @@ namespace OpenSim.Region.Framework.Scenes
2931 public void UpdateSingleRotation(Quaternion rot, uint localID) 3297 public void UpdateSingleRotation(Quaternion rot, uint localID)
2932 { 3298 {
2933 SceneObjectPart part = GetChildPart(localID); 3299 SceneObjectPart part = GetChildPart(localID);
2934
2935 SceneObjectPart[] parts = m_parts.GetArray(); 3300 SceneObjectPart[] parts = m_parts.GetArray();
2936 for (int i = 0; i < parts.Length; i++) 3301 for (int i = 0; i < parts.Length; i++)
2937 parts[i].StoreUndoState(); 3302 parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2938 3303
2939 if (part != null) 3304 if (part != null)
2940 { 3305 {
@@ -2962,15 +3327,24 @@ namespace OpenSim.Region.Framework.Scenes
2962 if (part.UUID == m_rootPart.UUID) 3327 if (part.UUID == m_rootPart.UUID)
2963 { 3328 {
2964 UpdateRootRotation(rot); 3329 UpdateRootRotation(rot);
2965 AbsolutePosition = pos; 3330 if (!m_rootPart.Undoing)
3331 {
3332 m_rootPart.Undoing = true;
3333 AbsolutePosition = pos;
3334 m_rootPart.Undoing = false;
3335 }
3336 else
3337 {
3338 AbsolutePosition = pos;
3339 }
2966 } 3340 }
2967 else 3341 else
2968 { 3342 {
3343 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2969 part.IgnoreUndoUpdate = true; 3344 part.IgnoreUndoUpdate = true;
2970 part.UpdateRotation(rot); 3345 part.UpdateRotation(rot);
2971 part.OffsetPosition = pos; 3346 part.OffsetPosition = pos;
2972 part.IgnoreUndoUpdate = false; 3347 part.IgnoreUndoUpdate = false;
2973 part.StoreUndoState();
2974 } 3348 }
2975 } 3349 }
2976 } 3350 }
@@ -2984,7 +3358,13 @@ namespace OpenSim.Region.Framework.Scenes
2984 Quaternion axRot = rot; 3358 Quaternion axRot = rot;
2985 Quaternion oldParentRot = m_rootPart.RotationOffset; 3359 Quaternion oldParentRot = m_rootPart.RotationOffset;
2986 3360
2987 m_rootPart.StoreUndoState(); 3361 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3362 bool cancelUndo = false;
3363 if (!m_rootPart.Undoing)
3364 {
3365 m_rootPart.Undoing = true;
3366 cancelUndo = true;
3367 }
2988 m_rootPart.UpdateRotation(rot); 3368 m_rootPart.UpdateRotation(rot);
2989 if (m_rootPart.PhysActor != null) 3369 if (m_rootPart.PhysActor != null)
2990 { 3370 {
@@ -3008,17 +3388,12 @@ namespace OpenSim.Region.Framework.Scenes
3008 newRot *= Quaternion.Inverse(axRot); 3388 newRot *= Quaternion.Inverse(axRot);
3009 prim.RotationOffset = newRot; 3389 prim.RotationOffset = newRot;
3010 prim.ScheduleTerseUpdate(); 3390 prim.ScheduleTerseUpdate();
3391 prim.IgnoreUndoUpdate = false;
3011 } 3392 }
3012 } 3393 }
3013 3394 if (cancelUndo == true)
3014 for (int i = 0; i < parts.Length; i++)
3015 { 3395 {
3016 SceneObjectPart childpart = parts[i]; 3396 m_rootPart.Undoing = false;
3017 if (childpart != m_rootPart)
3018 {
3019 childpart.IgnoreUndoUpdate = false;
3020 childpart.StoreUndoState();
3021 }
3022 } 3397 }
3023 3398
3024 m_rootPart.ScheduleTerseUpdate(); 3399 m_rootPart.ScheduleTerseUpdate();
@@ -3244,7 +3619,6 @@ namespace OpenSim.Region.Framework.Scenes
3244 public float GetMass() 3619 public float GetMass()
3245 { 3620 {
3246 float retmass = 0f; 3621 float retmass = 0f;
3247
3248 SceneObjectPart[] parts = m_parts.GetArray(); 3622 SceneObjectPart[] parts = m_parts.GetArray();
3249 for (int i = 0; i < parts.Length; i++) 3623 for (int i = 0; i < parts.Length; i++)
3250 retmass += parts[i].GetMass(); 3624 retmass += parts[i].GetMass();
@@ -3360,6 +3734,14 @@ namespace OpenSim.Region.Framework.Scenes
3360 SetFromItemID(uuid); 3734 SetFromItemID(uuid);
3361 } 3735 }
3362 3736
3737 public void ResetOwnerChangeFlag()
3738 {
3739 ForEachPart(delegate(SceneObjectPart part)
3740 {
3741 part.ResetOwnerChangeFlag();
3742 });
3743 }
3744
3363 #endregion 3745 #endregion
3364 } 3746 }
3365} 3747}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index f164201..b615d42 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -61,7 +61,8 @@ namespace OpenSim.Region.Framework.Scenes
61 TELEPORT = 512, 61 TELEPORT = 512,
62 REGION_RESTART = 1024, 62 REGION_RESTART = 1024,
63 MEDIA = 2048, 63 MEDIA = 2048,
64 ANIMATION = 16384 64 ANIMATION = 16384,
65 POSITION = 32768
65 } 66 }
66 67
67 // I don't really know where to put this except here. 68 // I don't really know where to put this except here.
@@ -145,10 +146,10 @@ namespace OpenSim.Region.Framework.Scenes
145 public Vector3 StatusSandboxPos; 146 public Vector3 StatusSandboxPos;
146 147
147 // TODO: This needs to be persisted in next XML version update! 148 // TODO: This needs to be persisted in next XML version update!
148 149 [XmlIgnore]
149 public readonly int[] PayPrice = {-2,-2,-2,-2,-2}; 150 public int[] PayPrice = {-2,-2,-2,-2,-2};
150 151
151 152 [XmlIgnore]
152 public PhysicsActor PhysActor 153 public PhysicsActor PhysActor
153 { 154 {
154 get { return m_physActor; } 155 get { return m_physActor; }
@@ -190,7 +191,15 @@ namespace OpenSim.Region.Framework.Scenes
190 191
191 public UUID FromFolderID; 192 public UUID FromFolderID;
192 193
193 194 // The following two are to hold the attachment data
195 // while an object is inworld
196 [XmlIgnore]
197 public byte AttachPoint = 0;
198
199 [XmlIgnore]
200 public Vector3 AttachOffset = Vector3.Zero;
201
202 [XmlIgnore]
194 public int STATUS_ROTATE_X; 203 public int STATUS_ROTATE_X;
195 204
196 205
@@ -285,6 +294,7 @@ namespace OpenSim.Region.Framework.Scenes
285 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 294 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
286 private Vector3 m_sitTargetPosition; 295 private Vector3 m_sitTargetPosition;
287 private string m_sitAnimation = "SIT"; 296 private string m_sitAnimation = "SIT";
297 private bool m_occupied; // KF if any av is sitting on this prim
288 private string m_text = String.Empty; 298 private string m_text = String.Empty;
289 private string m_touchName = String.Empty; 299 private string m_touchName = String.Empty;
290 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 300 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
@@ -374,7 +384,7 @@ namespace OpenSim.Region.Framework.Scenes
374 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 384 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
375 Quaternion rotationOffset, Vector3 offsetPosition) 385 Quaternion rotationOffset, Vector3 offsetPosition)
376 { 386 {
377 m_name = "Primitive"; 387 m_name = "Object";
378 388
379 Rezzed = DateTime.UtcNow; 389 Rezzed = DateTime.UtcNow;
380 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 390 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
@@ -430,7 +440,7 @@ namespace OpenSim.Region.Framework.Scenes
430 private uint _ownerMask = (uint)PermissionMask.All; 440 private uint _ownerMask = (uint)PermissionMask.All;
431 private uint _groupMask = (uint)PermissionMask.None; 441 private uint _groupMask = (uint)PermissionMask.None;
432 private uint _everyoneMask = (uint)PermissionMask.None; 442 private uint _everyoneMask = (uint)PermissionMask.None;
433 private uint _nextOwnerMask = (uint)PermissionMask.All; 443 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
434 private PrimFlags _flags = PrimFlags.None; 444 private PrimFlags _flags = PrimFlags.None;
435 private DateTime m_expires; 445 private DateTime m_expires;
436 private DateTime m_rezzed; 446 private DateTime m_rezzed;
@@ -470,12 +480,16 @@ namespace OpenSim.Region.Framework.Scenes
470 } 480 }
471 481
472 /// <value> 482 /// <value>
473 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 483 /// Get the inventory list
474 /// </value> 484 /// </value>
475 public TaskInventoryDictionary TaskInventory 485 public TaskInventoryDictionary TaskInventory
476 { 486 {
477 get { return m_inventory.Items; } 487 get {
478 set { m_inventory.Items = value; } 488 return m_inventory.Items;
489 }
490 set {
491 m_inventory.Items = value;
492 }
479 } 493 }
480 494
481 /// <summary> 495 /// <summary>
@@ -615,14 +629,12 @@ namespace OpenSim.Region.Framework.Scenes
615 set { m_LoopSoundSlavePrims = value; } 629 set { m_LoopSoundSlavePrims = value; }
616 } 630 }
617 631
618
619 public Byte[] TextureAnimation 632 public Byte[] TextureAnimation
620 { 633 {
621 get { return m_TextureAnimation; } 634 get { return m_TextureAnimation; }
622 set { m_TextureAnimation = value; } 635 set { m_TextureAnimation = value; }
623 } 636 }
624 637
625
626 public Byte[] ParticleSystem 638 public Byte[] ParticleSystem
627 { 639 {
628 get { return m_particleSystem; } 640 get { return m_particleSystem; }
@@ -676,7 +688,6 @@ namespace OpenSim.Region.Framework.Scenes
676 set 688 set
677 { 689 {
678 m_groupPosition = value; 690 m_groupPosition = value;
679
680 PhysicsActor actor = PhysActor; 691 PhysicsActor actor = PhysActor;
681 if (actor != null) 692 if (actor != null)
682 { 693 {
@@ -696,25 +707,13 @@ namespace OpenSim.Region.Framework.Scenes
696 707
697 // Tell the physics engines that this prim changed. 708 // Tell the physics engines that this prim changed.
698 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 709 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
710
699 } 711 }
700 catch (Exception e) 712 catch (Exception e)
701 { 713 {
702 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 714 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
703 } 715 }
704 } 716 }
705
706 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
707 if (m_sitTargetAvatar != UUID.Zero)
708 {
709 if (m_parentGroup != null) // TODO can there be a SOP without a SOG?
710 {
711 ScenePresence avatar;
712 if (m_parentGroup.Scene.TryGetScenePresence(m_sitTargetAvatar, out avatar))
713 {
714 avatar.ParentPosition = GetWorldPosition();
715 }
716 }
717 }
718 } 717 }
719 } 718 }
720 719
@@ -723,7 +722,8 @@ namespace OpenSim.Region.Framework.Scenes
723 get { return m_offsetPosition; } 722 get { return m_offsetPosition; }
724 set 723 set
725 { 724 {
726 StoreUndoState(); 725 Vector3 oldpos = m_offsetPosition;
726 StoreUndoState(UndoType.STATE_PRIM_POSITION);
727 m_offsetPosition = value; 727 m_offsetPosition = value;
728 728
729 if (ParentGroup != null && !ParentGroup.IsDeleted) 729 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -737,7 +737,22 @@ namespace OpenSim.Region.Framework.Scenes
737 // Tell the physics engines that this prim changed. 737 // Tell the physics engines that this prim changed.
738 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 738 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
739 } 739 }
740
741 if (!m_parentGroup.m_dupeInProgress)
742 {
743 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
744 foreach (ScenePresence av in avs)
745 {
746 if (av.LinkedPrim == m_uuid)
747 {
748 Vector3 offset = (m_offsetPosition - oldpos);
749 av.OffsetPosition += offset;
750 av.SendFullUpdateToAllClients();
751 }
752 }
753 }
740 } 754 }
755 TriggerScriptChangedEvent(Changed.POSITION);
741 } 756 }
742 } 757 }
743 758
@@ -779,7 +794,7 @@ namespace OpenSim.Region.Framework.Scenes
779 794
780 set 795 set
781 { 796 {
782 StoreUndoState(); 797 StoreUndoState(UndoType.STATE_PRIM_ROTATION);
783 m_rotationOffset = value; 798 m_rotationOffset = value;
784 799
785 PhysicsActor actor = PhysActor; 800 PhysicsActor actor = PhysActor;
@@ -863,7 +878,16 @@ namespace OpenSim.Region.Framework.Scenes
863 /// <summary></summary> 878 /// <summary></summary>
864 public Vector3 Acceleration 879 public Vector3 Acceleration
865 { 880 {
866 get { return m_acceleration; } 881 get
882 {
883 PhysicsActor actor = PhysActor;
884 if (actor != null)
885 {
886 m_acceleration = actor.Acceleration;
887 }
888 return m_acceleration;
889 }
890
867 set { m_acceleration = value; } 891 set { m_acceleration = value; }
868 } 892 }
869 893
@@ -968,7 +992,7 @@ namespace OpenSim.Region.Framework.Scenes
968 get { return m_shape.Scale; } 992 get { return m_shape.Scale; }
969 set 993 set
970 { 994 {
971 StoreUndoState(); 995 StoreUndoState(UndoType.STATE_PRIM_SCALE);
972 if (m_shape != null) 996 if (m_shape != null)
973 { 997 {
974 m_shape.Scale = value; 998 m_shape.Scale = value;
@@ -1036,9 +1060,10 @@ namespace OpenSim.Region.Framework.Scenes
1036 { 1060 {
1037 get { 1061 get {
1038 if (IsAttachment) 1062 if (IsAttachment)
1039 return GroupPosition; 1063 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1040 1064
1041 return m_offsetPosition + m_groupPosition; } 1065// return m_offsetPosition + m_groupPosition; }
1066 return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored!
1042 } 1067 }
1043 1068
1044 public SceneObjectGroup ParentGroup 1069 public SceneObjectGroup ParentGroup
@@ -1197,6 +1222,13 @@ namespace OpenSim.Region.Framework.Scenes
1197 _flags = value; 1222 _flags = value;
1198 } 1223 }
1199 } 1224 }
1225
1226 [XmlIgnore]
1227 public bool IsOccupied // KF If an av is sittingon this prim
1228 {
1229 get { return m_occupied; }
1230 set { m_occupied = value; }
1231 }
1200 1232
1201 1233
1202 public UUID SitTargetAvatar 1234 public UUID SitTargetAvatar
@@ -1272,14 +1304,6 @@ namespace OpenSim.Region.Framework.Scenes
1272 } 1304 }
1273 } 1305 }
1274 1306
1275 /// <summary>
1276 /// Clear all pending updates of parts to clients
1277 /// </summary>
1278 private void ClearUpdateSchedule()
1279 {
1280 m_updateFlag = 0;
1281 }
1282
1283 private void SendObjectPropertiesToClient(UUID AgentID) 1307 private void SendObjectPropertiesToClient(UUID AgentID)
1284 { 1308 {
1285 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1309 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1530,14 +1554,21 @@ namespace OpenSim.Region.Framework.Scenes
1530 // or flexible 1554 // or flexible
1531 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible)) 1555 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible))
1532 { 1556 {
1533 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( 1557 try
1534 string.Format("{0}/{1}", Name, UUID), 1558 {
1535 Shape, 1559 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
1536 AbsolutePosition, 1560 string.Format("{0}/{1}", Name, UUID),
1537 Scale, 1561 Shape,
1538 RotationOffset, 1562 AbsolutePosition,
1539 RigidBody); 1563 Scale,
1540 1564 RotationOffset,
1565 RigidBody);
1566 }
1567 catch
1568 {
1569 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid);
1570 PhysActor = null;
1571 }
1541 // Basic Physics returns null.. joy joy joy. 1572 // Basic Physics returns null.. joy joy joy.
1542 if (PhysActor != null) 1573 if (PhysActor != null)
1543 { 1574 {
@@ -1565,7 +1596,7 @@ namespace OpenSim.Region.Framework.Scenes
1565 { 1596 {
1566 m_redo.Clear(); 1597 m_redo.Clear();
1567 } 1598 }
1568 StoreUndoState(); 1599 StoreUndoState(UndoType.STATE_ALL);
1569 } 1600 }
1570 1601
1571 public byte ConvertScriptUintToByte(uint indata) 1602 public byte ConvertScriptUintToByte(uint indata)
@@ -1634,6 +1665,9 @@ namespace OpenSim.Region.Framework.Scenes
1634 1665
1635 // Move afterwards ResetIDs as it clears the localID 1666 // Move afterwards ResetIDs as it clears the localID
1636 dupe.LocalId = localID; 1667 dupe.LocalId = localID;
1668 if(dupe.PhysActor != null)
1669 dupe.PhysActor.LocalID = localID;
1670
1637 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1671 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1638 dupe._lastOwnerID = OwnerID; 1672 dupe._lastOwnerID = OwnerID;
1639 1673
@@ -1677,7 +1711,7 @@ namespace OpenSim.Region.Framework.Scenes
1677 PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); 1711 PrimitiveBaseShape shape = PrimitiveBaseShape.Create();
1678 part.Shape = shape; 1712 part.Shape = shape;
1679 1713
1680 part.Name = "Primitive"; 1714 part.Name = "Object";
1681 part._ownerID = UUID.Random(); 1715 part._ownerID = UUID.Random();
1682 1716
1683 return part; 1717 return part;
@@ -2037,12 +2071,17 @@ namespace OpenSim.Region.Framework.Scenes
2037 public Vector3 GetWorldPosition() 2071 public Vector3 GetWorldPosition()
2038 { 2072 {
2039 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2073 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
2040
2041 Vector3 axPos = OffsetPosition; 2074 Vector3 axPos = OffsetPosition;
2042
2043 axPos *= parentRot; 2075 axPos *= parentRot;
2044 Vector3 translationOffsetPosition = axPos; 2076 Vector3 translationOffsetPosition = axPos;
2045 return GroupPosition + translationOffsetPosition; 2077 if(_parentID == 0)
2078 {
2079 return GroupPosition;
2080 }
2081 else
2082 {
2083 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
2084 }
2046 } 2085 }
2047 2086
2048 /// <summary> 2087 /// <summary>
@@ -2053,7 +2092,7 @@ namespace OpenSim.Region.Framework.Scenes
2053 { 2092 {
2054 Quaternion newRot; 2093 Quaternion newRot;
2055 2094
2056 if (this.LinkNum == 0) 2095 if (this.LinkNum < 2) //KF Single or root prim
2057 { 2096 {
2058 newRot = RotationOffset; 2097 newRot = RotationOffset;
2059 } 2098 }
@@ -2699,17 +2738,18 @@ namespace OpenSim.Region.Framework.Scenes
2699 //Trys to fetch sound id from prim's inventory. 2738 //Trys to fetch sound id from prim's inventory.
2700 //Prim's inventory doesn't support non script items yet 2739 //Prim's inventory doesn't support non script items yet
2701 2740
2702 lock (TaskInventory) 2741 TaskInventory.LockItemsForRead(true);
2742
2743 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2703 { 2744 {
2704 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2745 if (item.Value.Name == sound)
2705 { 2746 {
2706 if (item.Value.Name == sound) 2747 soundID = item.Value.ItemID;
2707 { 2748 break;
2708 soundID = item.Value.ItemID;
2709 break;
2710 }
2711 } 2749 }
2712 } 2750 }
2751
2752 TaskInventory.LockItemsForRead(false);
2713 } 2753 }
2714 2754
2715 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2755 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2769,7 +2809,7 @@ namespace OpenSim.Region.Framework.Scenes
2769 /// <param name="scale"></param> 2809 /// <param name="scale"></param>
2770 public void Resize(Vector3 scale) 2810 public void Resize(Vector3 scale)
2771 { 2811 {
2772 StoreUndoState(); 2812 StoreUndoState(UndoType.STATE_PRIM_SCALE);
2773 m_shape.Scale = scale; 2813 m_shape.Scale = scale;
2774 2814
2775 ParentGroup.HasGroupChanged = true; 2815 ParentGroup.HasGroupChanged = true;
@@ -2778,38 +2818,7 @@ namespace OpenSim.Region.Framework.Scenes
2778 2818
2779 public void RotLookAt(Quaternion target, float strength, float damping) 2819 public void RotLookAt(Quaternion target, float strength, float damping)
2780 { 2820 {
2781 rotLookAt(target, strength, damping); 2821 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2782 }
2783
2784 public void rotLookAt(Quaternion target, float strength, float damping)
2785 {
2786 if (IsAttachment)
2787 {
2788 /*
2789 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2790 if (avatar != null)
2791 {
2792 Rotate the Av?
2793 } */
2794 }
2795 else
2796 {
2797 APIDDamp = damping;
2798 APIDStrength = strength;
2799 APIDTarget = target;
2800 }
2801 }
2802
2803 public void startLookAt(Quaternion rot, float damp, float strength)
2804 {
2805 APIDDamp = damp;
2806 APIDStrength = strength;
2807 APIDTarget = rot;
2808 }
2809
2810 public void stopLookAt()
2811 {
2812 APIDTarget = Quaternion.Identity;
2813 } 2822 }
2814 2823
2815 /// <summary> 2824 /// <summary>
@@ -2821,7 +2830,10 @@ namespace OpenSim.Region.Framework.Scenes
2821 2830
2822 if (m_parentGroup != null) 2831 if (m_parentGroup != null)
2823 { 2832 {
2824 m_parentGroup.QueueForUpdateCheck(); 2833 if (!m_parentGroup.areUpdatesSuspended)
2834 {
2835 m_parentGroup.QueueForUpdateCheck();
2836 }
2825 } 2837 }
2826 2838
2827 int timeNow = Util.UnixTimeSinceEpoch(); 2839 int timeNow = Util.UnixTimeSinceEpoch();
@@ -3038,8 +3050,8 @@ namespace OpenSim.Region.Framework.Scenes
3038 { 3050 {
3039 const float ROTATION_TOLERANCE = 0.01f; 3051 const float ROTATION_TOLERANCE = 0.01f;
3040 const float VELOCITY_TOLERANCE = 0.001f; 3052 const float VELOCITY_TOLERANCE = 0.001f;
3041 const float POSITION_TOLERANCE = 0.05f; 3053 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
3042 const int TIME_MS_TOLERANCE = 3000; 3054 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
3043 3055
3044 if (m_updateFlag == 1) 3056 if (m_updateFlag == 1)
3045 { 3057 {
@@ -3053,7 +3065,7 @@ namespace OpenSim.Region.Framework.Scenes
3053 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3065 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
3054 { 3066 {
3055 AddTerseUpdateToAllAvatars(); 3067 AddTerseUpdateToAllAvatars();
3056 ClearUpdateSchedule(); 3068
3057 3069
3058 // This causes the Scene to 'poll' physical objects every couple of frames 3070 // This causes the Scene to 'poll' physical objects every couple of frames
3059 // bad, so it's been replaced by an event driven method. 3071 // bad, so it's been replaced by an event driven method.
@@ -3071,16 +3083,18 @@ namespace OpenSim.Region.Framework.Scenes
3071 m_lastAngularVelocity = AngularVelocity; 3083 m_lastAngularVelocity = AngularVelocity;
3072 m_lastTerseSent = Environment.TickCount; 3084 m_lastTerseSent = Environment.TickCount;
3073 } 3085 }
3086 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
3087 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
3074 } 3088 }
3075 else 3089 else
3076 { 3090 {
3077 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 3091 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3078 { 3092 {
3079 AddFullUpdateToAllAvatars(); 3093 AddFullUpdateToAllAvatars();
3080 ClearUpdateSchedule(); 3094 m_updateFlag = 0; //Same here
3081 } 3095 }
3082 } 3096 }
3083 ClearUpdateSchedule(); 3097 m_updateFlag = 0;
3084 } 3098 }
3085 3099
3086 /// <summary> 3100 /// <summary>
@@ -3108,17 +3122,16 @@ namespace OpenSim.Region.Framework.Scenes
3108 if (!UUID.TryParse(sound, out soundID)) 3122 if (!UUID.TryParse(sound, out soundID))
3109 { 3123 {
3110 // search sound file from inventory 3124 // search sound file from inventory
3111 lock (TaskInventory) 3125 TaskInventory.LockItemsForRead(true);
3126 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3112 { 3127 {
3113 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3128 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3114 { 3129 {
3115 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3130 soundID = item.Value.ItemID;
3116 { 3131 break;
3117 soundID = item.Value.ItemID;
3118 break;
3119 }
3120 } 3132 }
3121 } 3133 }
3134 TaskInventory.LockItemsForRead(false);
3122 } 3135 }
3123 3136
3124 if (soundID == UUID.Zero) 3137 if (soundID == UUID.Zero)
@@ -3555,7 +3568,7 @@ namespace OpenSim.Region.Framework.Scenes
3555 3568
3556 public void StopLookAt() 3569 public void StopLookAt()
3557 { 3570 {
3558 m_parentGroup.stopLookAt(); 3571 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3559 3572
3560 m_parentGroup.ScheduleGroupForTerseUpdate(); 3573 m_parentGroup.ScheduleGroupForTerseUpdate();
3561 } 3574 }
@@ -3582,10 +3595,9 @@ namespace OpenSim.Region.Framework.Scenes
3582 m_parentGroup.ScheduleGroupForTerseUpdate(); 3595 m_parentGroup.ScheduleGroupForTerseUpdate();
3583 //m_parentGroup.ScheduleGroupForFullUpdate(); 3596 //m_parentGroup.ScheduleGroupForFullUpdate();
3584 } 3597 }
3585 3598 public void StoreUndoState(UndoType type)
3586 public void StoreUndoState()
3587 { 3599 {
3588 if (!Undoing) 3600 if (!Undoing && (m_parentGroup == null || m_parentGroup.RootPart == null || !m_parentGroup.RootPart.Undoing))
3589 { 3601 {
3590 if (!IgnoreUndoUpdate) 3602 if (!IgnoreUndoUpdate)
3591 { 3603 {
@@ -3596,17 +3608,25 @@ namespace OpenSim.Region.Framework.Scenes
3596 if (m_undo.Count > 0) 3608 if (m_undo.Count > 0)
3597 { 3609 {
3598 UndoState last = m_undo.Peek(); 3610 UndoState last = m_undo.Peek();
3599 if (last != null) 3611
3600 {
3601 if (last.Compare(this))
3602 return;
3603 }
3604 } 3612 }
3605 3613
3606 if (m_parentGroup.GetSceneMaxUndo() > 0) 3614 if (m_parentGroup.GetSceneMaxUndo() > 0)
3607 { 3615 {
3608 UndoState nUndo = new UndoState(this); 3616 UndoState lastUndo = m_undo.Peek();
3609 3617
3618 UndoState nUndo = new UndoState(this, type);
3619
3620 if (lastUndo != null)
3621 {
3622 TimeSpan ts = DateTime.Now.Subtract(lastUndo.LastUpdated);
3623 if (ts.TotalMilliseconds < 500)
3624 {
3625 //Delete the last entry since it was less than 500 milliseconds ago
3626 nUndo.Merge(lastUndo);
3627 m_undo.Pop();
3628 }
3629 }
3610 m_undo.Push(nUndo); 3630 m_undo.Push(nUndo);
3611 } 3631 }
3612 3632
@@ -4083,11 +4103,13 @@ namespace OpenSim.Region.Framework.Scenes
4083 if (m_undo.Count > 0) 4103 if (m_undo.Count > 0)
4084 { 4104 {
4085 UndoState nUndo = null; 4105 UndoState nUndo = null;
4106 UndoState goback = m_undo.Pop();
4086 if (m_parentGroup.GetSceneMaxUndo() > 0) 4107 if (m_parentGroup.GetSceneMaxUndo() > 0)
4087 { 4108 {
4088 nUndo = new UndoState(this); 4109 nUndo = new UndoState(this, goback.Type);
4089 } 4110 }
4090 UndoState goback = m_undo.Pop(); 4111
4112
4091 if (goback != null) 4113 if (goback != null)
4092 { 4114 {
4093 goback.PlaybackState(this); 4115 goback.PlaybackState(this);
@@ -4102,13 +4124,13 @@ namespace OpenSim.Region.Framework.Scenes
4102 { 4124 {
4103 lock (m_redo) 4125 lock (m_redo)
4104 { 4126 {
4127 UndoState gofwd = m_redo.Pop();
4105 if (m_parentGroup.GetSceneMaxUndo() > 0) 4128 if (m_parentGroup.GetSceneMaxUndo() > 0)
4106 { 4129 {
4107 UndoState nUndo = new UndoState(this); 4130 UndoState nUndo = new UndoState(this, gofwd.Type);
4108 4131
4109 m_undo.Push(nUndo); 4132 m_undo.Push(nUndo);
4110 } 4133 }
4111 UndoState gofwd = m_redo.Pop();
4112 if (gofwd != null) 4134 if (gofwd != null)
4113 gofwd.PlayfwdState(this); 4135 gofwd.PlayfwdState(this);
4114 } 4136 }
@@ -4556,8 +4578,9 @@ namespace OpenSim.Region.Framework.Scenes
4556 { 4578 {
4557 m_shape.TextureEntry = textureEntry; 4579 m_shape.TextureEntry = textureEntry;
4558 TriggerScriptChangedEvent(Changed.TEXTURE); 4580 TriggerScriptChangedEvent(Changed.TEXTURE);
4559 4581 m_updateFlag = 1;
4560 ParentGroup.HasGroupChanged = true; 4582 ParentGroup.HasGroupChanged = true;
4583
4561 //This is madness.. 4584 //This is madness..
4562 //ParentGroup.ScheduleGroupForFullUpdate(); 4585 //ParentGroup.ScheduleGroupForFullUpdate();
4563 //This is sparta 4586 //This is sparta
@@ -4790,5 +4813,17 @@ namespace OpenSim.Region.Framework.Scenes
4790 Color color = Color; 4813 Color color = Color;
4791 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4814 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4792 } 4815 }
4816
4817 public void ResetOwnerChangeFlag()
4818 {
4819 List<UUID> inv = Inventory.GetInventoryList();
4820
4821 foreach (UUID itemID in inv)
4822 {
4823 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4824 item.OwnerChanged = false;
4825 Inventory.UpdateInventoryItem(item, false, false);
4826 }
4827 }
4793 } 4828 }
4794} 4829}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 6a204c3..8fcfcc5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -47,6 +47,8 @@ namespace OpenSim.Region.Framework.Scenes
47 47
48 private string m_inventoryFileName = String.Empty; 48 private string m_inventoryFileName = String.Empty;
49 private int m_inventoryFileNameSerial = 0; 49 private int m_inventoryFileNameSerial = 0;
50
51 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
50 52
51 /// <value> 53 /// <value>
52 /// The part to which the inventory belongs. 54 /// The part to which the inventory belongs.
@@ -83,7 +85,9 @@ namespace OpenSim.Region.Framework.Scenes
83 /// </value> 85 /// </value>
84 protected internal TaskInventoryDictionary Items 86 protected internal TaskInventoryDictionary Items
85 { 87 {
86 get { return m_items; } 88 get {
89 return m_items;
90 }
87 set 91 set
88 { 92 {
89 m_items = value; 93 m_items = value;
@@ -119,39 +123,45 @@ namespace OpenSim.Region.Framework.Scenes
119 /// <param name="linkNum">Link number for the part</param> 123 /// <param name="linkNum">Link number for the part</param>
120 public void ResetInventoryIDs() 124 public void ResetInventoryIDs()
121 { 125 {
122 if (null == m_part || null == m_part.ParentGroup) 126 m_items.LockItemsForWrite(true);
123 return; 127
124 128 if (Items.Count == 0)
125 lock (m_items)
126 { 129 {
127 if (0 == m_items.Count) 130 m_items.LockItemsForWrite(false);
128 return; 131 return;
132 }
129 133
130 IList<TaskInventoryItem> items = GetInventoryItems(); 134 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
131 m_items.Clear(); 135 Items.Clear();
132 136
133 foreach (TaskInventoryItem item in items) 137 foreach (TaskInventoryItem item in items)
134 { 138 {
135 item.ResetIDs(m_part.UUID); 139 item.ResetIDs(m_part.UUID);
136 m_items.Add(item.ItemID, item); 140 Items.Add(item.ItemID, item);
137 }
138 } 141 }
142 m_items.LockItemsForWrite(false);
139 } 143 }
140 144
141 public void ResetObjectID() 145 public void ResetObjectID()
142 { 146 {
143 lock (Items) 147 m_items.LockItemsForWrite(true);
148
149 if (Items.Count == 0)
144 { 150 {
145 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 151 m_items.LockItemsForWrite(false);
146 Items.Clear(); 152 return;
147
148 foreach (TaskInventoryItem item in items)
149 {
150 item.ParentPartID = m_part.UUID;
151 item.ParentID = m_part.UUID;
152 Items.Add(item.ItemID, item);
153 }
154 } 153 }
154
155 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
156 Items.Clear();
157
158 foreach (TaskInventoryItem item in items)
159 {
160 item.ParentPartID = m_part.UUID;
161 item.ParentID = m_part.UUID;
162 Items.Add(item.ItemID, item);
163 }
164 m_items.LockItemsForWrite(false);
155 } 165 }
156 166
157 /// <summary> 167 /// <summary>
@@ -160,12 +170,11 @@ namespace OpenSim.Region.Framework.Scenes
160 /// <param name="ownerId"></param> 170 /// <param name="ownerId"></param>
161 public void ChangeInventoryOwner(UUID ownerId) 171 public void ChangeInventoryOwner(UUID ownerId)
162 { 172 {
163 lock (Items) 173 m_items.LockItemsForWrite(true);
174 if (0 == Items.Count)
164 { 175 {
165 if (0 == Items.Count) 176 m_items.LockItemsForWrite(false);
166 { 177 return;
167 return;
168 }
169 } 178 }
170 179
171 HasInventoryChanged = true; 180 HasInventoryChanged = true;
@@ -179,6 +188,7 @@ namespace OpenSim.Region.Framework.Scenes
179 item.OwnerID = ownerId; 188 item.OwnerID = ownerId;
180 } 189 }
181 } 190 }
191 m_items.LockItemsForWrite(false);
182 } 192 }
183 193
184 /// <summary> 194 /// <summary>
@@ -187,12 +197,11 @@ namespace OpenSim.Region.Framework.Scenes
187 /// <param name="groupID"></param> 197 /// <param name="groupID"></param>
188 public void ChangeInventoryGroup(UUID groupID) 198 public void ChangeInventoryGroup(UUID groupID)
189 { 199 {
190 lock (Items) 200 m_items.LockItemsForWrite(true);
201 if (0 == Items.Count)
191 { 202 {
192 if (0 == Items.Count) 203 m_items.LockItemsForWrite(false);
193 { 204 return;
194 return;
195 }
196 } 205 }
197 206
198 // Don't let this set the HasGroupChanged flag for attachments 207 // Don't let this set the HasGroupChanged flag for attachments
@@ -204,12 +213,15 @@ namespace OpenSim.Region.Framework.Scenes
204 m_part.ParentGroup.HasGroupChanged = true; 213 m_part.ParentGroup.HasGroupChanged = true;
205 } 214 }
206 215
207 List<TaskInventoryItem> items = GetInventoryItems(); 216 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
208 foreach (TaskInventoryItem item in items) 217 foreach (TaskInventoryItem item in items)
209 { 218 {
210 if (groupID != item.GroupID) 219 if (groupID != item.GroupID)
220 {
211 item.GroupID = groupID; 221 item.GroupID = groupID;
222 }
212 } 223 }
224 m_items.LockItemsForWrite(false);
213 } 225 }
214 226
215 /// <summary> 227 /// <summary>
@@ -217,9 +229,14 @@ namespace OpenSim.Region.Framework.Scenes
217 /// </summary> 229 /// </summary>
218 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 230 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
219 { 231 {
220 List<TaskInventoryItem> scripts = GetInventoryScripts(); 232 Items.LockItemsForRead(true);
221 foreach (TaskInventoryItem item in scripts) 233 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
222 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 234 Items.LockItemsForRead(false);
235 foreach (TaskInventoryItem item in items)
236 {
237 if ((int)InventoryType.LSL == item.InvType)
238 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
239 }
223 } 240 }
224 241
225 public ArrayList GetScriptErrors(UUID itemID) 242 public ArrayList GetScriptErrors(UUID itemID)
@@ -252,9 +269,18 @@ namespace OpenSim.Region.Framework.Scenes
252 /// </param> 269 /// </param>
253 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 270 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
254 { 271 {
255 List<TaskInventoryItem> scripts = GetInventoryScripts(); 272 Items.LockItemsForRead(true);
256 foreach (TaskInventoryItem item in scripts) 273 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
257 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 274 Items.LockItemsForRead(false);
275
276 foreach (TaskInventoryItem item in items)
277 {
278 if ((int)InventoryType.LSL == item.InvType)
279 {
280 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
281 m_part.RemoveScriptEvents(item.ItemID);
282 }
283 }
258 } 284 }
259 285
260 /// <summary> 286 /// <summary>
@@ -270,7 +296,10 @@ namespace OpenSim.Region.Framework.Scenes
270 // item.Name, item.ItemID, Name, UUID); 296 // item.Name, item.ItemID, Name, UUID);
271 297
272 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 298 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
299 {
300 StoreScriptError(item.ItemID, "no permission");
273 return; 301 return;
302 }
274 303
275 m_part.AddFlag(PrimFlags.Scripted); 304 m_part.AddFlag(PrimFlags.Scripted);
276 305
@@ -279,14 +308,13 @@ namespace OpenSim.Region.Framework.Scenes
279 if (stateSource == 2 && // Prim crossing 308 if (stateSource == 2 && // Prim crossing
280 m_part.ParentGroup.Scene.m_trustBinaries) 309 m_part.ParentGroup.Scene.m_trustBinaries)
281 { 310 {
282 lock (m_items) 311 m_items.LockItemsForWrite(true);
283 { 312 m_items[item.ItemID].PermsMask = 0;
284 m_items[item.ItemID].PermsMask = 0; 313 m_items[item.ItemID].PermsGranter = UUID.Zero;
285 m_items[item.ItemID].PermsGranter = UUID.Zero; 314 m_items.LockItemsForWrite(false);
286 }
287
288 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 315 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
289 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 316 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
317 StoreScriptErrors(item.ItemID, null);
290 m_part.ParentGroup.AddActiveScriptCount(1); 318 m_part.ParentGroup.AddActiveScriptCount(1);
291 m_part.ScheduleFullUpdate(); 319 m_part.ScheduleFullUpdate();
292 return; 320 return;
@@ -295,6 +323,8 @@ namespace OpenSim.Region.Framework.Scenes
295 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 323 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
296 if (null == asset) 324 if (null == asset)
297 { 325 {
326 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
327 StoreScriptError(item.ItemID, msg);
298 m_log.ErrorFormat( 328 m_log.ErrorFormat(
299 "[PRIM INVENTORY]: " + 329 "[PRIM INVENTORY]: " +
300 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 330 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -306,15 +336,17 @@ namespace OpenSim.Region.Framework.Scenes
306 if (m_part.ParentGroup.m_savedScriptState != null) 336 if (m_part.ParentGroup.m_savedScriptState != null)
307 RestoreSavedScriptState(item.OldItemID, item.ItemID); 337 RestoreSavedScriptState(item.OldItemID, item.ItemID);
308 338
309 lock (m_items) 339 m_items.LockItemsForWrite(true);
310 { 340
311 m_items[item.ItemID].PermsMask = 0; 341 m_items[item.ItemID].PermsMask = 0;
312 m_items[item.ItemID].PermsGranter = UUID.Zero; 342 m_items[item.ItemID].PermsGranter = UUID.Zero;
313 } 343
344 m_items.LockItemsForWrite(false);
314 345
315 string script = Utils.BytesToString(asset.Data); 346 string script = Utils.BytesToString(asset.Data);
316 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 347 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
317 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 348 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
349 StoreScriptErrors(item.ItemID, null);
318 m_part.ParentGroup.AddActiveScriptCount(1); 350 m_part.ParentGroup.AddActiveScriptCount(1);
319 m_part.ScheduleFullUpdate(); 351 m_part.ScheduleFullUpdate();
320 } 352 }
@@ -378,21 +410,145 @@ namespace OpenSim.Region.Framework.Scenes
378 410
379 /// <summary> 411 /// <summary>
380 /// Start a script which is in this prim's inventory. 412 /// Start a script which is in this prim's inventory.
413 /// Some processing may occur in the background, but this routine returns asap.
381 /// </summary> 414 /// </summary>
382 /// <param name="itemId"> 415 /// <param name="itemId">
383 /// A <see cref="UUID"/> 416 /// A <see cref="UUID"/>
384 /// </param> 417 /// </param>
385 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 418 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
386 { 419 {
387 TaskInventoryItem item = GetInventoryItem(itemId); 420 lock (m_scriptErrors)
388 if (item != null) 421 {
389 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 422 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
423 m_scriptErrors.Remove(itemId);
424 }
425 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
426 }
427
428 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
429 {
430 m_items.LockItemsForRead(true);
431 if (m_items.ContainsKey(itemId))
432 {
433 if (m_items.ContainsKey(itemId))
434 {
435 m_items.LockItemsForRead(false);
436 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
437 }
438 else
439 {
440 m_items.LockItemsForRead(false);
441 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
442 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
443 StoreScriptError(itemId, msg);
444 m_log.ErrorFormat(
445 "[PRIM INVENTORY]: " +
446 "Couldn't start script with ID {0} since it {1}", itemId, msg);
447 }
448 }
390 else 449 else
450 {
451 m_items.LockItemsForRead(false);
452 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
453 StoreScriptError(itemId, msg);
391 m_log.ErrorFormat( 454 m_log.ErrorFormat(
392 "[PRIM INVENTORY]: " + 455 "[PRIM INVENTORY]: " +
393 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 456 "Couldn't start script with ID {0} since it {1}", itemId, msg);
394 itemId, m_part.Name, m_part.UUID, 457 }
395 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 458
459 }
460
461 /// <summary>
462 /// Start a script which is in this prim's inventory and return any compilation error messages.
463 /// </summary>
464 /// <param name="itemId">
465 /// A <see cref="UUID"/>
466 /// </param>
467 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
468 {
469 ArrayList errors;
470
471 // Indicate to CreateScriptInstanceInternal() we want it to
472 // post any compilation/loading error messages
473 lock (m_scriptErrors)
474 {
475 m_scriptErrors[itemId] = null;
476 }
477
478 // Perform compilation/loading
479 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
480
481 // Wait for and retrieve any errors
482 lock (m_scriptErrors)
483 {
484 while ((errors = m_scriptErrors[itemId]) == null)
485 {
486 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
487 {
488 m_log.ErrorFormat(
489 "[PRIM INVENTORY]: " +
490 "timedout waiting for script {0} errors", itemId);
491 errors = m_scriptErrors[itemId];
492 if (errors == null)
493 {
494 errors = new ArrayList(1);
495 errors.Add("timedout waiting for errors");
496 }
497 break;
498 }
499 }
500 m_scriptErrors.Remove(itemId);
501 }
502 return errors;
503 }
504
505 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
506 private void StoreScriptErrors(UUID itemId, ArrayList errors)
507 {
508 lock (m_scriptErrors)
509 {
510 // If compilation/loading initiated via CreateScriptInstance(),
511 // it does not want the errors, so just get out
512 if (!m_scriptErrors.ContainsKey(itemId))
513 {
514 return;
515 }
516
517 // Initiated via CreateScriptInstanceEr(), if we know what the
518 // errors are, save them and wake CreateScriptInstanceEr().
519 if (errors != null)
520 {
521 m_scriptErrors[itemId] = errors;
522 System.Threading.Monitor.PulseAll(m_scriptErrors);
523 return;
524 }
525 }
526
527 // Initiated via CreateScriptInstanceEr() but we don't know what
528 // the errors are yet, so retrieve them from the script engine.
529 // This may involve some waiting internal to GetScriptErrors().
530 errors = GetScriptErrors(itemId);
531
532 // Get a default non-null value to indicate success.
533 if (errors == null)
534 {
535 errors = new ArrayList();
536 }
537
538 // Post to CreateScriptInstanceEr() and wake it up
539 lock (m_scriptErrors)
540 {
541 m_scriptErrors[itemId] = errors;
542 System.Threading.Monitor.PulseAll(m_scriptErrors);
543 }
544 }
545
546 // Like StoreScriptErrors(), but just posts a single string message
547 private void StoreScriptError(UUID itemId, string message)
548 {
549 ArrayList errors = new ArrayList(1);
550 errors.Add(message);
551 StoreScriptErrors(itemId, errors);
396 } 552 }
397 553
398 /// <summary> 554 /// <summary>
@@ -405,15 +561,7 @@ namespace OpenSim.Region.Framework.Scenes
405 /// </param> 561 /// </param>
406 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 562 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
407 { 563 {
408 bool scriptPresent = false; 564 if (m_items.ContainsKey(itemId))
409
410 lock (m_items)
411 {
412 if (m_items.ContainsKey(itemId))
413 scriptPresent = true;
414 }
415
416 if (scriptPresent)
417 { 565 {
418 if (!sceneObjectBeingDeleted) 566 if (!sceneObjectBeingDeleted)
419 m_part.RemoveScriptEvents(itemId); 567 m_part.RemoveScriptEvents(itemId);
@@ -438,14 +586,16 @@ namespace OpenSim.Region.Framework.Scenes
438 /// <returns></returns> 586 /// <returns></returns>
439 private bool InventoryContainsName(string name) 587 private bool InventoryContainsName(string name)
440 { 588 {
441 lock (m_items) 589 m_items.LockItemsForRead(true);
590 foreach (TaskInventoryItem item in m_items.Values)
442 { 591 {
443 foreach (TaskInventoryItem item in m_items.Values) 592 if (item.Name == name)
444 { 593 {
445 if (item.Name == name) 594 m_items.LockItemsForRead(false);
446 return true; 595 return true;
447 } 596 }
448 } 597 }
598 m_items.LockItemsForRead(false);
449 return false; 599 return false;
450 } 600 }
451 601
@@ -487,8 +637,9 @@ namespace OpenSim.Region.Framework.Scenes
487 /// <param name="item"></param> 637 /// <param name="item"></param>
488 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 638 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
489 { 639 {
490 List<TaskInventoryItem> il = GetInventoryItems(); 640 m_items.LockItemsForRead(true);
491 641 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
642 m_items.LockItemsForRead(false);
492 foreach (TaskInventoryItem i in il) 643 foreach (TaskInventoryItem i in il)
493 { 644 {
494 if (i.Name == item.Name) 645 if (i.Name == item.Name)
@@ -526,14 +677,14 @@ namespace OpenSim.Region.Framework.Scenes
526 item.Name = name; 677 item.Name = name;
527 item.GroupID = m_part.GroupID; 678 item.GroupID = m_part.GroupID;
528 679
529 lock (m_items) 680 m_items.LockItemsForWrite(true);
530 m_items.Add(item.ItemID, item); 681 m_items.Add(item.ItemID, item);
531 682 m_items.LockItemsForWrite(false);
532 if (allowedDrop) 683 if (allowedDrop)
533 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 684 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
534 else 685 else
535 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 686 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
536 687
537 m_inventorySerial++; 688 m_inventorySerial++;
538 //m_inventorySerial += 2; 689 //m_inventorySerial += 2;
539 HasInventoryChanged = true; 690 HasInventoryChanged = true;
@@ -549,15 +700,15 @@ namespace OpenSim.Region.Framework.Scenes
549 /// <param name="items"></param> 700 /// <param name="items"></param>
550 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 701 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
551 { 702 {
552 lock (m_items) 703 m_items.LockItemsForWrite(true);
704 foreach (TaskInventoryItem item in items)
553 { 705 {
554 foreach (TaskInventoryItem item in items) 706 m_items.Add(item.ItemID, item);
555 { 707// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
556 m_items.Add(item.ItemID, item);
557// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
558 }
559 m_inventorySerial++;
560 } 708 }
709 m_items.LockItemsForWrite(false);
710
711 m_inventorySerial++;
561 } 712 }
562 713
563 /// <summary> 714 /// <summary>
@@ -568,10 +719,9 @@ namespace OpenSim.Region.Framework.Scenes
568 public TaskInventoryItem GetInventoryItem(UUID itemId) 719 public TaskInventoryItem GetInventoryItem(UUID itemId)
569 { 720 {
570 TaskInventoryItem item; 721 TaskInventoryItem item;
571 722 m_items.LockItemsForRead(true);
572 lock (m_items) 723 m_items.TryGetValue(itemId, out item);
573 m_items.TryGetValue(itemId, out item); 724 m_items.LockItemsForRead(false);
574
575 return item; 725 return item;
576 } 726 }
577 727
@@ -587,15 +737,16 @@ namespace OpenSim.Region.Framework.Scenes
587 { 737 {
588 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 738 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
589 739
590 lock (m_items) 740 m_items.LockItemsForRead(true);
741
742 foreach (TaskInventoryItem item in m_items.Values)
591 { 743 {
592 foreach (TaskInventoryItem item in m_items.Values) 744 if (item.Name == name)
593 { 745 items.Add(item);
594 if (item.Name == name)
595 items.Add(item);
596 }
597 } 746 }
598 747
748 m_items.LockItemsForRead(false);
749
599 return items; 750 return items;
600 } 751 }
601 752
@@ -678,9 +829,9 @@ namespace OpenSim.Region.Framework.Scenes
678 829
679 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 830 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
680 { 831 {
681 TaskInventoryItem it = GetInventoryItem(item.ItemID); 832 m_items.LockItemsForWrite(true);
682 if (it != null)
683 833
834 if (m_items.ContainsKey(item.ItemID))
684 { 835 {
685 item.ParentID = m_part.UUID; 836 item.ParentID = m_part.UUID;
686 item.ParentPartID = m_part.UUID; 837 item.ParentPartID = m_part.UUID;
@@ -692,14 +843,10 @@ namespace OpenSim.Region.Framework.Scenes
692 item.GroupID = m_part.GroupID; 843 item.GroupID = m_part.GroupID;
693 844
694 if (item.AssetID == UUID.Zero) 845 if (item.AssetID == UUID.Zero)
695 item.AssetID = it.AssetID; 846 item.AssetID = m_items[item.ItemID].AssetID;
696
697 lock (m_items)
698 {
699 m_items[item.ItemID] = item;
700 m_inventorySerial++;
701 }
702 847
848 m_items[item.ItemID] = item;
849 m_inventorySerial++;
703 if (fireScriptEvents) 850 if (fireScriptEvents)
704 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 851 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
705 if (considerChanged) 852 if (considerChanged)
@@ -707,6 +854,7 @@ namespace OpenSim.Region.Framework.Scenes
707 HasInventoryChanged = true; 854 HasInventoryChanged = true;
708 m_part.ParentGroup.HasGroupChanged = true; 855 m_part.ParentGroup.HasGroupChanged = true;
709 } 856 }
857 m_items.LockItemsForWrite(false);
710 return true; 858 return true;
711 } 859 }
712 else 860 else
@@ -717,8 +865,9 @@ namespace OpenSim.Region.Framework.Scenes
717 item.ItemID, m_part.Name, m_part.UUID, 865 item.ItemID, m_part.Name, m_part.UUID,
718 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 866 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
719 } 867 }
720 return false; 868 m_items.LockItemsForWrite(false);
721 869
870 return false;
722 } 871 }
723 872
724 /// <summary> 873 /// <summary>
@@ -729,37 +878,53 @@ namespace OpenSim.Region.Framework.Scenes
729 /// in this prim's inventory.</returns> 878 /// in this prim's inventory.</returns>
730 public int RemoveInventoryItem(UUID itemID) 879 public int RemoveInventoryItem(UUID itemID)
731 { 880 {
732 TaskInventoryItem item = GetInventoryItem(itemID); 881 m_items.LockItemsForRead(true);
733 if (item != null) 882
883 if (m_items.ContainsKey(itemID))
734 { 884 {
735 int type = m_items[itemID].InvType; 885 int type = m_items[itemID].InvType;
886 m_items.LockItemsForRead(false);
736 if (type == 10) // Script 887 if (type == 10) // Script
737 { 888 {
738 m_part.RemoveScriptEvents(itemID);
739 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 889 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
740 } 890 }
891 m_items.LockItemsForWrite(true);
741 m_items.Remove(itemID); 892 m_items.Remove(itemID);
893 m_items.LockItemsForWrite(false);
742 m_inventorySerial++; 894 m_inventorySerial++;
743 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 895 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
744 896
745 HasInventoryChanged = true; 897 HasInventoryChanged = true;
746 m_part.ParentGroup.HasGroupChanged = true; 898 m_part.ParentGroup.HasGroupChanged = true;
747 899
748 if (!ContainsScripts()) 900 int scriptcount = 0;
901 m_items.LockItemsForRead(true);
902 foreach (TaskInventoryItem item in m_items.Values)
903 {
904 if (item.Type == 10)
905 {
906 scriptcount++;
907 }
908 }
909 m_items.LockItemsForRead(false);
910
911
912 if (scriptcount <= 0)
913 {
749 m_part.RemFlag(PrimFlags.Scripted); 914 m_part.RemFlag(PrimFlags.Scripted);
915 }
750 916
751 m_part.ScheduleFullUpdate(); 917 m_part.ScheduleFullUpdate();
752 918
753 return type; 919 return type;
754
755 } 920 }
756 else 921 else
757 { 922 {
923 m_items.LockItemsForRead(false);
758 m_log.ErrorFormat( 924 m_log.ErrorFormat(
759 "[PRIM INVENTORY]: " + 925 "[PRIM INVENTORY]: " +
760 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 926 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
761 itemID, m_part.Name, m_part.UUID, 927 itemID, m_part.Name, m_part.UUID);
762 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
763 } 928 }
764 929
765 return -1; 930 return -1;
@@ -867,6 +1032,8 @@ namespace OpenSim.Region.Framework.Scenes
867 invString.AddSectionEnd(); 1032 invString.AddSectionEnd();
868 } 1033 }
869 } 1034 }
1035 int count = m_items.Count;
1036 m_items.LockItemsForRead(false);
870 1037
871 fileData = Utils.StringToBytes(invString.BuildString); 1038 fileData = Utils.StringToBytes(invString.BuildString);
872 1039
@@ -887,10 +1054,11 @@ namespace OpenSim.Region.Framework.Scenes
887 { 1054 {
888 if (HasInventoryChanged) 1055 if (HasInventoryChanged)
889 { 1056 {
890 HasInventoryChanged = false; 1057 Items.LockItemsForRead(true);
891 List<TaskInventoryItem> items = GetInventoryItems(); 1058 datastore.StorePrimInventory(m_part.UUID, Items.Values);
892 datastore.StorePrimInventory(m_part.UUID, items); 1059 Items.LockItemsForRead(false);
893 1060
1061 HasInventoryChanged = false;
894 } 1062 }
895 } 1063 }
896 1064
@@ -957,89 +1125,75 @@ namespace OpenSim.Region.Framework.Scenes
957 { 1125 {
958 uint mask=0x7fffffff; 1126 uint mask=0x7fffffff;
959 1127
960 lock (m_items) 1128 foreach (TaskInventoryItem item in m_items.Values)
961 { 1129 {
962 foreach (TaskInventoryItem item in m_items.Values) 1130 if (item.InvType != (int)InventoryType.Object)
963 { 1131 {
964 if (item.InvType != (int)InventoryType.Object) 1132 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
965 { 1133 mask &= ~((uint)PermissionMask.Copy >> 13);
966 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1134 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
967 mask &= ~((uint)PermissionMask.Copy >> 13); 1135 mask &= ~((uint)PermissionMask.Transfer >> 13);
968 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1136 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
969 mask &= ~((uint)PermissionMask.Transfer >> 13); 1137 mask &= ~((uint)PermissionMask.Modify >> 13);
970 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1138 }
971 mask &= ~((uint)PermissionMask.Modify >> 13); 1139 else
972 } 1140 {
973 else 1141 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
974 { 1142 mask &= ~((uint)PermissionMask.Copy >> 13);
975 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1143 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
976 mask &= ~((uint)PermissionMask.Copy >> 13); 1144 mask &= ~((uint)PermissionMask.Transfer >> 13);
977 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1145 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
978 mask &= ~((uint)PermissionMask.Transfer >> 13); 1146 mask &= ~((uint)PermissionMask.Modify >> 13);
979 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
980 mask &= ~((uint)PermissionMask.Modify >> 13);
981 }
982
983 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
984 mask &= ~(uint)PermissionMask.Copy;
985 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
986 mask &= ~(uint)PermissionMask.Transfer;
987 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
988 mask &= ~(uint)PermissionMask.Modify;
989 } 1147 }
1148
1149 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1150 mask &= ~(uint)PermissionMask.Copy;
1151 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1152 mask &= ~(uint)PermissionMask.Transfer;
1153 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1154 mask &= ~(uint)PermissionMask.Modify;
990 } 1155 }
991
992 return mask; 1156 return mask;
993 } 1157 }
994 1158
995 public void ApplyNextOwnerPermissions() 1159 public void ApplyNextOwnerPermissions()
996 { 1160 {
997 lock (m_items) 1161 foreach (TaskInventoryItem item in m_items.Values)
998 { 1162 {
999 foreach (TaskInventoryItem item in m_items.Values) 1163 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1000 { 1164 {
1001 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1165 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1002 { 1166 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1003 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1167 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1004 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1168 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1005 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1169 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1006 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1170 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1007 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1008 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1009 }
1010 item.CurrentPermissions &= item.NextPermissions;
1011 item.BasePermissions &= item.NextPermissions;
1012 item.EveryonePermissions &= item.NextPermissions;
1013 item.OwnerChanged = true;
1014 } 1171 }
1172 item.OwnerChanged = true;
1173 item.CurrentPermissions &= item.NextPermissions;
1174 item.BasePermissions &= item.NextPermissions;
1175 item.EveryonePermissions &= item.NextPermissions;
1015 } 1176 }
1016 } 1177 }
1017 1178
1018 public void ApplyGodPermissions(uint perms) 1179 public void ApplyGodPermissions(uint perms)
1019 { 1180 {
1020 lock (m_items) 1181 foreach (TaskInventoryItem item in m_items.Values)
1021 { 1182 {
1022 foreach (TaskInventoryItem item in m_items.Values) 1183 item.CurrentPermissions = perms;
1023 { 1184 item.BasePermissions = perms;
1024 item.CurrentPermissions = perms;
1025 item.BasePermissions = perms;
1026 }
1027 } 1185 }
1028 } 1186 }
1029 1187
1030 public bool ContainsScripts() 1188 public bool ContainsScripts()
1031 { 1189 {
1032 lock (m_items) 1190 foreach (TaskInventoryItem item in m_items.Values)
1033 { 1191 {
1034 foreach (TaskInventoryItem item in m_items.Values) 1192 if (item.InvType == (int)InventoryType.LSL)
1035 { 1193 {
1036 if (item.InvType == (int)InventoryType.LSL) 1194 return true;
1037 {
1038 return true;
1039 }
1040 } 1195 }
1041 } 1196 }
1042
1043 return false; 1197 return false;
1044 } 1198 }
1045 1199
@@ -1047,11 +1201,8 @@ namespace OpenSim.Region.Framework.Scenes
1047 { 1201 {
1048 List<UUID> ret = new List<UUID>(); 1202 List<UUID> ret = new List<UUID>();
1049 1203
1050 lock (m_items) 1204 foreach (TaskInventoryItem item in m_items.Values)
1051 { 1205 ret.Add(item.ItemID);
1052 foreach (TaskInventoryItem item in m_items.Values)
1053 ret.Add(item.ItemID);
1054 }
1055 1206
1056 return ret; 1207 return ret;
1057 } 1208 }
@@ -1082,31 +1233,46 @@ namespace OpenSim.Region.Framework.Scenes
1082 1233
1083 public Dictionary<UUID, string> GetScriptStates() 1234 public Dictionary<UUID, string> GetScriptStates()
1084 { 1235 {
1236 return GetScriptStates(false);
1237 }
1238
1239 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1240 {
1085 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 1241 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
1086 1242
1087 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1243 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1088 if (engines == null) // No engine at all 1244 if (engines == null) // No engine at all
1089 return ret; 1245 return ret;
1090 1246
1091 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1247 Items.LockItemsForRead(true);
1092 1248 foreach (TaskInventoryItem item in m_items.Values)
1093 foreach (TaskInventoryItem item in scripts)
1094 { 1249 {
1095 foreach (IScriptModule e in engines) 1250 if (item.InvType == (int)InventoryType.LSL)
1096 { 1251 {
1097 if (e != null) 1252 foreach (IScriptModule e in engines)
1098 { 1253 {
1099 string n = e.GetXMLState(item.ItemID); 1254 if (e != null)
1100 if (n != String.Empty)
1101 { 1255 {
1102 if (!ret.ContainsKey(item.ItemID)) 1256 string n = e.GetXMLState(item.ItemID);
1103 ret[item.ItemID] = n; 1257 if (n != String.Empty)
1104 break; 1258 {
1259 if (oldIDs)
1260 {
1261 if (!ret.ContainsKey(item.OldItemID))
1262 ret[item.OldItemID] = n;
1263 }
1264 else
1265 {
1266 if (!ret.ContainsKey(item.ItemID))
1267 ret[item.ItemID] = n;
1268 }
1269 break;
1270 }
1105 } 1271 }
1106 } 1272 }
1107 } 1273 }
1108 } 1274 }
1109 1275 Items.LockItemsForRead(false);
1110 return ret; 1276 return ret;
1111 } 1277 }
1112 1278
@@ -1116,21 +1282,27 @@ namespace OpenSim.Region.Framework.Scenes
1116 if (engines == null) 1282 if (engines == null)
1117 return; 1283 return;
1118 1284
1119 List<TaskInventoryItem> scripts = GetInventoryScripts();
1120 1285
1121 foreach (TaskInventoryItem item in scripts) 1286 Items.LockItemsForRead(true);
1287
1288 foreach (TaskInventoryItem item in m_items.Values)
1122 { 1289 {
1123 foreach (IScriptModule engine in engines) 1290 if (item.InvType == (int)InventoryType.LSL)
1124 { 1291 {
1125 if (engine != null) 1292 foreach (IScriptModule engine in engines)
1126 { 1293 {
1127 if (item.OwnerChanged) 1294 if (engine != null)
1128 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1295 {
1129 item.OwnerChanged = false; 1296 if (item.OwnerChanged)
1130 engine.ResumeScript(item.ItemID); 1297 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1298 item.OwnerChanged = false;
1299 engine.ResumeScript(item.ItemID);
1300 }
1131 } 1301 }
1132 } 1302 }
1133 } 1303 }
1304
1305 Items.LockItemsForRead(false);
1134 } 1306 }
1135 } 1307 }
1136} 1308}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index bfc1bd6..b340bda 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[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 79// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
@@ -87,7 +88,9 @@ namespace OpenSim.Region.Framework.Scenes
87 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 88 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
88 /// issue #1716 89 /// issue #1716
89 /// </summary> 90 /// </summary>
90 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); 91// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
92 // Value revised by KF 091121 by comparison with SL.
93 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
91 94
92 public UUID currentParcelUUID = UUID.Zero; 95 public UUID currentParcelUUID = UUID.Zero;
93 96
@@ -121,8 +124,11 @@ namespace OpenSim.Region.Framework.Scenes
121 public Vector3 lastKnownAllowedPosition; 124 public Vector3 lastKnownAllowedPosition;
122 public bool sentMessageAboutRestrictedParcelFlyingDown; 125 public bool sentMessageAboutRestrictedParcelFlyingDown;
123 public Vector4 CollisionPlane = Vector4.UnitW; 126 public Vector4 CollisionPlane = Vector4.UnitW;
124 127
128 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
129 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
125 private Vector3 m_lastPosition; 130 private Vector3 m_lastPosition;
131 private Vector3 m_lastWorldPosition;
126 private Quaternion m_lastRotation; 132 private Quaternion m_lastRotation;
127 private Vector3 m_lastVelocity; 133 private Vector3 m_lastVelocity;
128 //private int m_lastTerseSent; 134 //private int m_lastTerseSent;
@@ -153,9 +159,10 @@ namespace OpenSim.Region.Framework.Scenes
153 private int m_perfMonMS; 159 private int m_perfMonMS;
154 160
155 private bool m_setAlwaysRun; 161 private bool m_setAlwaysRun;
156
157 private bool m_forceFly; 162 private bool m_forceFly;
158 private bool m_flyDisabled; 163 private bool m_flyDisabled;
164 private bool m_flyingOld; // add for fly velocity control
165 public bool m_wasFlying; // add for fly velocity control
159 166
160 private float m_speedModifier = 1.0f; 167 private float m_speedModifier = 1.0f;
161 168
@@ -174,7 +181,8 @@ namespace OpenSim.Region.Framework.Scenes
174 protected RegionInfo m_regionInfo; 181 protected RegionInfo m_regionInfo;
175 protected ulong crossingFromRegion; 182 protected ulong crossingFromRegion;
176 183
177 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 184 private readonly Vector3[] Dir_Vectors = new Vector3[11];
185 private bool m_isNudging = false;
178 186
179 // Position of agent's camera in world (region cordinates) 187 // Position of agent's camera in world (region cordinates)
180 protected Vector3 m_CameraCenter; 188 protected Vector3 m_CameraCenter;
@@ -199,17 +207,25 @@ namespace OpenSim.Region.Framework.Scenes
199 private bool m_autopilotMoving; 207 private bool m_autopilotMoving;
200 private Vector3 m_autoPilotTarget; 208 private Vector3 m_autoPilotTarget;
201 private bool m_sitAtAutoTarget; 209 private bool m_sitAtAutoTarget;
210 private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
202 211
203 private string m_nextSitAnimation = String.Empty; 212 private string m_nextSitAnimation = String.Empty;
204 213
205 //PauPaw:Proper PID Controler for autopilot************ 214 //PauPaw:Proper PID Controler for autopilot************
206 private bool m_moveToPositionInProgress; 215 private bool m_moveToPositionInProgress;
207 private Vector3 m_moveToPositionTarget; 216 private Vector3 m_moveToPositionTarget;
217 private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
208 218
209 private bool m_followCamAuto; 219 private bool m_followCamAuto;
210 220
211 private int m_movementUpdateCount; 221 private int m_movementUpdateCount;
222 private int m_lastColCount = -1; //KF: Look for Collision chnages
223 private int m_updateCount = 0; //KF: Update Anims for a while
224 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
212 private const int NumMovementsBetweenRayCast = 5; 225 private const int NumMovementsBetweenRayCast = 5;
226 private List<uint> m_lastColliders = new List<uint>();
227
228 private object m_syncRoot = new Object();
213 229
214 private bool CameraConstraintActive; 230 private bool CameraConstraintActive;
215 //private int m_moveToPositionStateStatus; 231 //private int m_moveToPositionStateStatus;
@@ -236,7 +252,9 @@ namespace OpenSim.Region.Framework.Scenes
236 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 252 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
237 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 253 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
238 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 254 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
239 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 255 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
256 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
257 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
240 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 258 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
241 } 259 }
242 260
@@ -443,9 +461,18 @@ namespace OpenSim.Region.Framework.Scenes
443 get 461 get
444 { 462 {
445 PhysicsActor actor = m_physicsActor; 463 PhysicsActor actor = m_physicsActor;
446 if (actor != null) 464// if (actor != null)
465 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
447 m_pos = actor.Position; 466 m_pos = actor.Position;
448 467
468 // If we're sitting, we need to update our position
469 if (m_parentID != 0)
470 {
471 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
472 if (part != null)
473 m_parentPosition = part.AbsolutePosition;
474 }
475
449 return m_parentPosition + m_pos; 476 return m_parentPosition + m_pos;
450 } 477 }
451 set 478 set
@@ -464,7 +491,8 @@ namespace OpenSim.Region.Framework.Scenes
464 } 491 }
465 } 492 }
466 493
467 m_pos = value; 494 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
495 m_pos = value;
468 m_parentPosition = Vector3.Zero; 496 m_parentPosition = Vector3.Zero;
469 } 497 }
470 } 498 }
@@ -508,10 +536,39 @@ namespace OpenSim.Region.Framework.Scenes
508 } 536 }
509 } 537 }
510 538
539 public Quaternion OffsetRotation
540 {
541 get { return m_offsetRotation; }
542 set { m_offsetRotation = value; }
543 }
544
511 public Quaternion Rotation 545 public Quaternion Rotation
512 { 546 {
513 get { return m_bodyRot; } 547 get {
514 set { m_bodyRot = value; } 548 if (m_parentID != 0)
549 {
550 if (m_offsetRotation != null)
551 {
552 return m_offsetRotation;
553 }
554 else
555 {
556 return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
557 }
558
559 }
560 else
561 {
562 return m_bodyRot;
563 }
564 }
565 set {
566 m_bodyRot = value;
567 if (m_parentID != 0)
568 {
569 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
570 }
571 }
515 } 572 }
516 573
517 public Quaternion PreviousRotation 574 public Quaternion PreviousRotation
@@ -536,11 +593,21 @@ namespace OpenSim.Region.Framework.Scenes
536 593
537 private uint m_parentID; 594 private uint m_parentID;
538 595
596
597 private UUID m_linkedPrim;
598
539 public uint ParentID 599 public uint ParentID
540 { 600 {
541 get { return m_parentID; } 601 get { return m_parentID; }
542 set { m_parentID = value; } 602 set { m_parentID = value; }
543 } 603 }
604
605 public UUID LinkedPrim
606 {
607 get { return m_linkedPrim; }
608 set { m_linkedPrim = value; }
609 }
610
544 public float Health 611 public float Health
545 { 612 {
546 get { return m_health; } 613 get { return m_health; }
@@ -662,7 +729,7 @@ namespace OpenSim.Region.Framework.Scenes
662 CreateSceneViewer(); 729 CreateSceneViewer();
663 m_animator = new ScenePresenceAnimator(this); 730 m_animator = new ScenePresenceAnimator(this);
664 } 731 }
665 732
666 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() 733 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
667 { 734 {
668 m_rootRegionHandle = reginfo.RegionHandle; 735 m_rootRegionHandle = reginfo.RegionHandle;
@@ -694,10 +761,7 @@ namespace OpenSim.Region.Framework.Scenes
694 m_reprioritization_timer.AutoReset = false; 761 m_reprioritization_timer.AutoReset = false;
695 762
696 AdjustKnownSeeds(); 763 AdjustKnownSeeds();
697
698 // TODO: I think, this won't send anything, as we are still a child here...
699 Animator.TrySetMovementAnimation("STAND"); 764 Animator.TrySetMovementAnimation("STAND");
700
701 // we created a new ScenePresence (a new child agent) in a fresh region. 765 // we created a new ScenePresence (a new child agent) in a fresh region.
702 // Request info about all the (root) agents in this region 766 // Request info about all the (root) agents in this region
703 // Note: This won't send data *to* other clients in that region (children don't send) 767 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -746,25 +810,47 @@ namespace OpenSim.Region.Framework.Scenes
746 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 810 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
747 Dir_Vectors[4] = Vector3.UnitZ; //UP 811 Dir_Vectors[4] = Vector3.UnitZ; //UP
748 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 812 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
749 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 813 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
750 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 814 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
751 Dir_Vectors[7] = -Vector3.UnitX; //BACK 815 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
816 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
817 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
752 } 818 }
753 819
754 private Vector3[] GetWalkDirectionVectors() 820 private Vector3[] GetWalkDirectionVectors()
755 { 821 {
756 Vector3[] vector = new Vector3[9]; 822 Vector3[] vector = new Vector3[11];
757 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 823 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
758 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 824 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
759 vector[2] = Vector3.UnitY; //LEFT 825 vector[2] = Vector3.UnitY; //LEFT
760 vector[3] = -Vector3.UnitY; //RIGHT 826 vector[3] = -Vector3.UnitY; //RIGHT
761 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 827 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
762 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 828 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
763 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 829 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
764 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 830 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
765 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 831 vector[8] = Vector3.UnitY; //LEFT_NUDGE
832 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
833 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
766 return vector; 834 return vector;
767 } 835 }
836
837 private bool[] GetDirectionIsNudge()
838 {
839 bool[] isNudge = new bool[11];
840 isNudge[0] = false; //FORWARD
841 isNudge[1] = false; //BACK
842 isNudge[2] = false; //LEFT
843 isNudge[3] = false; //RIGHT
844 isNudge[4] = false; //UP
845 isNudge[5] = false; //DOWN
846 isNudge[6] = true; //FORWARD_NUDGE
847 isNudge[7] = true; //BACK_NUDGE
848 isNudge[8] = true; //LEFT_NUDGE
849 isNudge[9] = true; //RIGHT_NUDGE
850 isNudge[10] = true; //DOWN_Nudge
851 return isNudge;
852 }
853
768 854
769 #endregion 855 #endregion
770 856
@@ -826,6 +912,52 @@ namespace OpenSim.Region.Framework.Scenes
826 pos.Y = crossedBorder.BorderLine.Z - 1; 912 pos.Y = crossedBorder.BorderLine.Z - 1;
827 } 913 }
828 914
915 //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
916 //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
917 //they'll bypass the landing point. But I can't think of any decent way of fixing this.
918 if (KnownChildRegionHandles.Count == 0)
919 {
920 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
921 if (land != null)
922 {
923 //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
924 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)
925 {
926 pos = land.LandData.UserLocation;
927 }
928 }
929 }
930
931 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
932 {
933 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
934
935 if (pos.X < 0)
936 {
937 emergencyPos.X = (int)Constants.RegionSize + pos.X;
938 if (!(pos.Y < 0))
939 emergencyPos.Y = pos.Y;
940 if (!(pos.Z < 0))
941 emergencyPos.Z = pos.Z;
942 }
943 if (pos.Y < 0)
944 {
945 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
946 if (!(pos.X < 0))
947 emergencyPos.X = pos.X;
948 if (!(pos.Z < 0))
949 emergencyPos.Z = pos.Z;
950 }
951 if (pos.Z < 0)
952 {
953 emergencyPos.Z = 128;
954 if (!(pos.Y < 0))
955 emergencyPos.Y = pos.Y;
956 if (!(pos.X < 0))
957 emergencyPos.X = pos.X;
958 }
959 }
960
829 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 961 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
830 { 962 {
831 m_log.WarnFormat( 963 m_log.WarnFormat(
@@ -954,12 +1086,17 @@ namespace OpenSim.Region.Framework.Scenes
954 { 1086 {
955 if (PhysicsActor != null) 1087 if (PhysicsActor != null)
956 { 1088 {
957 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1089 try
958 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; 1090 {
959 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1091 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
960 m_physicsActor.UnSubscribeEvents(); 1092 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
961 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1093 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
962 PhysicsActor = null; 1094 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1095 m_physicsActor.UnSubscribeEvents();
1096 PhysicsActor = null;
1097 }
1098 catch
1099 { }
963 } 1100 }
964 } 1101 }
965 1102
@@ -970,9 +1107,10 @@ namespace OpenSim.Region.Framework.Scenes
970 public void Teleport(Vector3 pos) 1107 public void Teleport(Vector3 pos)
971 { 1108 {
972 bool isFlying = false; 1109 bool isFlying = false;
1110
973 if (m_physicsActor != null) 1111 if (m_physicsActor != null)
974 isFlying = m_physicsActor.Flying; 1112 isFlying = m_physicsActor.Flying;
975 1113
976 RemoveFromPhysicalScene(); 1114 RemoveFromPhysicalScene();
977 Velocity = Vector3.Zero; 1115 Velocity = Vector3.Zero;
978 AbsolutePosition = pos; 1116 AbsolutePosition = pos;
@@ -984,6 +1122,7 @@ namespace OpenSim.Region.Framework.Scenes
984 } 1122 }
985 1123
986 SendTerseUpdateToAllClients(); 1124 SendTerseUpdateToAllClients();
1125
987 } 1126 }
988 1127
989 public void TeleportWithMomentum(Vector3 pos) 1128 public void TeleportWithMomentum(Vector3 pos)
@@ -1202,6 +1341,7 @@ namespace OpenSim.Region.Framework.Scenes
1202 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1341 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1203 1342
1204 m_pos = m_LastFinitePos; 1343 m_pos = m_LastFinitePos;
1344
1205 if (!m_pos.IsFinite()) 1345 if (!m_pos.IsFinite())
1206 { 1346 {
1207 m_pos.X = 127f; 1347 m_pos.X = 127f;
@@ -1268,7 +1408,6 @@ namespace OpenSim.Region.Framework.Scenes
1268 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1408 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1269 } 1409 }
1270 } 1410 }
1271
1272 lock (scriptedcontrols) 1411 lock (scriptedcontrols)
1273 { 1412 {
1274 if (scriptedcontrols.Count > 0) 1413 if (scriptedcontrols.Count > 0)
@@ -1283,6 +1422,9 @@ namespace OpenSim.Region.Framework.Scenes
1283 1422
1284 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1423 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1285 { 1424 {
1425 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1426 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1427
1286 // TODO: This doesn't prevent the user from walking yet. 1428 // TODO: This doesn't prevent the user from walking yet.
1287 // Setting parent ID would fix this, if we knew what value 1429 // Setting parent ID would fix this, if we knew what value
1288 // to use. Or we could add a m_isSitting variable. 1430 // to use. Or we could add a m_isSitting variable.
@@ -1331,12 +1473,20 @@ namespace OpenSim.Region.Framework.Scenes
1331 if (actor.Flying != oldflying) 1473 if (actor.Flying != oldflying)
1332 update_movementflag = true; 1474 update_movementflag = true;
1333 1475
1476 if (m_animator.m_jumping) // add for jumping
1477 update_movementflag = true;
1478
1334 if (q != m_bodyRot) 1479 if (q != m_bodyRot)
1335 { 1480 {
1336 m_bodyRot = q; 1481 m_bodyRot = q;
1337 update_rotation = true; 1482 update_rotation = true;
1338 } 1483 }
1339 1484
1485 //guilty until proven innocent..
1486 bool Nudging = true;
1487 //Basically, if there is at least one non-nudge control then we don't need
1488 //to worry about stopping the avatar
1489
1340 if (m_parentID == 0) 1490 if (m_parentID == 0)
1341 { 1491 {
1342 bool bAllowUpdateMoveToPosition = false; 1492 bool bAllowUpdateMoveToPosition = false;
@@ -1351,9 +1501,12 @@ namespace OpenSim.Region.Framework.Scenes
1351 else 1501 else
1352 dirVectors = Dir_Vectors; 1502 dirVectors = Dir_Vectors;
1353 1503
1354 // The fact that m_movementflag is a byte needs to be fixed 1504 bool[] isNudge = GetDirectionIsNudge();
1355 // it really should be a uint 1505
1356 uint nudgehack = 250; 1506
1507
1508
1509
1357 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1510 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1358 { 1511 {
1359 if (((uint)flags & (uint)DCF) != 0) 1512 if (((uint)flags & (uint)DCF) != 0)
@@ -1363,40 +1516,28 @@ namespace OpenSim.Region.Framework.Scenes
1363 try 1516 try
1364 { 1517 {
1365 agent_control_v3 += dirVectors[i]; 1518 agent_control_v3 += dirVectors[i];
1366 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1519 if (isNudge[i] == false)
1520 {
1521 Nudging = false;
1522 }
1367 } 1523 }
1368 catch (IndexOutOfRangeException) 1524 catch (IndexOutOfRangeException)
1369 { 1525 {
1370 // Why did I get this? 1526 // Why did I get this?
1371 } 1527 }
1372 1528
1373 if ((m_movementflag & (byte)(uint)DCF) == 0) 1529 if ((m_movementflag & (uint)DCF) == 0)
1374 { 1530 {
1375 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1376 {
1377 m_movementflag |= (byte)nudgehack;
1378 }
1379 m_movementflag += (byte)(uint)DCF; 1531 m_movementflag += (byte)(uint)DCF;
1380 update_movementflag = true; 1532 update_movementflag = true;
1381 } 1533 }
1382 } 1534 }
1383 else 1535 else
1384 { 1536 {
1385 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1537 if ((m_movementflag & (uint)DCF) != 0)
1386 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1387 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1388 ) // This or is for Nudge forward
1389 { 1538 {
1390 m_movementflag -= ((byte)(uint)DCF); 1539 m_movementflag -= (byte)(uint)DCF;
1391
1392 update_movementflag = true; 1540 update_movementflag = true;
1393 /*
1394 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1395 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1396 {
1397 m_log.Debug("Removed Hack flag");
1398 }
1399 */
1400 } 1541 }
1401 else 1542 else
1402 { 1543 {
@@ -1405,7 +1546,6 @@ namespace OpenSim.Region.Framework.Scenes
1405 } 1546 }
1406 i++; 1547 i++;
1407 } 1548 }
1408
1409 //Paupaw:Do Proper PID for Autopilot here 1549 //Paupaw:Do Proper PID for Autopilot here
1410 if (bResetMoveToPosition) 1550 if (bResetMoveToPosition)
1411 { 1551 {
@@ -1440,6 +1580,9 @@ namespace OpenSim.Region.Framework.Scenes
1440 // Ignore z component of vector 1580 // Ignore z component of vector
1441 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1581 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1442 LocalVectorToTarget2D.Normalize(); 1582 LocalVectorToTarget2D.Normalize();
1583
1584 //We're not nudging
1585 Nudging = false;
1443 agent_control_v3 += LocalVectorToTarget2D; 1586 agent_control_v3 += LocalVectorToTarget2D;
1444 1587
1445 // update avatar movement flags. the avatar coordinate system is as follows: 1588 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1530,13 +1673,13 @@ namespace OpenSim.Region.Framework.Scenes
1530 // m_log.DebugFormat( 1673 // m_log.DebugFormat(
1531 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1674 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1532 1675
1533 AddNewMovement(agent_control_v3, q); 1676 AddNewMovement(agent_control_v3, q, Nudging);
1534 1677
1535 1678
1536 } 1679 }
1537 } 1680 }
1538 1681
1539 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1682 if (update_movementflag && !SitGround)
1540 Animator.UpdateMovementAnimations(); 1683 Animator.UpdateMovementAnimations();
1541 1684
1542 m_scene.EventManager.TriggerOnClientMovement(this); 1685 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1551,7 +1694,6 @@ namespace OpenSim.Region.Framework.Scenes
1551 m_sitAtAutoTarget = false; 1694 m_sitAtAutoTarget = false;
1552 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1695 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1553 //proxy.PCode = (byte)PCode.ParticleSystem; 1696 //proxy.PCode = (byte)PCode.ParticleSystem;
1554
1555 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1697 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1556 proxyObjectGroup.AttachToScene(m_scene); 1698 proxyObjectGroup.AttachToScene(m_scene);
1557 1699
@@ -1593,7 +1735,7 @@ namespace OpenSim.Region.Framework.Scenes
1593 } 1735 }
1594 m_moveToPositionInProgress = true; 1736 m_moveToPositionInProgress = true;
1595 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1737 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1596 } 1738 }
1597 catch (Exception ex) 1739 catch (Exception ex)
1598 { 1740 {
1599 //Why did I get this error? 1741 //Why did I get this error?
@@ -1615,7 +1757,7 @@ namespace OpenSim.Region.Framework.Scenes
1615 Velocity = Vector3.Zero; 1757 Velocity = Vector3.Zero;
1616 SendFullUpdateToAllClients(); 1758 SendFullUpdateToAllClients();
1617 1759
1618 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1760 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1619 } 1761 }
1620 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1762 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1621 m_requestedSitTargetUUID = UUID.Zero; 1763 m_requestedSitTargetUUID = UUID.Zero;
@@ -1652,42 +1794,77 @@ namespace OpenSim.Region.Framework.Scenes
1652 1794
1653 if (m_parentID != 0) 1795 if (m_parentID != 0)
1654 { 1796 {
1655 m_log.Debug("StandupCode Executed"); 1797 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1656 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1657 if (part != null) 1798 if (part != null)
1658 { 1799 {
1800 part.TaskInventory.LockItemsForRead(true);
1659 TaskInventoryDictionary taskIDict = part.TaskInventory; 1801 TaskInventoryDictionary taskIDict = part.TaskInventory;
1660 if (taskIDict != null) 1802 if (taskIDict != null)
1661 { 1803 {
1662 lock (taskIDict) 1804 foreach (UUID taskID in taskIDict.Keys)
1663 { 1805 {
1664 foreach (UUID taskID in taskIDict.Keys) 1806 UnRegisterControlEventsToScript(LocalId, taskID);
1665 { 1807 taskIDict[taskID].PermsMask &= ~(
1666 UnRegisterControlEventsToScript(LocalId, taskID); 1808 2048 | //PERMISSION_CONTROL_CAMERA
1667 taskIDict[taskID].PermsMask &= ~( 1809 4); // PERMISSION_TAKE_CONTROLS
1668 2048 | //PERMISSION_CONTROL_CAMERA
1669 4); // PERMISSION_TAKE_CONTROLS
1670 }
1671 } 1810 }
1672
1673 } 1811 }
1812 part.TaskInventory.LockItemsForRead(false);
1674 // Reset sit target. 1813 // Reset sit target.
1675 if (part.GetAvatarOnSitTarget() == UUID) 1814 if (part.GetAvatarOnSitTarget() == UUID)
1676 part.SetAvatarOnSitTarget(UUID.Zero); 1815 part.SetAvatarOnSitTarget(UUID.Zero);
1677
1678 m_parentPosition = part.GetWorldPosition(); 1816 m_parentPosition = part.GetWorldPosition();
1679 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1817 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1680 } 1818 }
1819 // part.GetWorldRotation() is the rotation of the object being sat on
1820 // Rotation is the sittiing Av's rotation
1821
1822 Quaternion partRot;
1823// if (part.LinkNum == 1)
1824// { // Root prim of linkset
1825// partRot = part.ParentGroup.RootPart.RotationOffset;
1826// }
1827// else
1828// { // single or child prim
1829
1830// }
1831 if (part == null) //CW: Part may be gone. llDie() for example.
1832 {
1833 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1834 }
1835 else
1836 {
1837 partRot = part.GetWorldRotation();
1838 }
1839
1840 Quaternion partIRot = Quaternion.Inverse(partRot);
1681 1841
1842 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1843 Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
1844
1845
1682 if (m_physicsActor == null) 1846 if (m_physicsActor == null)
1683 { 1847 {
1684 AddToPhysicalScene(false); 1848 AddToPhysicalScene(false);
1685 } 1849 }
1686 1850 //CW: If the part isn't null then we can set the current position
1687 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1851 if (part != null)
1688 m_parentPosition = Vector3.Zero; 1852 {
1689 1853 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
1690 m_parentID = 0; 1854 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1855 part.IsOccupied = false;
1856 part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
1857 }
1858 else
1859 {
1860 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1861 AbsolutePosition = m_lastWorldPosition;
1862 }
1863
1864 m_parentPosition = Vector3.Zero;
1865 m_parentID = 0;
1866 m_linkedPrim = UUID.Zero;
1867 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1691 SendFullUpdateToAllClients(); 1868 SendFullUpdateToAllClients();
1692 m_requestedSitTargetID = 0; 1869 m_requestedSitTargetID = 0;
1693 if (m_physicsActor != null && m_appearance != null) 1870 if (m_physicsActor != null && m_appearance != null)
@@ -1696,7 +1873,6 @@ namespace OpenSim.Region.Framework.Scenes
1696 SetHeight(m_appearance.AvatarHeight); 1873 SetHeight(m_appearance.AvatarHeight);
1697 } 1874 }
1698 } 1875 }
1699
1700 Animator.TrySetMovementAnimation("STAND"); 1876 Animator.TrySetMovementAnimation("STAND");
1701 } 1877 }
1702 1878
@@ -1727,13 +1903,9 @@ namespace OpenSim.Region.Framework.Scenes
1727 Vector3 avSitOffSet = part.SitTargetPosition; 1903 Vector3 avSitOffSet = part.SitTargetPosition;
1728 Quaternion avSitOrientation = part.SitTargetOrientation; 1904 Quaternion avSitOrientation = part.SitTargetOrientation;
1729 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1905 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1730 1906 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1731 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1907 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1732 bool SitTargetisSet = 1908 if (SitTargetisSet && !SitTargetOccupied)
1733 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1734 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1735
1736 if (SitTargetisSet && SitTargetUnOccupied)
1737 { 1909 {
1738 //switch the target to this prim 1910 //switch the target to this prim
1739 return part; 1911 return part;
@@ -1747,84 +1919,164 @@ namespace OpenSim.Region.Framework.Scenes
1747 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 1919 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1748 { 1920 {
1749 bool autopilot = true; 1921 bool autopilot = true;
1922 Vector3 autopilotTarget = new Vector3();
1923 Quaternion sitOrientation = Quaternion.Identity;
1750 Vector3 pos = new Vector3(); 1924 Vector3 pos = new Vector3();
1751 Quaternion sitOrientation = pSitOrientation;
1752 Vector3 cameraEyeOffset = Vector3.Zero; 1925 Vector3 cameraEyeOffset = Vector3.Zero;
1753 Vector3 cameraAtOffset = Vector3.Zero; 1926 Vector3 cameraAtOffset = Vector3.Zero;
1754 bool forceMouselook = false; 1927 bool forceMouselook = false;
1755 1928
1756 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1929 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1757 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1930 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1758 if (part != null) 1931 if (part == null) return;
1759 { 1932
1760 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1933 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1761 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 1934 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1762 1935
1763 // Is a sit target available? 1936 // part is the prim to sit on
1764 Vector3 avSitOffSet = part.SitTargetPosition; 1937 // offset is the world-ref vector distance from that prim center to the click-spot
1765 Quaternion avSitOrientation = part.SitTargetOrientation; 1938 // UUID is the UUID of the Avatar doing the clicking
1766 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1939
1767 1940 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1768 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1941
1769 bool SitTargetisSet = 1942 // Is a sit target available?
1770 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1943 Vector3 avSitOffSet = part.SitTargetPosition;
1771 ( 1944 Quaternion avSitOrientation = part.SitTargetOrientation;
1772 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1945
1773 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 1946 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1774 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 1947 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1775 ) 1948 Quaternion partRot;
1776 )); 1949// if (part.LinkNum == 1)
1777 1950// { // Root prim of linkset
1778 if (SitTargetisSet && SitTargetUnOccupied) 1951// partRot = part.ParentGroup.RootPart.RotationOffset;
1779 { 1952// }
1780 part.SetAvatarOnSitTarget(UUID); 1953// else
1781 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1954// { // single or child prim
1782 sitOrientation = avSitOrientation; 1955 partRot = part.GetWorldRotation();
1783 autopilot = false; 1956// }
1784 } 1957 Quaternion partIRot = Quaternion.Inverse(partRot);
1785 1958//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1786 pos = part.AbsolutePosition + offset; 1959 // Sit analysis rewritten by KF 091125
1787 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 1960 if (SitTargetisSet) // scipted sit
1788 //{ 1961 {
1789 // offset = pos; 1962 if (!part.IsOccupied)
1790 //autopilot = false; 1963 {
1791 //} 1964//Console.WriteLine("Scripted, unoccupied");
1792 if (m_physicsActor != null) 1965 part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
1793 { 1966 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1794 // If we're not using the client autopilot, we're immediately warping the avatar to the location 1967
1795 // We can remove the physicsActor until they stand up. 1968 Quaternion nrot = avSitOrientation;
1796 m_sitAvatarHeight = m_physicsActor.Size.Z; 1969 if (!part.IsRoot)
1797
1798 if (autopilot)
1799 { 1970 {
1800 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1971 nrot = part.RotationOffset * avSitOrientation;
1801 {
1802 autopilot = false;
1803
1804 RemoveFromPhysicalScene();
1805 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1806 }
1807 } 1972 }
1808 else 1973 sitOrientation = nrot; // Change rotatione to the scripted one
1974 OffsetRotation = nrot;
1975 autopilot = false; // Jump direct to scripted llSitPos()
1976 }
1977 else
1978 {
1979//Console.WriteLine("Scripted, occupied");
1980 return;
1981 }
1982 }
1983 else // Not Scripted
1984 {
1985 if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
1986 {
1987 // large prim & offset, ignore if other Avs sitting
1988// offset.Z -= 0.05f;
1989 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
1990 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
1991
1992//Console.WriteLine(" offset ={0}", offset);
1993//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
1994//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
1995
1996 }
1997 else // small offset
1998 {
1999//Console.WriteLine("Small offset");
2000 if (!part.IsOccupied)
2001 {
2002 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
2003 autopilotTarget = part.AbsolutePosition;
2004//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
2005 }
2006 else return; // occupied small
2007 } // end large/small
2008 } // end Scripted/not
2009 cameraAtOffset = part.GetCameraAtOffset();
2010 cameraEyeOffset = part.GetCameraEyeOffset();
2011 forceMouselook = part.GetForceMouselook();
2012 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
2013 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
2014
2015 if (m_physicsActor != null)
2016 {
2017 // If we're not using the client autopilot, we're immediately warping the avatar to the location
2018 // We can remove the physicsActor until they stand up.
2019 m_sitAvatarHeight = m_physicsActor.Size.Z;
2020 if (autopilot)
2021 { // its not a scripted sit
2022// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
2023 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
1809 { 2024 {
2025 autopilot = false; // close enough
2026 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2027 Not using the part's position because returning the AV to the last known standing
2028 position is likely to be more friendly, isn't it? */
1810 RemoveFromPhysicalScene(); 2029 RemoveFromPhysicalScene();
1811 } 2030 Velocity = Vector3.Zero;
2031 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
2032 } // else the autopilot will get us close
2033 }
2034 else
2035 { // its a scripted sit
2036 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2037 I *am* using the part's position this time because we have no real idea how far away
2038 the avatar is from the sit target. */
2039 RemoveFromPhysicalScene();
2040 Velocity = Vector3.Zero;
1812 } 2041 }
1813
1814 cameraAtOffset = part.GetCameraAtOffset();
1815 cameraEyeOffset = part.GetCameraEyeOffset();
1816 forceMouselook = part.GetForceMouselook();
1817 } 2042 }
2043 else return; // physactor is null!
1818 2044
1819 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 2045 Vector3 offsetr; // = offset * partIRot;
1820 m_requestedSitTargetUUID = targetID; 2046 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
2047 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
2048 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
2049 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
2050 //offsetr = offset * partIRot;
2051//
2052 // else
2053 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
2054 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
2055 // (offset * partRot);
2056 // }
2057
2058//Console.WriteLine(" ");
2059//Console.WriteLine("link number ={0}", part.LinkNum);
2060//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2061//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2062//Console.WriteLine("Click offst ={0}", offset);
2063//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2064//Console.WriteLine("offsetr ={0}", offsetr);
2065//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2066//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2067
2068 //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
2069 ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2070
2071 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1821 // This calls HandleAgentSit twice, once from here, and the client calls 2072 // This calls HandleAgentSit twice, once from here, and the client calls
1822 // HandleAgentSit itself after it gets to the location 2073 // HandleAgentSit itself after it gets to the location
1823 // It doesn't get to the location until we've moved them there though 2074 // It doesn't get to the location until we've moved them there though
1824 // which happens in HandleAgentSit :P 2075 // which happens in HandleAgentSit :P
1825 m_autopilotMoving = autopilot; 2076 m_autopilotMoving = autopilot;
1826 m_autoPilotTarget = pos; 2077 m_autoPilotTarget = autopilotTarget;
1827 m_sitAtAutoTarget = autopilot; 2078 m_sitAtAutoTarget = autopilot;
2079 m_initialSitTarget = autopilotTarget;
1828 if (!autopilot) 2080 if (!autopilot)
1829 HandleAgentSit(remoteClient, UUID); 2081 HandleAgentSit(remoteClient, UUID);
1830 } 2082 }
@@ -2119,47 +2371,130 @@ namespace OpenSim.Region.Framework.Scenes
2119 { 2371 {
2120 if (part != null) 2372 if (part != null)
2121 { 2373 {
2374//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2122 if (part.GetAvatarOnSitTarget() == UUID) 2375 if (part.GetAvatarOnSitTarget() == UUID)
2123 { 2376 {
2377//Console.WriteLine("Scripted Sit");
2378 // Scripted sit
2124 Vector3 sitTargetPos = part.SitTargetPosition; 2379 Vector3 sitTargetPos = part.SitTargetPosition;
2125 Quaternion sitTargetOrient = part.SitTargetOrientation; 2380 Quaternion sitTargetOrient = part.SitTargetOrientation;
2126
2127 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2128 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2129
2130 //Quaternion result = (sitTargetOrient * vq) * nq;
2131
2132 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2381 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2133 m_pos += SIT_TARGET_ADJUSTMENT; 2382 m_pos += SIT_TARGET_ADJUSTMENT;
2383 if (!part.IsRoot)
2384 {
2385 m_pos *= part.RotationOffset;
2386 }
2134 m_bodyRot = sitTargetOrient; 2387 m_bodyRot = sitTargetOrient;
2135 //Rotation = sitTargetOrient;
2136 m_parentPosition = part.AbsolutePosition; 2388 m_parentPosition = part.AbsolutePosition;
2137 2389 part.IsOccupied = true;
2138 //SendTerseUpdateToAllClients(); 2390 part.ParentGroup.AddAvatar(agentID);
2139 } 2391 }
2140 else 2392 else
2141 { 2393 {
2142 m_pos -= part.AbsolutePosition; 2394 // if m_avUnscriptedSitPos is zero then Av sits above center
2395 // Else Av sits at m_avUnscriptedSitPos
2396
2397 // Non-scripted sit by Kitto Flora 21Nov09
2398 // Calculate angle of line from prim to Av
2399 Quaternion partIRot;
2400// if (part.LinkNum == 1)
2401// { // Root prim of linkset
2402// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2403// }
2404// else
2405// { // single or child prim
2406 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2407// }
2408 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2409 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2410 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2411 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2412 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2413 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2414 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2415 // Av sits at world euler <0,0, z>, translated by part rotation
2416 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2417
2143 m_parentPosition = part.AbsolutePosition; 2418 m_parentPosition = part.AbsolutePosition;
2144 } 2419 part.IsOccupied = true;
2420 part.ParentGroup.AddAvatar(agentID);
2421 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2422 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2423 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2424 m_avUnscriptedSitPos; // adds click offset, if any
2425 //Set up raytrace to find top surface of prim
2426 Vector3 size = part.Scale;
2427 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2428 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2429 Vector3 down = new Vector3(0f, 0f, -1f);
2430//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2431 m_scene.PhysicsScene.RaycastWorld(
2432 start, // Vector3 position,
2433 down, // Vector3 direction,
2434 mag, // float length,
2435 SitAltitudeCallback); // retMethod
2436 } // end scripted/not
2145 } 2437 }
2146 else 2438 else // no Av
2147 { 2439 {
2148 return; 2440 return;
2149 } 2441 }
2150 } 2442 }
2151 m_parentID = m_requestedSitTargetID;
2152 2443
2444 //We want our offsets to reference the root prim, not the child we may have sat on
2445 if (!part.IsRoot)
2446 {
2447 m_parentID = part.ParentGroup.RootPart.LocalId;
2448 m_pos += part.OffsetPosition;
2449 }
2450 else
2451 {
2452 m_parentID = m_requestedSitTargetID;
2453 }
2454
2455 m_linkedPrim = part.UUID;
2456 if (part.GetAvatarOnSitTarget() != UUID)
2457 {
2458 m_offsetRotation = m_offsetRotation / part.RotationOffset;
2459 }
2153 Velocity = Vector3.Zero; 2460 Velocity = Vector3.Zero;
2154 RemoveFromPhysicalScene(); 2461 RemoveFromPhysicalScene();
2155
2156 Animator.TrySetMovementAnimation(sitAnimation); 2462 Animator.TrySetMovementAnimation(sitAnimation);
2157 SendFullUpdateToAllClients(); 2463 SendFullUpdateToAllClients();
2158 // This may seem stupid, but Our Full updates don't send avatar rotation :P 2464 SendTerseUpdateToAllClients();
2159 // So we're also sending a terse update (which has avatar rotation)
2160 // [Update] We do now.
2161 //SendTerseUpdateToAllClients();
2162 } 2465 }
2466
2467 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2468 {
2469 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2470 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2471 if(hitYN)
2472 {
2473 // m_pos = Av offset from prim center to make look like on center
2474 // m_parentPosition = Actual center pos of prim
2475 // collisionPoint = spot on prim where we want to sit
2476 // collisionPoint.Z = global sit surface height
2477 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2478 Quaternion partIRot;
2479// if (part.LinkNum == 1)
2480/// { // Root prim of linkset
2481// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2482// }
2483// else
2484// { // single or child prim
2485 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2486// }
2487 if (m_initialSitTarget != null)
2488 {
2489 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2490 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2491 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2492 m_pos += offset;
2493 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2494 }
2495
2496 }
2497 } // End SitAltitudeCallback KF.
2163 2498
2164 /// <summary> 2499 /// <summary>
2165 /// Event handler for the 'Always run' setting on the client 2500 /// Event handler for the 'Always run' setting on the client
@@ -2189,7 +2524,7 @@ namespace OpenSim.Region.Framework.Scenes
2189 /// </summary> 2524 /// </summary>
2190 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2525 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2191 /// <param name="rotation">The direction in which this avatar should now face. 2526 /// <param name="rotation">The direction in which this avatar should now face.
2192 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2527 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2193 { 2528 {
2194 if (m_isChildAgent) 2529 if (m_isChildAgent)
2195 { 2530 {
@@ -2230,15 +2565,26 @@ namespace OpenSim.Region.Framework.Scenes
2230 Rotation = rotation; 2565 Rotation = rotation;
2231 Vector3 direc = vec * rotation; 2566 Vector3 direc = vec * rotation;
2232 direc.Normalize(); 2567 direc.Normalize();
2568 PhysicsActor actor = m_physicsActor;
2569
2570 if (actor.Flying != m_flyingOld) // add for fly velocity control
2571 {
2572 m_flyingOld = actor.Flying; // add for fly velocity control
2573 if (!actor.Flying) m_wasFlying = true; // add for fly velocity control
2574 }
2575
2576 if (m_physicsActor.IsColliding == true) m_wasFlying = false; // add for fly velocity control
2577
2578 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2233 2579
2234 direc *= 0.03f * 128f * m_speedModifier; 2580 direc *= 0.03f * 128f * m_speedModifier;
2235 2581
2236 PhysicsActor actor = m_physicsActor;
2237 if (actor != null) 2582 if (actor != null)
2238 { 2583 {
2239 if (actor.Flying) 2584 if (actor.Flying)
2240 { 2585 {
2241 direc *= 4.0f; 2586// rm speed mod direc *= 4.0f;
2587 direc *= 5.2f; // for speed mod
2242 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2588 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
2243 //bool colliding = (m_physicsActor.IsColliding==true); 2589 //bool colliding = (m_physicsActor.IsColliding==true);
2244 //if (controlland) 2590 //if (controlland)
@@ -2251,22 +2597,34 @@ namespace OpenSim.Region.Framework.Scenes
2251 // m_log.Info("[AGENT]: Stop FLying"); 2597 // m_log.Info("[AGENT]: Stop FLying");
2252 //} 2598 //}
2253 } 2599 }
2600 if (Animator.m_falling && m_wasFlying) // if falling from flying, disable motion add
2601 {
2602 direc *= 0.0f;
2603 }
2604 /* This jumping section removed to SPA
2254 else if (!actor.Flying && actor.IsColliding) 2605 else if (!actor.Flying && actor.IsColliding)
2255 { 2606 {
2256 if (direc.Z > 2.0f) 2607 if (direc.Z > 2.0f)
2257 { 2608 {
2258 direc.Z *= 3.0f; 2609 if(m_animator.m_animTickJump == -1)
2259 2610 {
2260 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2611 direc.Z *= 3.0f; // jump
2261 Animator.TrySetMovementAnimation("PREJUMP"); 2612 }
2262 Animator.TrySetMovementAnimation("JUMP"); 2613 else
2614 {
2615 direc.Z *= 0.1f; // prejump
2616 }
2617 / * Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
2618 Animator.TrySetMovementAnimation("PREJUMP");
2619 Animator.TrySetMovementAnimation("JUMP");
2620 * /
2263 } 2621 }
2264 } 2622 } */
2265 } 2623 }
2266 2624
2267 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2625 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2268 m_forceToApply = direc; 2626 m_forceToApply = direc;
2269 2627 m_isNudging = Nudging;
2270 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2628 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2271 } 2629 }
2272 2630
@@ -2281,7 +2639,7 @@ namespace OpenSim.Region.Framework.Scenes
2281 const float POSITION_TOLERANCE = 0.05f; 2639 const float POSITION_TOLERANCE = 0.05f;
2282 //const int TIME_MS_TOLERANCE = 3000; 2640 //const int TIME_MS_TOLERANCE = 3000;
2283 2641
2284 SendPrimUpdates(); 2642
2285 2643
2286 if (m_isChildAgent == false) 2644 if (m_isChildAgent == false)
2287 { 2645 {
@@ -2311,6 +2669,9 @@ namespace OpenSim.Region.Framework.Scenes
2311 CheckForBorderCrossing(); 2669 CheckForBorderCrossing();
2312 CheckForSignificantMovement(); // sends update to the modules. 2670 CheckForSignificantMovement(); // sends update to the modules.
2313 } 2671 }
2672
2673 //Sending prim updates AFTER the avatar terse updates are sent
2674 SendPrimUpdates();
2314 } 2675 }
2315 2676
2316 #endregion 2677 #endregion
@@ -3058,6 +3419,7 @@ namespace OpenSim.Region.Framework.Scenes
3058 m_callbackURI = cAgent.CallbackURI; 3419 m_callbackURI = cAgent.CallbackURI;
3059 3420
3060 m_pos = cAgent.Position; 3421 m_pos = cAgent.Position;
3422
3061 m_velocity = cAgent.Velocity; 3423 m_velocity = cAgent.Velocity;
3062 m_CameraCenter = cAgent.Center; 3424 m_CameraCenter = cAgent.Center;
3063 m_CameraAtAxis = cAgent.AtAxis; 3425 m_CameraAtAxis = cAgent.AtAxis;
@@ -3176,17 +3538,46 @@ namespace OpenSim.Region.Framework.Scenes
3176 /// </summary> 3538 /// </summary>
3177 public override void UpdateMovement() 3539 public override void UpdateMovement()
3178 { 3540 {
3179 if (m_forceToApply.HasValue) 3541 if (Animator!=null) // add for jumping
3180 { 3542 { // add for jumping
3181 Vector3 force = m_forceToApply.Value; 3543 // if (!m_animator.m_jumping) // add for jumping
3544 // { // add for jumping
3182 3545
3183 m_updateflag = true; 3546 if (m_forceToApply.HasValue) // this section realigned
3184// movementvector = force; 3547 {
3185 Velocity = force;
3186 3548
3187 m_forceToApply = null; 3549 Vector3 force = m_forceToApply.Value;
3188 } 3550 m_updateflag = true;
3189 } 3551if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3552 Velocity = force;
3553//Console.WriteLine("UM1 {0}", Velocity);
3554 m_forceToApply = null;
3555 }
3556 else
3557 {
3558 if (m_isNudging)
3559 {
3560 Vector3 force = Vector3.Zero;
3561
3562 m_updateflag = true;
3563if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3564 Velocity = force;
3565//Console.WriteLine("UM2 {0}", Velocity);
3566 m_isNudging = false;
3567 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3568 }
3569 else // add for jumping
3570 { // add for jumping
3571 Vector3 force = Vector3.Zero; // add for jumping
3572if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3573//Console.WriteLine("UM3 {0}", Velocity);
3574 Velocity = force; // add for jumping
3575 }
3576
3577 }
3578 // } // end realign
3579 } // add for jumping
3580 } // add for jumping
3190 3581
3191 /// <summary> 3582 /// <summary>
3192 /// Adds a physical representation of the avatar to the Physics plugin 3583 /// Adds a physical representation of the avatar to the Physics plugin
@@ -3200,10 +3591,8 @@ namespace OpenSim.Region.Framework.Scenes
3200 3591
3201 Vector3 pVec = AbsolutePosition; 3592 Vector3 pVec = AbsolutePosition;
3202 3593
3203 // Old bug where the height was in centimeters instead of meters
3204 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, 3594 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
3205 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying); 3595 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
3206
3207 scene.AddPhysicsActorTaint(m_physicsActor); 3596 scene.AddPhysicsActorTaint(m_physicsActor);
3208 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3597 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3209 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3598 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
@@ -3227,18 +3616,29 @@ namespace OpenSim.Region.Framework.Scenes
3227 { 3616 {
3228 if (e == null) 3617 if (e == null)
3229 return; 3618 return;
3230 3619
3231 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3620 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3232 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3233 // as of this comment the interval is set in AddToPhysicalScene 3621 // as of this comment the interval is set in AddToPhysicalScene
3234 if (Animator!=null) 3622 if (Animator!=null)
3235 Animator.UpdateMovementAnimations(); 3623 {
3624 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3625 { // else its will lock out other animation changes, like ground sit.
3626 Animator.UpdateMovementAnimations();
3627 m_updateCount--;
3628 }
3629 }
3236 3630
3237 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3631 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3238 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3632 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3239 3633
3240 CollisionPlane = Vector4.UnitW; 3634 CollisionPlane = Vector4.UnitW;
3241 3635
3636 if (m_lastColCount != coldata.Count)
3637 {
3638 m_updateCount = UPDATE_COUNT;
3639 m_lastColCount = coldata.Count;
3640 }
3641
3242 if (coldata.Count != 0 && Animator != null) 3642 if (coldata.Count != 0 && Animator != null)
3243 { 3643 {
3244 switch (Animator.CurrentMovementAnimation) 3644 switch (Animator.CurrentMovementAnimation)
@@ -3268,6 +3668,148 @@ namespace OpenSim.Region.Framework.Scenes
3268 } 3668 }
3269 } 3669 }
3270 3670
3671 List<uint> thisHitColliders = new List<uint>();
3672 List<uint> endedColliders = new List<uint>();
3673 List<uint> startedColliders = new List<uint>();
3674
3675 foreach (uint localid in coldata.Keys)
3676 {
3677 thisHitColliders.Add(localid);
3678 if (!m_lastColliders.Contains(localid))
3679 {
3680 startedColliders.Add(localid);
3681 }
3682 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3683 }
3684
3685 // calculate things that ended colliding
3686 foreach (uint localID in m_lastColliders)
3687 {
3688 if (!thisHitColliders.Contains(localID))
3689 {
3690 endedColliders.Add(localID);
3691 }
3692 }
3693 //add the items that started colliding this time to the last colliders list.
3694 foreach (uint localID in startedColliders)
3695 {
3696 m_lastColliders.Add(localID);
3697 }
3698 // remove things that ended colliding from the last colliders list
3699 foreach (uint localID in endedColliders)
3700 {
3701 m_lastColliders.Remove(localID);
3702 }
3703
3704 // do event notification
3705 if (startedColliders.Count > 0)
3706 {
3707 ColliderArgs StartCollidingMessage = new ColliderArgs();
3708 List<DetectedObject> colliding = new List<DetectedObject>();
3709 foreach (uint localId in startedColliders)
3710 {
3711 if (localId == 0)
3712 continue;
3713
3714 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3715 string data = "";
3716 if (obj != null)
3717 {
3718 DetectedObject detobj = new DetectedObject();
3719 detobj.keyUUID = obj.UUID;
3720 detobj.nameStr = obj.Name;
3721 detobj.ownerUUID = obj.OwnerID;
3722 detobj.posVector = obj.AbsolutePosition;
3723 detobj.rotQuat = obj.GetWorldRotation();
3724 detobj.velVector = obj.Velocity;
3725 detobj.colliderType = 0;
3726 detobj.groupUUID = obj.GroupID;
3727 colliding.Add(detobj);
3728 }
3729 }
3730
3731 if (colliding.Count > 0)
3732 {
3733 StartCollidingMessage.Colliders = colliding;
3734
3735 foreach (SceneObjectGroup att in Attachments)
3736 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3737 }
3738 }
3739
3740 if (endedColliders.Count > 0)
3741 {
3742 ColliderArgs EndCollidingMessage = new ColliderArgs();
3743 List<DetectedObject> colliding = new List<DetectedObject>();
3744 foreach (uint localId in endedColliders)
3745 {
3746 if (localId == 0)
3747 continue;
3748
3749 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3750 string data = "";
3751 if (obj != null)
3752 {
3753 DetectedObject detobj = new DetectedObject();
3754 detobj.keyUUID = obj.UUID;
3755 detobj.nameStr = obj.Name;
3756 detobj.ownerUUID = obj.OwnerID;
3757 detobj.posVector = obj.AbsolutePosition;
3758 detobj.rotQuat = obj.GetWorldRotation();
3759 detobj.velVector = obj.Velocity;
3760 detobj.colliderType = 0;
3761 detobj.groupUUID = obj.GroupID;
3762 colliding.Add(detobj);
3763 }
3764 }
3765
3766 if (colliding.Count > 0)
3767 {
3768 EndCollidingMessage.Colliders = colliding;
3769
3770 foreach (SceneObjectGroup att in Attachments)
3771 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
3772 }
3773 }
3774
3775 if (thisHitColliders.Count > 0)
3776 {
3777 ColliderArgs CollidingMessage = new ColliderArgs();
3778 List<DetectedObject> colliding = new List<DetectedObject>();
3779 foreach (uint localId in thisHitColliders)
3780 {
3781 if (localId == 0)
3782 continue;
3783
3784 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3785 string data = "";
3786 if (obj != null)
3787 {
3788 DetectedObject detobj = new DetectedObject();
3789 detobj.keyUUID = obj.UUID;
3790 detobj.nameStr = obj.Name;
3791 detobj.ownerUUID = obj.OwnerID;
3792 detobj.posVector = obj.AbsolutePosition;
3793 detobj.rotQuat = obj.GetWorldRotation();
3794 detobj.velVector = obj.Velocity;
3795 detobj.colliderType = 0;
3796 detobj.groupUUID = obj.GroupID;
3797 colliding.Add(detobj);
3798 }
3799 }
3800
3801 if (colliding.Count > 0)
3802 {
3803 CollidingMessage.Colliders = colliding;
3804
3805 lock (m_attachments)
3806 {
3807 foreach (SceneObjectGroup att in m_attachments)
3808 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
3809 }
3810 }
3811 }
3812
3271 if (m_invulnerable) 3813 if (m_invulnerable)
3272 return; 3814 return;
3273 3815
@@ -3693,6 +4235,39 @@ namespace OpenSim.Region.Framework.Scenes
3693 return; 4235 return;
3694 } 4236 }
3695 4237
4238 XmlDocument doc = new XmlDocument();
4239 string stateData = String.Empty;
4240
4241 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
4242 if (attServ != null)
4243 {
4244 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
4245 stateData = attServ.Get(ControllingClient.AgentId.ToString());
4246 if (stateData != String.Empty)
4247 {
4248 try
4249 {
4250 doc.LoadXml(stateData);
4251 }
4252 catch { }
4253 }
4254 }
4255
4256 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
4257
4258 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
4259 if (nodes.Count > 0)
4260 {
4261 foreach (XmlNode n in nodes)
4262 {
4263 XmlElement elem = (XmlElement)n;
4264 string itemID = elem.GetAttribute("ItemID");
4265 string xml = elem.InnerXml;
4266
4267 itemData[new UUID(itemID)] = xml;
4268 }
4269 }
4270
3696 List<AvatarAttachment> attachments = m_appearance.GetAttachments(); 4271 List<AvatarAttachment> attachments = m_appearance.GetAttachments();
3697 foreach (AvatarAttachment attach in attachments) 4272 foreach (AvatarAttachment attach in attachments)
3698 { 4273 {
@@ -3713,7 +4288,30 @@ namespace OpenSim.Region.Framework.Scenes
3713 4288
3714 try 4289 try
3715 { 4290 {
3716 m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); 4291 string xmlData;
4292 XmlDocument d = new XmlDocument();
4293 UUID asset;
4294 if (itemData.TryGetValue(itemID, out xmlData))
4295 {
4296 d.LoadXml(xmlData);
4297 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
4298
4299 // Rez from inventory
4300 asset
4301 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
4302
4303 }
4304 else
4305 {
4306 // Rez from inventory (with a null doc to let
4307 // CHANGED_OWNER happen)
4308 asset
4309 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
4310 }
4311
4312 m_log.InfoFormat(
4313 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2}",
4314 p, itemID, asset);
3717 } 4315 }
3718 catch (Exception e) 4316 catch (Exception e)
3719 { 4317 {
@@ -3746,6 +4344,15 @@ namespace OpenSim.Region.Framework.Scenes
3746 m_reprioritization_called = false; 4344 m_reprioritization_called = false;
3747 } 4345 }
3748 } 4346 }
4347
4348 private Vector3 Quat2Euler(Quaternion rot){
4349 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4350 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4351 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4352 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4353 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4354 return(new Vector3(x,y,z));
4355 }
3749 4356
3750 public void SaveChangedAttachments() 4357 public void SaveChangedAttachments()
3751 { 4358 {
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index fb4ef28..dfc69d8 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -99,7 +99,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
99 sceneObject.AddPart(part); 99 sceneObject.AddPart(part);
100 part.LinkNum = linkNum; 100 part.LinkNum = linkNum;
101 part.TrimPermissions(); 101 part.TrimPermissions();
102 part.StoreUndoState(); 102 part.StoreUndoState(UndoType.STATE_ALL);
103 reader.Close(); 103 reader.Close();
104 sr.Close(); 104 sr.Close();
105 } 105 }
@@ -217,7 +217,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
217 if (originalLinkNum != 0) 217 if (originalLinkNum != 0)
218 part.LinkNum = originalLinkNum; 218 part.LinkNum = originalLinkNum;
219 219
220 part.StoreUndoState(); 220 part.StoreUndoState(UndoType.STATE_ALL);
221 reader.Close(); 221 reader.Close();
222 sr.Close(); 222 sr.Close();
223 } 223 }
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