aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs226
-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.cs34
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs249
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs317
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs230
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs657
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs283
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs672
-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
15 files changed, 2818 insertions, 1055 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 4865481..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,48 +230,127 @@ 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 else if (m_animTickJump == -1)
237 {
238 m_animTickJump = 0;
239 return "STAND";
240 }
241 257
242 return m_movementAnimation; 258 return m_movementAnimation;
243 } 259 }
244 260
245 #endregion Falling/Floating/Landing 261 #endregion Falling/Floating/Landing
246 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
247 #region Ground Movement 315 #region Ground Movement
248 316
249 if (m_movementAnimation == "FALLDOWN") 317 if (m_movementAnimation == "FALLDOWN")
250 { 318 {
319 m_falling = false;
251 m_animTickFall = Environment.TickCount; 320 m_animTickFall = Environment.TickCount;
252
253 // TODO: SOFT_LAND support 321 // TODO: SOFT_LAND support
254 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
255 } 330 }
256 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"))
257 { 335 {
258 float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; 336 int landElapsed = Environment.TickCount - m_animTickFall; // add for jumping
259 if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY)) 337 int limit = 1000; // add for jumping
260 return "LAND"; 338 if(m_movementAnimation == "LAND") limit = 350; // add for jumping
261 } 339 // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client
262 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
263 m_animTickFall = 0; 354 m_animTickFall = 0;
264 355
265 if (move.Z > 0f) 356 if (move.Z > 0f)
@@ -271,7 +362,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
271 m_animTickJump = Environment.TickCount; 362 m_animTickJump = Environment.TickCount;
272 return "PREJUMP"; 363 return "PREJUMP";
273 } 364 }
274 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f) 365 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 800.0f)
275 { 366 {
276 // Start actual jump 367 // Start actual jump
277 if (m_animTickJump == -1) 368 if (m_animTickJump == -1)
@@ -284,37 +375,40 @@ namespace OpenSim.Region.Framework.Scenes.Animation
284 m_animTickJump = -1; 375 m_animTickJump = -1;
285 return "JUMP"; 376 return "JUMP";
286 } 377 }
287 else
288 return "JUMP";
289 } 378 }
290 else 379 else
291 { 380 {
292 // Not jumping 381 // Not jumping
293 m_animTickJump = 0; 382 m_animTickJump = 0;
294 383 */
295 if (move.X != 0f || move.Y != 0f) 384 // next section moved outside paren. and realigned for jumping
296 { 385 if (move.X != 0f || move.Y != 0f)
297 // Walking / crouchwalking / running 386 {
298 if (move.Z < 0f) 387 m_fallHeight = actor.Position.Z; // save latest flying height
299 return "CROUCHWALK"; 388 m_falling = false; // Add for falling
300 else if (m_scenePresence.SetAlwaysRun) 389 // Walking / crouchwalking / running
301 return "RUN"; 390 if (move.Z < 0f)
302 else 391 return "CROUCHWALK";
303 return "WALK"; 392 else if (m_scenePresence.SetAlwaysRun)
304 } 393 return "RUN";
305 else 394 else
306 { 395 return "WALK";
307 // Not walking
308 if (move.Z < 0f)
309 return "CROUCH";
310 else
311 return "STAND";
312 }
313 } 396 }
314 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
315 #endregion Ground Movement 408 #endregion Ground Movement
316 409
317 //return m_movementAnimation; 410 m_falling = false; // Add for falling
411 return m_movementAnimation;
318 } 412 }
319 413
320 /// <summary> 414 /// <summary>
@@ -323,7 +417,15 @@ namespace OpenSim.Region.Framework.Scenes.Animation
323 public void UpdateMovementAnimations() 417 public void UpdateMovementAnimations()
324 { 418 {
325 m_movementAnimation = GetMovementAnimation(); 419 m_movementAnimation = GetMovementAnimation();
326 TrySetMovementAnimation(m_movementAnimation); 420/* if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
421 {
422 // This was the previous behavior before PREJUMP
423 TrySetMovementAnimation("JUMP");
424 }
425 else
426 { removed for jumping */
427 TrySetMovementAnimation(m_movementAnimation);
428// rm for jumping }
327 } 429 }
328 430
329 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 f9599f5..cde8d3f 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 {
@@ -224,22 +225,16 @@ namespace OpenSim.Region.Framework.Scenes
224 if (entity == null) 225 if (entity == null)
225 return double.NaN; 226 return double.NaN;
226 227
227 // Use group position for child prims 228 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
228 Vector3 entityPos = entity.AbsolutePosition; 229 if (presence != null)
229 if (entity is SceneObjectPart)
230 { 230 {
231 SceneObjectGroup group = (entity as SceneObjectPart).ParentGroup; 231 // Use group position for child prims
232 if (group != null) 232 Vector3 entityPos;
233 entityPos = group.AbsolutePosition; 233 if (entity is SceneObjectPart)
234 entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition;
234 else 235 else
235 entityPos = entity.AbsolutePosition; 236 entityPos = entity.AbsolutePosition;
236 }
237 else
238 entityPos = entity.AbsolutePosition;
239 237
240 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
241 if (presence != null)
242 {
243 if (!presence.IsChildAgent) 238 if (!presence.IsChildAgent)
244 { 239 {
245 if (entity is ScenePresence) 240 if (entity is ScenePresence)
@@ -259,12 +254,19 @@ namespace OpenSim.Region.Framework.Scenes
259 254
260 if (entity is SceneObjectPart) 255 if (entity is SceneObjectPart)
261 { 256 {
262 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
263 if (physActor == null || !physActor.IsPhysical)
264 priority += 100;
265
266 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) 257 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
258 {
267 priority = 1.0; 259 priority = 1.0;
260 }
261 else
262 {
263 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
264 if (physActor == null || !physActor.IsPhysical)
265 priority += 100;
266 }
267
268 if (((SceneObjectPart)entity).ParentGroup.RootPart != (SceneObjectPart)entity)
269 priority +=1;
268 } 270 }
269 return priority; 271 return priority;
270 } 272 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 321d0aa..47c574a 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;
@@ -688,6 +670,8 @@ namespace OpenSim.Region.Framework.Scenes
688 return; 670 return;
689 } 671 }
690 672
673 if (newName == null) newName = item.Name;
674
691 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 675 AssetBase asset = AssetService.Get(item.AssetID.ToString());
692 676
693 if (asset != null) 677 if (asset != null)
@@ -735,6 +719,24 @@ namespace OpenSim.Region.Framework.Scenes
735 } 719 }
736 720
737 /// <summary> 721 /// <summary>
722 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
723 /// </summary>
724 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
725 {
726 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
727 foreach (InventoryItemBase b in items)
728 {
729 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
730 InventoryItemBase n = InventoryService.GetItem(b);
731 n.Folder = destfolder;
732 moveitems.Add(n);
733 remoteClient.SendInventoryItemCreateUpdate(n, 0);
734 }
735
736 MoveInventoryItem(remoteClient, moveitems);
737 }
738
739 /// <summary>
738 /// Move an item within the agent's inventory. 740 /// Move an item within the agent's inventory.
739 /// </summary> 741 /// </summary>
740 /// <param name="remoteClient"></param> 742 /// <param name="remoteClient"></param>
@@ -967,8 +969,12 @@ namespace OpenSim.Region.Framework.Scenes
967 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 969 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
968 { 970 {
969 SceneObjectPart part = GetSceneObjectPart(localID); 971 SceneObjectPart part = GetSceneObjectPart(localID);
970 SceneObjectGroup group = part.ParentGroup; 972 SceneObjectGroup group = null;
971 if (group != null) 973 if (part != null)
974 {
975 group = part.ParentGroup;
976 }
977 if (part != null && group != null)
972 { 978 {
973 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) 979 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
974 return; 980 return;
@@ -1417,13 +1423,6 @@ namespace OpenSim.Region.Framework.Scenes
1417 { 1423 {
1418 agentTransactions.HandleTaskItemUpdateFromTransaction( 1424 agentTransactions.HandleTaskItemUpdateFromTransaction(
1419 remoteClient, part, transactionID, currentItem); 1425 remoteClient, part, transactionID, currentItem);
1420
1421 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1422 remoteClient.SendAgentAlertMessage("Notecard saved", false);
1423 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1424 remoteClient.SendAgentAlertMessage("Script saved", false);
1425 else
1426 remoteClient.SendAgentAlertMessage("Item saved", false);
1427 } 1426 }
1428 1427
1429 // Base ALWAYS has move 1428 // Base ALWAYS has move
@@ -1541,7 +1540,7 @@ namespace OpenSim.Region.Framework.Scenes
1541 return; 1540 return;
1542 1541
1543 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1542 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1544 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1543 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1545 remoteClient.AgentId); 1544 remoteClient.AgentId);
1546 AssetService.Store(asset); 1545 AssetService.Store(asset);
1547 1546
@@ -1694,23 +1693,32 @@ namespace OpenSim.Region.Framework.Scenes
1694 // build a list of eligible objects 1693 // build a list of eligible objects
1695 List<uint> deleteIDs = new List<uint>(); 1694 List<uint> deleteIDs = new List<uint>();
1696 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1695 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1697 1696 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1698 // Start with true for both, then remove the flags if objects
1699 // that we can't derez are part of the selection
1700 bool permissionToTake = true;
1701 bool permissionToTakeCopy = true;
1702 bool permissionToDelete = true;
1703 1697
1704 foreach (uint localID in localIDs) 1698 foreach (uint localID in localIDs)
1705 { 1699 {
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
1706 // Invalid id 1706 // Invalid id
1707 SceneObjectPart part = GetSceneObjectPart(localID); 1707 SceneObjectPart part = GetSceneObjectPart(localID);
1708 if (part == null) 1708 if (part == null)
1709 {
1710 //Client still thinks the object exists, kill it
1711 deleteIDs.Add(localID);
1709 continue; 1712 continue;
1713 }
1710 1714
1711 // Already deleted by someone else 1715 // Already deleted by someone else
1712 if (part.ParentGroup == null || part.ParentGroup.IsDeleted) 1716 if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
1717 {
1718 //Client still thinks the object exists, kill it
1719 deleteIDs.Add(localID);
1713 continue; 1720 continue;
1721 }
1714 1722
1715 // Can't delete child prims 1723 // Can't delete child prims
1716 if (part != part.ParentGroup.RootPart) 1724 if (part != part.ParentGroup.RootPart)
@@ -1718,9 +1726,6 @@ namespace OpenSim.Region.Framework.Scenes
1718 1726
1719 SceneObjectGroup grp = part.ParentGroup; 1727 SceneObjectGroup grp = part.ParentGroup;
1720 1728
1721 deleteIDs.Add(localID);
1722 deleteGroups.Add(grp);
1723
1724 if (remoteClient == null) 1729 if (remoteClient == null)
1725 { 1730 {
1726 // Autoreturn has a null client. Nothing else does. So 1731 // Autoreturn has a null client. Nothing else does. So
@@ -1737,80 +1742,104 @@ namespace OpenSim.Region.Framework.Scenes
1737 } 1742 }
1738 else 1743 else
1739 { 1744 {
1740 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1745 if (action == DeRezAction.TakeCopy)
1746 {
1747 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1748 permissionToTakeCopy = false;
1749 }
1750 else
1751 {
1741 permissionToTakeCopy = false; 1752 permissionToTakeCopy = false;
1742 1753 }
1743 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1754 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1744 permissionToTake = false; 1755 permissionToTake = false;
1745 1756
1746 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1757 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1747 permissionToDelete = false; 1758 permissionToDelete = false;
1748 } 1759 }
1749 }
1750 1760
1751 // Handle god perms 1761 // Handle god perms
1752 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1762 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1753 { 1763 {
1754 permissionToTake = true; 1764 permissionToTake = true;
1755 permissionToTakeCopy = true; 1765 permissionToTakeCopy = true;
1756 permissionToDelete = true; 1766 permissionToDelete = true;
1757 } 1767 }
1758 1768
1759 // If we're re-saving, we don't even want to delete 1769 // If we're re-saving, we don't even want to delete
1760 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1770 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1761 permissionToDelete = false; 1771 permissionToDelete = false;
1762 1772
1763 // if we want to take a copy, we also don't want to delete 1773 // if we want to take a copy, we also don't want to delete
1764 // Note: after this point, the permissionToTakeCopy flag 1774 // Note: after this point, the permissionToTakeCopy flag
1765 // becomes irrelevant. It already includes the permissionToTake 1775 // becomes irrelevant. It already includes the permissionToTake
1766 // permission and after excluding no copy items here, we can 1776 // permission and after excluding no copy items here, we can
1767 // just use that. 1777 // just use that.
1768 if (action == DeRezAction.TakeCopy) 1778 if (action == DeRezAction.TakeCopy)
1769 { 1779 {
1770 // If we don't have permission, stop right here 1780 // If we don't have permission, stop right here
1771 if (!permissionToTakeCopy) 1781 if (!permissionToTakeCopy)
1772 return; 1782 return;
1773 1783
1774 permissionToTake = true; 1784 permissionToTake = true;
1775 // Don't delete 1785 // Don't delete
1776 permissionToDelete = false; 1786 permissionToDelete = false;
1777 } 1787 }
1778 1788
1779 if (action == DeRezAction.Return) 1789 if (action == DeRezAction.Return)
1780 {
1781 if (remoteClient != null)
1782 { 1790 {
1783 if (Permissions.CanReturnObjects( 1791 if (remoteClient != null)
1784 null,
1785 remoteClient.AgentId,
1786 deleteGroups))
1787 { 1792 {
1788 permissionToTake = true; 1793 if (Permissions.CanReturnObjects(
1789 permissionToDelete = true; 1794 null,
1790 1795 remoteClient.AgentId,
1791 foreach (SceneObjectGroup g in deleteGroups) 1796 deleteGroups))
1792 { 1797 {
1793 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1798 permissionToTake = true;
1799 permissionToDelete = true;
1800
1801 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1794 } 1802 }
1795 } 1803 }
1804 else // Auto return passes through here with null agent
1805 {
1806 permissionToTake = true;
1807 permissionToDelete = true;
1808 }
1796 } 1809 }
1797 else // Auto return passes through here with null agent 1810
1811 if (permissionToTake && (!permissionToDelete))
1812 takeGroups.Add(grp);
1813
1814 if (permissionToDelete)
1798 { 1815 {
1799 permissionToTake = true; 1816 if (permissionToTake)
1800 permissionToDelete = true; 1817 deleteGroups.Add(grp);
1818 deleteIDs.Add(grp.LocalId);
1801 } 1819 }
1802 } 1820 }
1803 1821
1804 if (permissionToTake) 1822 SendKillObject(deleteIDs);
1823
1824 if (deleteGroups.Count > 0)
1805 { 1825 {
1826 foreach (SceneObjectGroup g in deleteGroups)
1827 deleteIDs.Remove(g.LocalId);
1828
1806 m_asyncSceneObjectDeleter.DeleteToInventory( 1829 m_asyncSceneObjectDeleter.DeleteToInventory(
1807 action, destinationID, deleteGroups, remoteClient, 1830 action, destinationID, deleteGroups, remoteClient,
1808 permissionToDelete); 1831 true);
1809 } 1832 }
1810 else if (permissionToDelete) 1833 if (takeGroups.Count > 0)
1834 {
1835 m_asyncSceneObjectDeleter.DeleteToInventory(
1836 action, destinationID, takeGroups, remoteClient,
1837 false);
1838 }
1839 if (deleteIDs.Count > 0)
1811 { 1840 {
1812 foreach (SceneObjectGroup g in deleteGroups) 1841 foreach (SceneObjectGroup g in deleteGroups)
1813 DeleteSceneObject(g, false); 1842 DeleteSceneObject(g, true);
1814 } 1843 }
1815 } 1844 }
1816 1845
@@ -1862,21 +1891,29 @@ namespace OpenSim.Region.Framework.Scenes
1862 else // oopsies 1891 else // oopsies
1863 item.Folder = UUID.Zero; 1892 item.Folder = UUID.Zero;
1864 1893
1894 // Set up base perms properly
1895 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
1896 permsBase &= grp.RootPart.BaseMask;
1897 permsBase |= (uint)PermissionMask.Move;
1898
1899 // Make sure we don't lock it
1900 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
1901
1865 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions()) 1902 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
1866 { 1903 {
1867 item.BasePermissions = grp.RootPart.NextOwnerMask; 1904 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
1868 item.CurrentPermissions = grp.RootPart.NextOwnerMask; 1905 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
1869 item.NextPermissions = grp.RootPart.NextOwnerMask; 1906 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1870 item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask; 1907 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
1871 item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask; 1908 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
1872 } 1909 }
1873 else 1910 else
1874 { 1911 {
1875 item.BasePermissions = grp.RootPart.BaseMask; 1912 item.BasePermissions = permsBase;
1876 item.CurrentPermissions = grp.RootPart.OwnerMask; 1913 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
1877 item.NextPermissions = grp.RootPart.NextOwnerMask; 1914 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1878 item.EveryOnePermissions = grp.RootPart.EveryoneMask; 1915 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
1879 item.GroupPermissions = grp.RootPart.GroupMask; 1916 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
1880 } 1917 }
1881 item.CreationDate = Util.UnixTimeSinceEpoch(); 1918 item.CreationDate = Util.UnixTimeSinceEpoch();
1882 1919
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index c4bd028..d915807 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;
@@ -171,6 +174,8 @@ namespace OpenSim.Region.Framework.Scenes
171 private volatile bool shuttingdown; 174 private volatile bool shuttingdown;
172 175
173 private int m_lastUpdate; 176 private int m_lastUpdate;
177 private int m_lastIncoming;
178 private int m_lastOutgoing;
174 private bool m_firstHeartbeat = true; 179 private bool m_firstHeartbeat = true;
175 180
176 private object m_deleting_scene_object = new object(); 181 private object m_deleting_scene_object = new object();
@@ -222,6 +227,19 @@ namespace OpenSim.Region.Framework.Scenes
222 get { return m_sceneGridService; } 227 get { return m_sceneGridService; }
223 } 228 }
224 229
230 public ISnmpModule SnmpService
231 {
232 get
233 {
234 if (m_snmpService == null)
235 {
236 m_snmpService = RequestModuleInterface<ISnmpModule>();
237 }
238
239 return m_snmpService;
240 }
241 }
242
225 public ISimulationDataService SimulationDataService 243 public ISimulationDataService SimulationDataService
226 { 244 {
227 get 245 get
@@ -553,6 +571,8 @@ namespace OpenSim.Region.Framework.Scenes
553 m_regionName = m_regInfo.RegionName; 571 m_regionName = m_regInfo.RegionName;
554 m_datastore = m_regInfo.DataStore; 572 m_datastore = m_regInfo.DataStore;
555 m_lastUpdate = Util.EnvironmentTickCount(); 573 m_lastUpdate = Util.EnvironmentTickCount();
574 m_lastIncoming = 0;
575 m_lastOutgoing = 0;
556 576
557 m_physicalPrim = physicalPrim; 577 m_physicalPrim = physicalPrim;
558 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor; 578 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor;
@@ -566,6 +586,8 @@ namespace OpenSim.Region.Framework.Scenes
566 #region Region Settings 586 #region Region Settings
567 587
568 // Load region settings 588 // Load region settings
589 m_regInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(m_regInfo.RegionID);
590
569 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID); 591 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID);
570 if (estateDataService != null) 592 if (estateDataService != null)
571 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false); 593 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -625,9 +647,10 @@ namespace OpenSim.Region.Framework.Scenes
625 //Animation states 647 //Animation states
626 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 648 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
627 // TODO: Change default to true once the feature is supported 649 // TODO: Change default to true once the feature is supported
628 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 650 m_usePreJump = startupConfig.GetBoolean("enableprejump", true);
629
630 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 651 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
652
653 m_log.DebugFormat("[SCENE]: prejump is {0}", m_usePreJump ? "ON" : "OFF");
631 if (RegionInfo.NonphysPrimMax > 0) 654 if (RegionInfo.NonphysPrimMax > 0)
632 { 655 {
633 m_maxNonphys = RegionInfo.NonphysPrimMax; 656 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -659,6 +682,7 @@ namespace OpenSim.Region.Framework.Scenes
659 m_persistAfter *= 10000000; 682 m_persistAfter *= 10000000;
660 683
661 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 684 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
685 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
662 686
663 IConfig packetConfig = m_config.Configs["PacketPool"]; 687 IConfig packetConfig = m_config.Configs["PacketPool"];
664 if (packetConfig != null) 688 if (packetConfig != null)
@@ -668,6 +692,8 @@ namespace OpenSim.Region.Framework.Scenes
668 } 692 }
669 693
670 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 694 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
695 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
696 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
671 697
672 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 698 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
673 if (m_generateMaptiles) 699 if (m_generateMaptiles)
@@ -692,9 +718,9 @@ namespace OpenSim.Region.Framework.Scenes
692 } 718 }
693 } 719 }
694 } 720 }
695 catch 721 catch (Exception e)
696 { 722 {
697 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 723 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
698 } 724 }
699 725
700 #endregion Region Config 726 #endregion Region Config
@@ -1065,6 +1091,7 @@ namespace OpenSim.Region.Framework.Scenes
1065 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1091 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1066 if (HeartbeatThread != null) 1092 if (HeartbeatThread != null)
1067 { 1093 {
1094 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1068 HeartbeatThread.Abort(); 1095 HeartbeatThread.Abort();
1069 HeartbeatThread = null; 1096 HeartbeatThread = null;
1070 } 1097 }
@@ -1188,9 +1215,6 @@ namespace OpenSim.Region.Framework.Scenes
1188 try 1215 try
1189 { 1216 {
1190 Update(); 1217 Update();
1191
1192 m_lastUpdate = Util.EnvironmentTickCount();
1193 m_firstHeartbeat = false;
1194 } 1218 }
1195 catch (ThreadAbortException) 1219 catch (ThreadAbortException)
1196 { 1220 {
@@ -1381,6 +1405,9 @@ namespace OpenSim.Region.Framework.Scenes
1381 1405
1382 // Tell the watchdog that this thread is still alive 1406 // Tell the watchdog that this thread is still alive
1383 Watchdog.UpdateThread(); 1407 Watchdog.UpdateThread();
1408
1409 m_lastUpdate = Util.EnvironmentTickCount();
1410 m_firstHeartbeat = false;
1384 } 1411 }
1385 } 1412 }
1386 1413
@@ -1736,14 +1763,24 @@ namespace OpenSim.Region.Framework.Scenes
1736 /// <returns></returns> 1763 /// <returns></returns>
1737 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1764 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1738 { 1765 {
1766
1767 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1768 Vector3 wpos = Vector3.Zero;
1769 // Check for water surface intersection from above
1770 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1771 {
1772 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1773 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1774 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1775 wpos.Z = wheight;
1776 }
1777
1739 Vector3 pos = Vector3.Zero; 1778 Vector3 pos = Vector3.Zero;
1740 if (RayEndIsIntersection == (byte)1) 1779 if (RayEndIsIntersection == (byte)1)
1741 { 1780 {
1742 pos = RayEnd; 1781 pos = RayEnd;
1743 return pos;
1744 } 1782 }
1745 1783 else if (RayTargetID != UUID.Zero)
1746 if (RayTargetID != UUID.Zero)
1747 { 1784 {
1748 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1785 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1749 1786
@@ -1765,7 +1802,7 @@ namespace OpenSim.Region.Framework.Scenes
1765 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1802 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1766 1803
1767 // Un-comment out the following line to Get Raytrace results printed to the console. 1804 // Un-comment out the following line to Get Raytrace results printed to the console.
1768 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1805 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1769 float ScaleOffset = 0.5f; 1806 float ScaleOffset = 0.5f;
1770 1807
1771 // If we hit something 1808 // If we hit something
@@ -1788,13 +1825,10 @@ namespace OpenSim.Region.Framework.Scenes
1788 //pos.Z -= 0.25F; 1825 //pos.Z -= 0.25F;
1789 1826
1790 } 1827 }
1791
1792 return pos;
1793 } 1828 }
1794 else 1829 else
1795 { 1830 {
1796 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1831 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1797
1798 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1832 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1799 1833
1800 // Un-comment the following line to print the raytrace results to the console. 1834 // Un-comment the following line to print the raytrace results to the console.
@@ -1803,13 +1837,12 @@ namespace OpenSim.Region.Framework.Scenes
1803 if (ei.HitTF) 1837 if (ei.HitTF)
1804 { 1838 {
1805 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1839 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1806 } else 1840 }
1841 else
1807 { 1842 {
1808 // fall back to our stupid functionality 1843 // fall back to our stupid functionality
1809 pos = RayEnd; 1844 pos = RayEnd;
1810 } 1845 }
1811
1812 return pos;
1813 } 1846 }
1814 } 1847 }
1815 else 1848 else
@@ -1820,8 +1853,12 @@ namespace OpenSim.Region.Framework.Scenes
1820 //increase height so its above the ground. 1853 //increase height so its above the ground.
1821 //should be getting the normal of the ground at the rez point and using that? 1854 //should be getting the normal of the ground at the rez point and using that?
1822 pos.Z += scale.Z / 2f; 1855 pos.Z += scale.Z / 2f;
1823 return pos; 1856// return pos;
1824 } 1857 }
1858
1859 // check against posible water intercept
1860 if (wpos.Z > pos.Z) pos = wpos;
1861 return pos;
1825 } 1862 }
1826 1863
1827 1864
@@ -1901,7 +1938,10 @@ namespace OpenSim.Region.Framework.Scenes
1901 public bool AddRestoredSceneObject( 1938 public bool AddRestoredSceneObject(
1902 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1939 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1903 { 1940 {
1904 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1941 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1942 if (result)
1943 sceneObject.IsDeleted = false;
1944 return result;
1905 } 1945 }
1906 1946
1907 /// <summary> 1947 /// <summary>
@@ -1978,6 +2018,15 @@ namespace OpenSim.Region.Framework.Scenes
1978 /// </summary> 2018 /// </summary>
1979 public void DeleteAllSceneObjects() 2019 public void DeleteAllSceneObjects()
1980 { 2020 {
2021 DeleteAllSceneObjects(false);
2022 }
2023
2024 /// <summary>
2025 /// Delete every object from the scene. This does not include attachments worn by avatars.
2026 /// </summary>
2027 public void DeleteAllSceneObjects(bool exceptNoCopy)
2028 {
2029 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
1981 lock (Entities) 2030 lock (Entities)
1982 { 2031 {
1983 EntityBase[] entities = Entities.GetEntities(); 2032 EntityBase[] entities = Entities.GetEntities();
@@ -1986,11 +2035,24 @@ namespace OpenSim.Region.Framework.Scenes
1986 if (e is SceneObjectGroup) 2035 if (e is SceneObjectGroup)
1987 { 2036 {
1988 SceneObjectGroup sog = (SceneObjectGroup)e; 2037 SceneObjectGroup sog = (SceneObjectGroup)e;
1989 if (!sog.IsAttachment) 2038 if (sog != null && !sog.IsAttachment)
1990 DeleteSceneObject((SceneObjectGroup)e, false); 2039 {
2040 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2041 {
2042 DeleteSceneObject((SceneObjectGroup)e, false);
2043 }
2044 else
2045 {
2046 toReturn.Add((SceneObjectGroup)e);
2047 }
2048 }
1991 } 2049 }
1992 } 2050 }
1993 } 2051 }
2052 if (toReturn.Count > 0)
2053 {
2054 returnObjects(toReturn.ToArray(), UUID.Zero);
2055 }
1994 } 2056 }
1995 2057
1996 /// <summary> 2058 /// <summary>
@@ -2039,6 +2101,8 @@ namespace OpenSim.Region.Framework.Scenes
2039 } 2101 }
2040 2102
2041 group.DeleteGroupFromScene(silent); 2103 group.DeleteGroupFromScene(silent);
2104 if (!silent)
2105 SendKillObject(new List<uint>() { group.LocalId });
2042 2106
2043// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2107// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2044 } 2108 }
@@ -2369,6 +2433,12 @@ namespace OpenSim.Region.Framework.Scenes
2369 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2433 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2370 public bool AddSceneObject(SceneObjectGroup sceneObject) 2434 public bool AddSceneObject(SceneObjectGroup sceneObject)
2371 { 2435 {
2436 if (sceneObject.OwnerID == UUID.Zero)
2437 {
2438 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2439 return false;
2440 }
2441
2372 // If the user is banned, we won't let any of their objects 2442 // If the user is banned, we won't let any of their objects
2373 // enter. Period. 2443 // enter. Period.
2374 // 2444 //
@@ -2416,15 +2486,28 @@ namespace OpenSim.Region.Framework.Scenes
2416 2486
2417 if (AttachmentsModule != null) 2487 if (AttachmentsModule != null)
2418 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); 2488 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
2489
2490 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was found, attaching", sceneObject.UUID);
2419 } 2491 }
2420 else 2492 else
2421 { 2493 {
2494 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2422 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2495 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2423 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2496 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2424 } 2497 }
2498 if (sceneObject.OwnerID == UUID.Zero)
2499 {
2500 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2501 return false;
2502 }
2425 } 2503 }
2426 else 2504 else
2427 { 2505 {
2506 if (sceneObject.OwnerID == UUID.Zero)
2507 {
2508 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2509 return false;
2510 }
2428 AddRestoredSceneObject(sceneObject, true, false); 2511 AddRestoredSceneObject(sceneObject, true, false);
2429 2512
2430 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2513 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2536,12 +2619,19 @@ namespace OpenSim.Region.Framework.Scenes
2536 } 2619 }
2537 } 2620 }
2538 2621
2539 if (GetScenePresence(client.AgentId) != null) 2622 if (TryGetScenePresence(client.AgentId, out presence))
2540 { 2623 {
2541 m_LastLogin = Util.EnvironmentTickCount(); 2624 m_LastLogin = Util.EnvironmentTickCount();
2542 EventManager.TriggerOnNewClient(client); 2625 EventManager.TriggerOnNewClient(client);
2543 if (vialogin) 2626 if (vialogin)
2627 {
2544 EventManager.TriggerOnClientLogin(client); 2628 EventManager.TriggerOnClientLogin(client);
2629
2630 // Send initial parcel data
2631 Vector3 pos = presence.AbsolutePosition;
2632 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2633 land.SendLandUpdateToClient(presence.ControllingClient);
2634 }
2545 } 2635 }
2546 } 2636 }
2547 2637
@@ -2697,6 +2787,7 @@ namespace OpenSim.Region.Framework.Scenes
2697 client.OnFetchInventory += HandleFetchInventory; 2787 client.OnFetchInventory += HandleFetchInventory;
2698 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2788 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2699 client.OnCopyInventoryItem += CopyInventoryItem; 2789 client.OnCopyInventoryItem += CopyInventoryItem;
2790 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2700 client.OnMoveInventoryItem += MoveInventoryItem; 2791 client.OnMoveInventoryItem += MoveInventoryItem;
2701 client.OnRemoveInventoryItem += RemoveInventoryItem; 2792 client.OnRemoveInventoryItem += RemoveInventoryItem;
2702 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2793 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2875,15 +2966,16 @@ namespace OpenSim.Region.Framework.Scenes
2875 /// </summary> 2966 /// </summary>
2876 /// <param name="agentId">The avatar's Unique ID</param> 2967 /// <param name="agentId">The avatar's Unique ID</param>
2877 /// <param name="client">The IClientAPI for the client</param> 2968 /// <param name="client">The IClientAPI for the client</param>
2878 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 2969 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2879 { 2970 {
2880 if (m_teleportModule != null) 2971 if (m_teleportModule != null)
2881 m_teleportModule.TeleportHome(agentId, client); 2972 return m_teleportModule.TeleportHome(agentId, client);
2882 else 2973 else
2883 { 2974 {
2884 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 2975 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2885 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 2976 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2886 } 2977 }
2978 return false;
2887 } 2979 }
2888 2980
2889 /// <summary> 2981 /// <summary>
@@ -2982,6 +3074,16 @@ namespace OpenSim.Region.Framework.Scenes
2982 /// <param name="flags"></param> 3074 /// <param name="flags"></param>
2983 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3075 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
2984 { 3076 {
3077 //Add half the avatar's height so that the user doesn't fall through prims
3078 ScenePresence presence;
3079 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3080 {
3081 if (presence.Appearance != null)
3082 {
3083 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3084 }
3085 }
3086
2985 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3087 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
2986 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3088 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
2987 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3089 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3075,7 +3177,9 @@ namespace OpenSim.Region.Framework.Scenes
3075 regions.Remove(RegionInfo.RegionHandle); 3177 regions.Remove(RegionInfo.RegionHandle);
3076 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3178 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3077 } 3179 }
3180 m_log.Debug("[Scene] Beginning ClientClosed");
3078 m_eventManager.TriggerClientClosed(agentID, this); 3181 m_eventManager.TriggerClientClosed(agentID, this);
3182 m_log.Debug("[Scene] Finished ClientClosed");
3079 } 3183 }
3080 catch (NullReferenceException) 3184 catch (NullReferenceException)
3081 { 3185 {
@@ -3083,7 +3187,12 @@ namespace OpenSim.Region.Framework.Scenes
3083 // Avatar is already disposed :/ 3187 // Avatar is already disposed :/
3084 } 3188 }
3085 3189
3190 m_log.Debug("[Scene] Beginning OnRemovePresence");
3086 m_eventManager.TriggerOnRemovePresence(agentID); 3191 m_eventManager.TriggerOnRemovePresence(agentID);
3192 m_log.Debug("[Scene] Finished OnRemovePresence");
3193
3194 if (avatar != null && (!avatar.IsChildAgent))
3195 avatar.SaveChangedAttachments();
3087 3196
3088 if (avatar != null && (!avatar.IsChildAgent)) 3197 if (avatar != null && (!avatar.IsChildAgent))
3089 avatar.SaveChangedAttachments(); 3198 avatar.SaveChangedAttachments();
@@ -3092,7 +3201,7 @@ namespace OpenSim.Region.Framework.Scenes
3092 delegate(IClientAPI client) 3201 delegate(IClientAPI client)
3093 { 3202 {
3094 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3203 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3095 try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); } 3204 try { client.SendKillObject(avatar.RegionHandle, new List<uint>() { avatar.LocalId}); }
3096 catch (NullReferenceException) { } 3205 catch (NullReferenceException) { }
3097 }); 3206 });
3098 3207
@@ -3103,8 +3212,11 @@ namespace OpenSim.Region.Framework.Scenes
3103 } 3212 }
3104 3213
3105 // Remove the avatar from the scene 3214 // Remove the avatar from the scene
3215 m_log.Debug("[Scene] Begin RemoveScenePresence");
3106 m_sceneGraph.RemoveScenePresence(agentID); 3216 m_sceneGraph.RemoveScenePresence(agentID);
3217 m_log.Debug("[Scene] Finished RemoveScenePresence. Removing the client manager");
3107 m_clientManager.Remove(agentID); 3218 m_clientManager.Remove(agentID);
3219 m_log.Debug("[Scene] Removed the client manager. Firing avatar.close");
3108 3220
3109 try 3221 try
3110 { 3222 {
@@ -3118,9 +3230,10 @@ namespace OpenSim.Region.Framework.Scenes
3118 { 3230 {
3119 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString()); 3231 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString());
3120 } 3232 }
3121 3233 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3122 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3234 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3123 CleanDroppedAttachments(); 3235 CleanDroppedAttachments();
3236 m_log.Debug("[Scene] The avatar has left the building");
3124 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3237 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3125 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3238 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3126 } 3239 }
@@ -3151,18 +3264,24 @@ namespace OpenSim.Region.Framework.Scenes
3151 3264
3152 #region Entities 3265 #region Entities
3153 3266
3154 public void SendKillObject(uint localID) 3267 public void SendKillObject(List<uint> localIDs)
3155 { 3268 {
3156 SceneObjectPart part = GetSceneObjectPart(localID); 3269 List<uint> deleteIDs = new List<uint>();
3157 if (part != null) // It is a prim 3270
3271 foreach (uint localID in localIDs)
3158 { 3272 {
3159 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid 3273 SceneObjectPart part = GetSceneObjectPart(localID);
3274 if (part != null) // It is a prim
3160 { 3275 {
3161 if (part.ParentGroup.RootPart != part) // Child part 3276 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid
3162 return; 3277 {
3278 if (part.ParentGroup.RootPart != part) // Child part
3279 continue;
3280 }
3163 } 3281 }
3282 deleteIDs.Add(localID);
3164 } 3283 }
3165 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); }); 3284 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); });
3166 } 3285 }
3167 3286
3168 #endregion 3287 #endregion
@@ -3180,7 +3299,6 @@ namespace OpenSim.Region.Framework.Scenes
3180 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; 3299 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
3181 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; 3300 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
3182 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; 3301 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
3183 m_sceneGridService.KiPrimitive += SendKillObject;
3184 m_sceneGridService.OnGetLandData += GetLandData; 3302 m_sceneGridService.OnGetLandData += GetLandData;
3185 } 3303 }
3186 3304
@@ -3189,7 +3307,6 @@ namespace OpenSim.Region.Framework.Scenes
3189 /// </summary> 3307 /// </summary>
3190 public void UnRegisterRegionWithComms() 3308 public void UnRegisterRegionWithComms()
3191 { 3309 {
3192 m_sceneGridService.KiPrimitive -= SendKillObject;
3193 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; 3310 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid;
3194 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; 3311 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar;
3195 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; 3312 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;
@@ -3276,6 +3393,7 @@ namespace OpenSim.Region.Framework.Scenes
3276 { 3393 {
3277 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3394 if (land != null && !TestLandRestrictions(agent, land, out reason))
3278 { 3395 {
3396 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3279 return false; 3397 return false;
3280 } 3398 }
3281 } 3399 }
@@ -3393,6 +3511,8 @@ namespace OpenSim.Region.Framework.Scenes
3393 } 3511 }
3394 } 3512 }
3395 // Honor parcel landing type and position. 3513 // Honor parcel landing type and position.
3514 /*
3515 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3396 if (land != null) 3516 if (land != null)
3397 { 3517 {
3398 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3518 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3400,6 +3520,7 @@ namespace OpenSim.Region.Framework.Scenes
3400 agent.startpos = land.LandData.UserLocation; 3520 agent.startpos = land.LandData.UserLocation;
3401 } 3521 }
3402 } 3522 }
3523 */// This is now handled properly in ScenePresence.MakeRootAgent
3403 } 3524 }
3404 3525
3405 return true; 3526 return true;
@@ -3495,7 +3616,7 @@ namespace OpenSim.Region.Framework.Scenes
3495 3616
3496 if (m_regInfo.EstateSettings != null) 3617 if (m_regInfo.EstateSettings != null)
3497 { 3618 {
3498 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3619 if ((!m_seeIntoBannedRegion) && m_regInfo.EstateSettings.IsBanned(agent.AgentID))
3499 { 3620 {
3500 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3621 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3501 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3622 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3685,6 +3806,12 @@ namespace OpenSim.Region.Framework.Scenes
3685 3806
3686 // We have to wait until the viewer contacts this region after receiving EAC. 3807 // We have to wait until the viewer contacts this region after receiving EAC.
3687 // That calls AddNewClient, which finally creates the ScenePresence 3808 // That calls AddNewClient, which finally creates the ScenePresence
3809 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID))
3810 {
3811 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3812 return false;
3813 }
3814
3688 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3815 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3689 if (nearestParcel == null) 3816 if (nearestParcel == null)
3690 { 3817 {
@@ -3692,6 +3819,14 @@ namespace OpenSim.Region.Framework.Scenes
3692 return false; 3819 return false;
3693 } 3820 }
3694 3821
3822 int num = m_sceneGraph.GetNumberOfScenePresences();
3823
3824 if (num >= RegionInfo.RegionSettings.AgentLimit)
3825 {
3826 if (!Permissions.IsAdministrator(cAgentData.AgentID))
3827 return false;
3828 }
3829
3695 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 3830 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
3696 3831
3697 if (childAgentUpdate != null) 3832 if (childAgentUpdate != null)
@@ -3758,12 +3893,22 @@ namespace OpenSim.Region.Framework.Scenes
3758 return false; 3893 return false;
3759 } 3894 }
3760 3895
3896 public bool IncomingCloseAgent(UUID agentID)
3897 {
3898 return IncomingCloseAgent(agentID, false);
3899 }
3900
3901 public bool IncomingCloseChildAgent(UUID agentID)
3902 {
3903 return IncomingCloseAgent(agentID, true);
3904 }
3905
3761 /// <summary> 3906 /// <summary>
3762 /// Tell a single agent to disconnect from the region. 3907 /// Tell a single agent to disconnect from the region.
3763 /// </summary> 3908 /// </summary>
3764 /// <param name="regionHandle"></param>
3765 /// <param name="agentID"></param> 3909 /// <param name="agentID"></param>
3766 public bool IncomingCloseAgent(UUID agentID) 3910 /// <param name="childOnly"></param>
3911 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3767 { 3912 {
3768 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3913 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3769 3914
@@ -3775,7 +3920,7 @@ namespace OpenSim.Region.Framework.Scenes
3775 { 3920 {
3776 m_sceneGraph.removeUserCount(false); 3921 m_sceneGraph.removeUserCount(false);
3777 } 3922 }
3778 else 3923 else if (!childOnly)
3779 { 3924 {
3780 m_sceneGraph.removeUserCount(true); 3925 m_sceneGraph.removeUserCount(true);
3781 } 3926 }
@@ -3791,9 +3936,12 @@ namespace OpenSim.Region.Framework.Scenes
3791 } 3936 }
3792 else 3937 else
3793 presence.ControllingClient.SendShutdownConnectionNotice(); 3938 presence.ControllingClient.SendShutdownConnectionNotice();
3939 presence.ControllingClient.Close(false);
3940 }
3941 else if (!childOnly)
3942 {
3943 presence.ControllingClient.Close(true);
3794 } 3944 }
3795
3796 presence.ControllingClient.Close();
3797 return true; 3945 return true;
3798 } 3946 }
3799 3947
@@ -4401,34 +4549,66 @@ namespace OpenSim.Region.Framework.Scenes
4401 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4549 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4402 } 4550 }
4403 4551
4404 public int GetHealth() 4552 public int GetHealth(out int flags, out string message)
4405 { 4553 {
4406 // Returns: 4554 // Returns:
4407 // 1 = sim is up and accepting http requests. The heartbeat has 4555 // 1 = sim is up and accepting http requests. The heartbeat has
4408 // stopped and the sim is probably locked up, but a remote 4556 // stopped and the sim is probably locked up, but a remote
4409 // admin restart may succeed 4557 // admin restart may succeed
4410 // 4558 //
4411 // 2 = Sim is up and the heartbeat is running. The sim is likely 4559 // 2 = Sim is up and the heartbeat is running. The sim is likely
4412 // usable for people within and logins _may_ work 4560 // usable for people within
4561 //
4562 // 3 = Sim is up and one packet thread is running. Sim is
4563 // unstable and will not accept new logins
4413 // 4564 //
4414 // 3 = We have seen a new user enter within the past 4 minutes 4565 // 4 = Sim is up and both packet threads are running. Sim is
4566 // likely usable
4567 //
4568 // 5 = We have seen a new user enter within the past 4 minutes
4415 // which can be seen as positive confirmation of sim health 4569 // which can be seen as positive confirmation of sim health
4416 // 4570 //
4571
4572 flags = 0;
4573 message = String.Empty;
4574
4575 CheckHeartbeat();
4576
4577 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4578 {
4579 // We're still starting
4580 // 0 means "in startup", it can't happen another way, since
4581 // to get here, we must be able to accept http connections
4582 return 0;
4583 }
4584
4417 int health=1; // Start at 1, means we're up 4585 int health=1; // Start at 1, means we're up
4418 4586
4419 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4587 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4588 {
4420 health+=1; 4589 health+=1;
4421 else 4590 flags |= 1;
4591 }
4592
4593 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4594 {
4595 health+=1;
4596 flags |= 2;
4597 }
4598
4599 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4600 {
4601 health+=1;
4602 flags |= 4;
4603 }
4604
4605 if (flags != 7)
4422 return health; 4606 return health;
4423 4607
4424 // A login in the last 4 mins? We can't be doing too badly 4608 // A login in the last 4 mins? We can't be doing too badly
4425 // 4609 //
4426 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4610 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4427 health++; 4611 health++;
4428 else
4429 return health;
4430
4431 CheckHeartbeat();
4432 4612
4433 return health; 4613 return health;
4434 } 4614 }
@@ -4879,8 +5059,17 @@ namespace OpenSim.Region.Framework.Scenes
4879 { 5059 {
4880 float ominX, ominY, ominZ, omaxX, omaxY, omaxZ; 5060 float ominX, ominY, ominZ, omaxX, omaxY, omaxZ;
4881 5061
5062 Vector3 vec = g.AbsolutePosition;
5063
4882 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); 5064 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ);
4883 5065
5066 ominX += vec.X;
5067 omaxX += vec.X;
5068 ominY += vec.Y;
5069 omaxY += vec.Y;
5070 ominZ += vec.Z;
5071 omaxZ += vec.Z;
5072
4884 if (minX > ominX) 5073 if (minX > ominX)
4885 minX = ominX; 5074 minX = ominX;
4886 if (minY > ominY) 5075 if (minY > ominY)
@@ -4950,10 +5139,28 @@ namespace OpenSim.Region.Framework.Scenes
4950 }); 5139 });
4951 } 5140 }
4952 5141
4953 foreach (SceneObjectGroup grp in objectsToDelete) 5142 if (objectsToDelete.Count > 0)
5143 {
5144 m_log.DebugFormat("[SCENE]: Starting delete of {0} dropped attachments", objectsToDelete.Count);
5145 foreach (SceneObjectGroup grp in objectsToDelete)
5146 {
5147 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5148 DeleteSceneObject(grp, true);
5149 }
5150 m_log.Debug("[SCENE]: Finished dropped attachment deletion");
5151 }
5152 }
5153
5154 public void ThreadAlive(int threadCode)
5155 {
5156 switch(threadCode)
4954 { 5157 {
4955 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID); 5158 case 1: // Incoming
4956 DeleteSceneObject(grp, true); 5159 m_lastIncoming = Util.EnvironmentTickCount();
5160 break;
5161 case 2: // Incoming
5162 m_lastOutgoing = Util.EnvironmentTickCount();
5163 break;
4957 } 5164 }
4958 } 5165 }
4959 5166
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 a2ed54f..7eebb99 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();
@@ -259,6 +273,33 @@ namespace OpenSim.Region.Framework.Scenes
259 protected internal bool AddRestoredSceneObject( 273 protected internal bool AddRestoredSceneObject(
260 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 274 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
261 { 275 {
276 if (!m_parentScene.CombineRegions)
277 {
278 // KF: Check for out-of-region, move inside and make static.
279 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
280 sceneObject.RootPart.GroupPosition.Y,
281 sceneObject.RootPart.GroupPosition.Z);
282 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 ||
283 npos.X > Constants.RegionSize ||
284 npos.Y > Constants.RegionSize))
285 {
286 if (npos.X < 0.0) npos.X = 1.0f;
287 if (npos.Y < 0.0) npos.Y = 1.0f;
288 if (npos.Z < 0.0) npos.Z = 0.0f;
289 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
290 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
291
292 foreach (SceneObjectPart part in sceneObject.Parts)
293 {
294 part.GroupPosition = npos;
295 }
296 sceneObject.RootPart.Velocity = Vector3.Zero;
297 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
298 sceneObject.RootPart.Acceleration = Vector3.Zero;
299 sceneObject.RootPart.Velocity = Vector3.Zero;
300 }
301 }
302
262 if (attachToBackup && (!alreadyPersisted)) 303 if (attachToBackup && (!alreadyPersisted))
263 { 304 {
264 sceneObject.ForceInventoryPersistence(); 305 sceneObject.ForceInventoryPersistence();
@@ -458,6 +499,30 @@ namespace OpenSim.Region.Framework.Scenes
458 m_updateList[obj.UUID] = obj; 499 m_updateList[obj.UUID] = obj;
459 } 500 }
460 501
502 public void FireAttachToBackup(SceneObjectGroup obj)
503 {
504 if (OnAttachToBackup != null)
505 {
506 OnAttachToBackup(obj);
507 }
508 }
509
510 public void FireDetachFromBackup(SceneObjectGroup obj)
511 {
512 if (OnDetachFromBackup != null)
513 {
514 OnDetachFromBackup(obj);
515 }
516 }
517
518 public void FireChangeBackup(SceneObjectGroup obj)
519 {
520 if (OnChangeBackup != null)
521 {
522 OnChangeBackup(obj);
523 }
524 }
525
461 /// <summary> 526 /// <summary>
462 /// Process all pending updates 527 /// Process all pending updates
463 /// </summary> 528 /// </summary>
@@ -592,7 +657,8 @@ namespace OpenSim.Region.Framework.Scenes
592 657
593 Entities[presence.UUID] = presence; 658 Entities[presence.UUID] = presence;
594 659
595 lock (m_presenceLock) 660 m_scenePresencesLock.EnterWriteLock();
661 try
596 { 662 {
597 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 663 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
598 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 664 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -616,6 +682,10 @@ namespace OpenSim.Region.Framework.Scenes
616 m_scenePresenceMap = newmap; 682 m_scenePresenceMap = newmap;
617 m_scenePresenceArray = newlist; 683 m_scenePresenceArray = newlist;
618 } 684 }
685 finally
686 {
687 m_scenePresencesLock.ExitWriteLock();
688 }
619 } 689 }
620 690
621 /// <summary> 691 /// <summary>
@@ -630,7 +700,8 @@ namespace OpenSim.Region.Framework.Scenes
630 agentID); 700 agentID);
631 } 701 }
632 702
633 lock (m_presenceLock) 703 m_scenePresencesLock.EnterWriteLock();
704 try
634 { 705 {
635 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 706 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
636 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 707 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -652,6 +723,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); 723 m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
653 } 724 }
654 } 725 }
726 finally
727 {
728 m_scenePresencesLock.ExitWriteLock();
729 }
655 } 730 }
656 731
657 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 732 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -775,6 +850,11 @@ namespace OpenSim.Region.Framework.Scenes
775 return m_scenePresenceArray; 850 return m_scenePresenceArray;
776 } 851 }
777 852
853 public int GetNumberOfScenePresences()
854 {
855 return m_scenePresenceArray.Count;
856 }
857
778 /// <summary> 858 /// <summary>
779 /// Request a scene presence by UUID. Fast, indexed lookup. 859 /// Request a scene presence by UUID. Fast, indexed lookup.
780 /// </summary> 860 /// </summary>
@@ -1068,9 +1148,11 @@ namespace OpenSim.Region.Framework.Scenes
1068 /// <param name="action"></param> 1148 /// <param name="action"></param>
1069 protected internal void ForEachSOG(Action<SceneObjectGroup> action) 1149 protected internal void ForEachSOG(Action<SceneObjectGroup> action)
1070 { 1150 {
1071 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); 1151 EntityBase[] objlist = Entities.GetAllByType<SceneObjectGroup>();
1072 foreach (SceneObjectGroup obj in objlist) 1152 foreach (EntityBase ent in objlist)
1073 { 1153 {
1154 SceneObjectGroup obj = (SceneObjectGroup)ent;
1155
1074 try 1156 try
1075 { 1157 {
1076 action(obj); 1158 action(obj);
@@ -1281,8 +1363,13 @@ namespace OpenSim.Region.Framework.Scenes
1281 { 1363 {
1282 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1364 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1283 { 1365 {
1284 if (m_parentScene.AttachmentsModule != null) 1366 // Set the new attachment point data in the object
1285 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1367 byte attachmentPoint = group.GetAttachmentPoint();
1368 group.UpdateGroupPosition(pos);
1369 group.RootPart.IsAttachment = false;
1370 group.AbsolutePosition = group.RootPart.AttachedPos;
1371 group.SetAttachmentPoint(attachmentPoint);
1372 group.HasGroupChanged = true;
1286 } 1373 }
1287 else 1374 else
1288 { 1375 {
@@ -1526,10 +1613,13 @@ namespace OpenSim.Region.Framework.Scenes
1526 /// <param name="childPrims"></param> 1613 /// <param name="childPrims"></param>
1527 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1614 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1528 { 1615 {
1616 SceneObjectGroup parentGroup = root.ParentGroup;
1617 if (parentGroup == null) return;
1529 Monitor.Enter(m_updateLock); 1618 Monitor.Enter(m_updateLock);
1619
1530 try 1620 try
1531 { 1621 {
1532 SceneObjectGroup parentGroup = root.ParentGroup; 1622 parentGroup.areUpdatesSuspended = true;
1533 1623
1534 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1624 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1535 if (parentGroup != null) 1625 if (parentGroup != null)
@@ -1541,11 +1631,6 @@ namespace OpenSim.Region.Framework.Scenes
1541 1631
1542 if (child != null) 1632 if (child != null)
1543 { 1633 {
1544 // Make sure no child prim is set for sale
1545 // So that, on delink, no prims are unwittingly
1546 // left for sale and sold off
1547 child.RootPart.ObjectSaleType = 0;
1548 child.RootPart.SalePrice = 10;
1549 childGroups.Add(child); 1634 childGroups.Add(child);
1550 } 1635 }
1551 } 1636 }
@@ -1568,12 +1653,13 @@ namespace OpenSim.Region.Framework.Scenes
1568 // occur on link to invoke this elsewhere (such as object selection) 1653 // occur on link to invoke this elsewhere (such as object selection)
1569 parentGroup.RootPart.CreateSelected = true; 1654 parentGroup.RootPart.CreateSelected = true;
1570 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1655 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1571 parentGroup.HasGroupChanged = true;
1572 parentGroup.ScheduleGroupForFullUpdate();
1573
1574 } 1656 }
1575 finally 1657 finally
1576 { 1658 {
1659 parentGroup.areUpdatesSuspended = false;
1660 parentGroup.HasGroupChanged = true;
1661 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1662 parentGroup.ScheduleGroupForFullUpdate();
1577 Monitor.Exit(m_updateLock); 1663 Monitor.Exit(m_updateLock);
1578 } 1664 }
1579 } 1665 }
@@ -1605,21 +1691,24 @@ namespace OpenSim.Region.Framework.Scenes
1605 1691
1606 SceneObjectGroup group = part.ParentGroup; 1692 SceneObjectGroup group = part.ParentGroup;
1607 if (!affectedGroups.Contains(group)) 1693 if (!affectedGroups.Contains(group))
1694 {
1695 group.areUpdatesSuspended = true;
1608 affectedGroups.Add(group); 1696 affectedGroups.Add(group);
1697 }
1609 } 1698 }
1610 } 1699 }
1611 } 1700 }
1612 1701
1613 foreach (SceneObjectPart child in childParts) 1702 if (childParts.Count > 0)
1614 { 1703 {
1615 // Unlink all child parts from their groups 1704 foreach (SceneObjectPart child in childParts)
1616 // 1705 {
1617 child.ParentGroup.DelinkFromGroup(child, true); 1706 // Unlink all child parts from their groups
1618 1707 //
1619 // These are not in affected groups and will not be 1708 child.ParentGroup.DelinkFromGroup(child, true);
1620 // handled further. Do the honors here. 1709 child.ParentGroup.HasGroupChanged = true;
1621 child.ParentGroup.HasGroupChanged = true; 1710 child.ParentGroup.ScheduleGroupForFullUpdate();
1622 child.ParentGroup.ScheduleGroupForFullUpdate(); 1711 }
1623 } 1712 }
1624 1713
1625 foreach (SceneObjectPart root in rootParts) 1714 foreach (SceneObjectPart root in rootParts)
@@ -1629,56 +1718,68 @@ namespace OpenSim.Region.Framework.Scenes
1629 // However, editing linked parts and unlinking may be different 1718 // However, editing linked parts and unlinking may be different
1630 // 1719 //
1631 SceneObjectGroup group = root.ParentGroup; 1720 SceneObjectGroup group = root.ParentGroup;
1721 group.areUpdatesSuspended = true;
1632 1722
1633 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1723 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1634 int numChildren = newSet.Count; 1724 int numChildren = newSet.Count;
1635 1725
1726 if (numChildren == 1)
1727 break;
1728
1636 // If there are prims left in a link set, but the root is 1729 // If there are prims left in a link set, but the root is
1637 // slated for unlink, we need to do this 1730 // slated for unlink, we need to do this
1731 // Unlink the remaining set
1638 // 1732 //
1639 if (numChildren != 1) 1733 bool sendEventsToRemainder = true;
1640 { 1734 if (numChildren > 1)
1641 // Unlink the remaining set 1735 sendEventsToRemainder = false;
1642 //
1643 bool sendEventsToRemainder = true;
1644 if (numChildren > 1)
1645 sendEventsToRemainder = false;
1646 1736
1647 foreach (SceneObjectPart p in newSet) 1737 foreach (SceneObjectPart p in newSet)
1738 {
1739 if (p != group.RootPart)
1648 { 1740 {
1649 if (p != group.RootPart) 1741 group.DelinkFromGroup(p, sendEventsToRemainder);
1650 group.DelinkFromGroup(p, sendEventsToRemainder); 1742 if (numChildren > 2)
1743 {
1744 p.ParentGroup.areUpdatesSuspended = true;
1745 }
1746 else
1747 {
1748 p.ParentGroup.HasGroupChanged = true;
1749 p.ParentGroup.ScheduleGroupForFullUpdate();
1750 }
1651 } 1751 }
1752 }
1753
1754 // If there is more than one prim remaining, we
1755 // need to re-link
1756 //
1757 if (numChildren > 2)
1758 {
1759 // Remove old root
1760 //
1761 if (newSet.Contains(root))
1762 newSet.Remove(root);
1652 1763
1653 // If there is more than one prim remaining, we 1764 // Preserve link ordering
1654 // need to re-link
1655 // 1765 //
1656 if (numChildren > 2) 1766 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1657 { 1767 {
1658 // Remove old root 1768 return a.LinkNum.CompareTo(b.LinkNum);
1659 // 1769 });
1660 if (newSet.Contains(root))
1661 newSet.Remove(root);
1662
1663 // Preserve link ordering
1664 //
1665 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1666 {
1667 return a.LinkNum.CompareTo(b.LinkNum);
1668 });
1669 1770
1670 // Determine new root 1771 // Determine new root
1671 // 1772 //
1672 SceneObjectPart newRoot = newSet[0]; 1773 SceneObjectPart newRoot = newSet[0];
1673 newSet.RemoveAt(0); 1774 newSet.RemoveAt(0);
1674 1775
1675 foreach (SceneObjectPart newChild in newSet) 1776 foreach (SceneObjectPart newChild in newSet)
1676 newChild.UpdateFlag = 0; 1777 newChild.UpdateFlag = 0;
1677 1778
1678 LinkObjects(newRoot, newSet); 1779 newRoot.ParentGroup.areUpdatesSuspended = true;
1679 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1780 LinkObjects(newRoot, newSet);
1680 affectedGroups.Add(newRoot.ParentGroup); 1781 if (!affectedGroups.Contains(newRoot.ParentGroup))
1681 } 1782 affectedGroups.Add(newRoot.ParentGroup);
1682 } 1783 }
1683 } 1784 }
1684 1785
@@ -1686,8 +1787,14 @@ namespace OpenSim.Region.Framework.Scenes
1686 // 1787 //
1687 foreach (SceneObjectGroup g in affectedGroups) 1788 foreach (SceneObjectGroup g in affectedGroups)
1688 { 1789 {
1790 // Child prims that have been unlinked and deleted will
1791 // return unless the root is deleted. This will remove them
1792 // from the database. They will be rewritten immediately,
1793 // minus the rows for the unlinked child prims.
1794 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1689 g.TriggerScriptChangedEvent(Changed.LINK); 1795 g.TriggerScriptChangedEvent(Changed.LINK);
1690 g.HasGroupChanged = true; // Persist 1796 g.HasGroupChanged = true; // Persist
1797 g.areUpdatesSuspended = false;
1691 g.ScheduleGroupForFullUpdate(); 1798 g.ScheduleGroupForFullUpdate();
1692 } 1799 }
1693 } 1800 }
@@ -1802,9 +1909,6 @@ namespace OpenSim.Region.Framework.Scenes
1802 child.ApplyNextOwnerPermissions(); 1909 child.ApplyNextOwnerPermissions();
1803 } 1910 }
1804 } 1911 }
1805
1806 copy.RootPart.ObjectSaleType = 0;
1807 copy.RootPart.SalePrice = 10;
1808 } 1912 }
1809 1913
1810 Entities.Add(copy); 1914 Entities.Add(copy);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 982e280..50521c4 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();
@@ -376,6 +372,9 @@ namespace OpenSim.Region.Framework.Scenes
376 372
377 public void ResumeScripts() 373 public void ResumeScripts()
378 { 374 {
375 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
376 return;
377
379 SceneObjectPart[] parts = m_parts.GetArray(); 378 SceneObjectPart[] parts = m_parts.GetArray();
380 for (int i = 0; i < parts.Length; i++) 379 for (int i = 0; i < parts.Length; i++)
381 parts[i].Inventory.ResumeScripts(); 380 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index f17fb28..72443b9 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
@@ -141,8 +193,19 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 193 return false;
142 if (m_scene.ShuttingDown) 194 if (m_scene.ShuttingDown)
143 return true; 195 return true;
196
197 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
198 {
199 m_maxPersistTime = m_scene.m_persistAfter;
200 m_minPersistTime = m_scene.m_dontPersistBefore;
201 }
202
144 long currentTime = DateTime.Now.Ticks; 203 long currentTime = DateTime.Now.Ticks;
145 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 204
205 if (timeLastChanged == 0) timeLastChanged = currentTime;
206 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
207
208 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
146 return true; 209 return true;
147 return false; 210 return false;
148 } 211 }
@@ -185,10 +248,10 @@ namespace OpenSim.Region.Framework.Scenes
185 248
186 private bool m_scriptListens_atTarget; 249 private bool m_scriptListens_atTarget;
187 private bool m_scriptListens_notAtTarget; 250 private bool m_scriptListens_notAtTarget;
188
189 private bool m_scriptListens_atRotTarget; 251 private bool m_scriptListens_atRotTarget;
190 private bool m_scriptListens_notAtRotTarget; 252 private bool m_scriptListens_notAtRotTarget;
191 253
254 public bool m_dupeInProgress = false;
192 internal Dictionary<UUID, string> m_savedScriptState; 255 internal Dictionary<UUID, string> m_savedScriptState;
193 256
194 #region Properties 257 #region Properties
@@ -228,7 +291,13 @@ namespace OpenSim.Region.Framework.Scenes
228 public virtual Quaternion Rotation 291 public virtual Quaternion Rotation
229 { 292 {
230 get { return m_rotation; } 293 get { return m_rotation; }
231 set { m_rotation = value; } 294 set {
295 foreach(SceneObjectPart p in m_parts.GetArray())
296 {
297 p.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
298 }
299 m_rotation = value;
300 }
232 } 301 }
233 302
234 public Quaternion GroupRotation 303 public Quaternion GroupRotation
@@ -302,7 +371,11 @@ namespace OpenSim.Region.Framework.Scenes
302 { 371 {
303 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 372 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
304 } 373 }
305 374
375 foreach (SceneObjectPart part in m_parts.GetArray())
376 {
377 part.IgnoreUndoUpdate = true;
378 }
306 if (RootPart.GetStatusSandbox()) 379 if (RootPart.GetStatusSandbox())
307 { 380 {
308 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 381 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -313,10 +386,31 @@ namespace OpenSim.Region.Framework.Scenes
313 return; 386 return;
314 } 387 }
315 } 388 }
316
317 SceneObjectPart[] parts = m_parts.GetArray(); 389 SceneObjectPart[] parts = m_parts.GetArray();
318 for (int i = 0; i < parts.Length; i++) 390 foreach (SceneObjectPart part in parts)
319 parts[i].GroupPosition = val; 391 {
392 part.IgnoreUndoUpdate = false;
393 part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
394 part.GroupPosition = val;
395 if (!m_dupeInProgress)
396 {
397 part.TriggerScriptChangedEvent(Changed.POSITION);
398 }
399 }
400 if (!m_dupeInProgress)
401 {
402 foreach (ScenePresence av in m_linkedAvatars)
403 {
404 SceneObjectPart p;
405 if (m_parts.TryGetValue(av.LinkedPrim, out p))
406 {
407 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
408 av.AbsolutePosition += offset;
409 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
410 av.SendAvatarDataToAllAgents();
411 }
412 }
413 }
320 414
321 //if (m_rootPart.PhysActor != null) 415 //if (m_rootPart.PhysActor != null)
322 //{ 416 //{
@@ -467,6 +561,7 @@ namespace OpenSim.Region.Framework.Scenes
467 /// </summary> 561 /// </summary>
468 public SceneObjectGroup() 562 public SceneObjectGroup()
469 { 563 {
564
470 } 565 }
471 566
472 /// <summary> 567 /// <summary>
@@ -483,7 +578,7 @@ namespace OpenSim.Region.Framework.Scenes
483 /// Constructor. This object is added to the scene later via AttachToScene() 578 /// Constructor. This object is added to the scene later via AttachToScene()
484 /// </summary> 579 /// </summary>
485 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 580 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
486 { 581 {
487 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 582 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
488 } 583 }
489 584
@@ -531,6 +626,9 @@ namespace OpenSim.Region.Framework.Scenes
531 /// </summary> 626 /// </summary>
532 public virtual void AttachToBackup() 627 public virtual void AttachToBackup()
533 { 628 {
629 if (IsAttachment) return;
630 m_scene.SceneGraph.FireAttachToBackup(this);
631
534 if (InSceneBackup) 632 if (InSceneBackup)
535 { 633 {
536 //m_log.DebugFormat( 634 //m_log.DebugFormat(
@@ -646,9 +744,9 @@ namespace OpenSim.Region.Framework.Scenes
646 result.normal = inter.normal; 744 result.normal = inter.normal;
647 result.distance = inter.distance; 745 result.distance = inter.distance;
648 } 746 }
747
649 } 748 }
650 } 749 }
651
652 return result; 750 return result;
653 } 751 }
654 752
@@ -668,17 +766,19 @@ namespace OpenSim.Region.Framework.Scenes
668 minZ = 8192f; 766 minZ = 8192f;
669 767
670 SceneObjectPart[] parts = m_parts.GetArray(); 768 SceneObjectPart[] parts = m_parts.GetArray();
671 for (int i = 0; i < parts.Length; i++) 769 foreach (SceneObjectPart part in parts)
672 { 770 {
673 SceneObjectPart part = parts[i];
674
675 Vector3 worldPos = part.GetWorldPosition(); 771 Vector3 worldPos = part.GetWorldPosition();
676 Vector3 offset = worldPos - AbsolutePosition; 772 Vector3 offset = worldPos - AbsolutePosition;
677 Quaternion worldRot; 773 Quaternion worldRot;
678 if (part.ParentID == 0) 774 if (part.ParentID == 0)
775 {
679 worldRot = part.RotationOffset; 776 worldRot = part.RotationOffset;
777 }
680 else 778 else
779 {
681 worldRot = part.GetWorldRotation(); 780 worldRot = part.GetWorldRotation();
781 }
682 782
683 Vector3 frontTopLeft; 783 Vector3 frontTopLeft;
684 Vector3 frontTopRight; 784 Vector3 frontTopRight;
@@ -690,6 +790,8 @@ namespace OpenSim.Region.Framework.Scenes
690 Vector3 backBottomLeft; 790 Vector3 backBottomLeft;
691 Vector3 backBottomRight; 791 Vector3 backBottomRight;
692 792
793 // Vector3[] corners = new Vector3[8];
794
693 Vector3 orig = Vector3.Zero; 795 Vector3 orig = Vector3.Zero;
694 796
695 frontTopLeft.X = orig.X - (part.Scale.X / 2); 797 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -724,6 +826,38 @@ namespace OpenSim.Region.Framework.Scenes
724 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 826 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
725 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 827 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
726 828
829
830
831 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
832 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
833 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
834 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
835 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
836 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
837 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
838 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
839
840 //for (int i = 0; i < 8; i++)
841 //{
842 // corners[i] = corners[i] * worldRot;
843 // corners[i] += offset;
844
845 // if (corners[i].X > maxX)
846 // maxX = corners[i].X;
847 // if (corners[i].X < minX)
848 // minX = corners[i].X;
849
850 // if (corners[i].Y > maxY)
851 // maxY = corners[i].Y;
852 // if (corners[i].Y < minY)
853 // minY = corners[i].Y;
854
855 // if (corners[i].Z > maxZ)
856 // maxZ = corners[i].Y;
857 // if (corners[i].Z < minZ)
858 // minZ = corners[i].Z;
859 //}
860
727 frontTopLeft = frontTopLeft * worldRot; 861 frontTopLeft = frontTopLeft * worldRot;
728 frontTopRight = frontTopRight * worldRot; 862 frontTopRight = frontTopRight * worldRot;
729 frontBottomLeft = frontBottomLeft * worldRot; 863 frontBottomLeft = frontBottomLeft * worldRot;
@@ -745,6 +879,15 @@ namespace OpenSim.Region.Framework.Scenes
745 backTopLeft += offset; 879 backTopLeft += offset;
746 backTopRight += offset; 880 backTopRight += offset;
747 881
882 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
883 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
884 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
885 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
886 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
887 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
888 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
889 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
890
748 if (frontTopRight.X > maxX) 891 if (frontTopRight.X > maxX)
749 maxX = frontTopRight.X; 892 maxX = frontTopRight.X;
750 if (frontTopLeft.X > maxX) 893 if (frontTopLeft.X > maxX)
@@ -890,15 +1033,20 @@ namespace OpenSim.Region.Framework.Scenes
890 1033
891 public void SaveScriptedState(XmlTextWriter writer) 1034 public void SaveScriptedState(XmlTextWriter writer)
892 { 1035 {
1036 SaveScriptedState(writer, false);
1037 }
1038
1039 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1040 {
893 XmlDocument doc = new XmlDocument(); 1041 XmlDocument doc = new XmlDocument();
894 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1042 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
895 1043
896 SceneObjectPart[] parts = m_parts.GetArray(); 1044 SceneObjectPart[] parts = m_parts.GetArray();
897 for (int i = 0; i < parts.Length; i++) 1045 for (int i = 0; i < parts.Length; i++)
898 { 1046 {
899 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1047 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
900 foreach (KeyValuePair<UUID, string> kvp in pstates) 1048 foreach (KeyValuePair<UUID, string> kvp in pstates)
901 states.Add(kvp.Key, kvp.Value); 1049 states[kvp.Key] = kvp.Value;
902 } 1050 }
903 1051
904 if (states.Count > 0) 1052 if (states.Count > 0)
@@ -917,6 +1065,118 @@ namespace OpenSim.Region.Framework.Scenes
917 } 1065 }
918 } 1066 }
919 1067
1068 /// <summary>
1069 /// Add the avatar to this linkset (avatar is sat).
1070 /// </summary>
1071 /// <param name="agentID"></param>
1072 public void AddAvatar(UUID agentID)
1073 {
1074 ScenePresence presence;
1075 if (m_scene.TryGetScenePresence(agentID, out presence))
1076 {
1077 if (!m_linkedAvatars.Contains(presence))
1078 {
1079 m_linkedAvatars.Add(presence);
1080 }
1081 }
1082 }
1083
1084 /// <summary>
1085 /// Delete the avatar from this linkset (avatar is unsat).
1086 /// </summary>
1087 /// <param name="agentID"></param>
1088 public void DeleteAvatar(UUID agentID)
1089 {
1090 ScenePresence presence;
1091 if (m_scene.TryGetScenePresence(agentID, out presence))
1092 {
1093 if (m_linkedAvatars.Contains(presence))
1094 {
1095 m_linkedAvatars.Remove(presence);
1096 }
1097 }
1098 }
1099
1100 /// <summary>
1101 /// Returns the list of linked presences (avatars sat on this group)
1102 /// </summary>
1103 /// <param name="agentID"></param>
1104 public List<ScenePresence> GetLinkedAvatars()
1105 {
1106 return m_linkedAvatars;
1107 }
1108
1109 /// <summary>
1110 /// Attach this scene object to the given avatar.
1111 /// </summary>
1112 /// <param name="agentID"></param>
1113 /// <param name="attachmentpoint"></param>
1114 /// <param name="AttachOffset"></param>
1115 public void AttachToAgent(UUID agentID, uint attachmentpoint, Vector3 AttachOffset, bool silent)
1116 {
1117 ScenePresence avatar = m_scene.GetScenePresence(agentID);
1118 if (avatar != null)
1119 {
1120 // don't attach attachments to child agents
1121 if (avatar.IsChildAgent) return;
1122
1123// m_log.DebugFormat("[SOG]: Adding attachment {0} to avatar {1}", Name, avatar.Name);
1124
1125 DetachFromBackup();
1126
1127 // Remove from database and parcel prim count
1128 m_scene.DeleteFromStorage(UUID);
1129 m_scene.EventManager.TriggerParcelPrimCountTainted();
1130
1131 m_rootPart.AttachedAvatar = agentID;
1132
1133 //Anakin Lohner bug #3839
1134 lock (m_parts)
1135 {
1136 foreach (SceneObjectPart p in m_parts.GetArray())
1137 {
1138 p.AttachedAvatar = agentID;
1139 }
1140 }
1141
1142 if (m_rootPart.PhysActor != null)
1143 {
1144 m_scene.PhysicsScene.RemovePrim(m_rootPart.PhysActor);
1145 m_rootPart.PhysActor = null;
1146 }
1147
1148 AbsolutePosition = AttachOffset;
1149 m_rootPart.AttachedPos = AttachOffset;
1150 m_rootPart.IsAttachment = true;
1151
1152 m_rootPart.SetParentLocalId(avatar.LocalId);
1153 SetAttachmentPoint(Convert.ToByte(attachmentpoint));
1154
1155 avatar.AddAttachment(this);
1156
1157 if (!silent)
1158 {
1159 // Killing it here will cause the client to deselect it
1160 // It then reappears on the avatar, deselected
1161 // through the full update below
1162 //
1163 if (IsSelected)
1164 {
1165 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1166 }
1167
1168 IsSelected = false; // fudge....
1169 ScheduleGroupForFullUpdate();
1170 }
1171 }
1172 else
1173 {
1174 m_log.WarnFormat(
1175 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1176 UUID, agentID, Scene.RegionInfo.RegionName);
1177 }
1178 }
1179
920 public byte GetAttachmentPoint() 1180 public byte GetAttachmentPoint()
921 { 1181 {
922 return m_rootPart.Shape.State; 1182 return m_rootPart.Shape.State;
@@ -1043,7 +1303,10 @@ namespace OpenSim.Region.Framework.Scenes
1043 public void AddPart(SceneObjectPart part) 1303 public void AddPart(SceneObjectPart part)
1044 { 1304 {
1045 part.SetParent(this); 1305 part.SetParent(this);
1046 part.LinkNum = m_parts.Add(part.UUID, part); 1306 m_parts.Add(part.UUID, part);
1307
1308 part.LinkNum = m_parts.Count;
1309
1047 if (part.LinkNum == 2 && RootPart != null) 1310 if (part.LinkNum == 2 && RootPart != null)
1048 RootPart.LinkNum = 1; 1311 RootPart.LinkNum = 1;
1049 } 1312 }
@@ -1127,7 +1390,7 @@ namespace OpenSim.Region.Framework.Scenes
1127 1390
1128 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1391 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1129 { 1392 {
1130 part.StoreUndoState(); 1393 part.StoreUndoState(UndoType.STATE_PRIM_ALL);
1131 part.OnGrab(offsetPos, remoteClient); 1394 part.OnGrab(offsetPos, remoteClient);
1132 } 1395 }
1133 1396
@@ -1147,6 +1410,11 @@ namespace OpenSim.Region.Framework.Scenes
1147 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1410 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1148 public void DeleteGroupFromScene(bool silent) 1411 public void DeleteGroupFromScene(bool silent)
1149 { 1412 {
1413 // We need to keep track of this state in case this group is still queued for backup.
1414 m_isDeleted = true;
1415
1416 DetachFromBackup();
1417
1150 SceneObjectPart[] parts = m_parts.GetArray(); 1418 SceneObjectPart[] parts = m_parts.GetArray();
1151 for (int i = 0; i < parts.Length; i++) 1419 for (int i = 0; i < parts.Length; i++)
1152 { 1420 {
@@ -1158,13 +1426,11 @@ namespace OpenSim.Region.Framework.Scenes
1158 avatar.StandUp(); 1426 avatar.StandUp();
1159 1427
1160 if (!silent) 1428 if (!silent)
1161 {
1162 part.UpdateFlag = 0; 1429 part.UpdateFlag = 0;
1163 if (part == m_rootPart)
1164 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1165 }
1166 }); 1430 });
1167 } 1431 }
1432
1433
1168 } 1434 }
1169 1435
1170 public void AddScriptLPS(int count) 1436 public void AddScriptLPS(int count)
@@ -1261,7 +1527,12 @@ namespace OpenSim.Region.Framework.Scenes
1261 1527
1262 public void SetOwnerId(UUID userId) 1528 public void SetOwnerId(UUID userId)
1263 { 1529 {
1264 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1530 ForEachPart(delegate(SceneObjectPart part)
1531 {
1532
1533 part.OwnerID = userId;
1534
1535 });
1265 } 1536 }
1266 1537
1267 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1538 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1293,11 +1564,17 @@ namespace OpenSim.Region.Framework.Scenes
1293 return; 1564 return;
1294 } 1565 }
1295 1566
1567 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1568 return;
1569
1296 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1570 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1297 // any exception propogate upwards. 1571 // any exception propogate upwards.
1298 try 1572 try
1299 { 1573 {
1300 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1574 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1575 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1576 m_scene.LoadingPrims) // Land may not be valid yet
1577
1301 { 1578 {
1302 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1579 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1303 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1580 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1322,6 +1599,7 @@ namespace OpenSim.Region.Framework.Scenes
1322 } 1599 }
1323 } 1600 }
1324 } 1601 }
1602
1325 } 1603 }
1326 1604
1327 if (HasGroupChanged) 1605 if (HasGroupChanged)
@@ -1329,6 +1607,20 @@ namespace OpenSim.Region.Framework.Scenes
1329 // don't backup while it's selected or you're asking for changes mid stream. 1607 // don't backup while it's selected or you're asking for changes mid stream.
1330 if (isTimeToPersist() || forcedBackup) 1608 if (isTimeToPersist() || forcedBackup)
1331 { 1609 {
1610 if (m_rootPart.PhysActor != null &&
1611 (!m_rootPart.PhysActor.IsPhysical))
1612 {
1613 // Possible ghost prim
1614 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1615 {
1616 foreach (SceneObjectPart part in m_parts.GetArray())
1617 {
1618 // Re-set physics actor positions and
1619 // orientations
1620 part.GroupPosition = m_rootPart.GroupPosition;
1621 }
1622 }
1623 }
1332// m_log.DebugFormat( 1624// m_log.DebugFormat(
1333// "[SCENE]: Storing {0}, {1} in {2}", 1625// "[SCENE]: Storing {0}, {1} in {2}",
1334// Name, UUID, m_scene.RegionInfo.RegionName); 1626// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1392,81 +1684,90 @@ namespace OpenSim.Region.Framework.Scenes
1392 /// <returns></returns> 1684 /// <returns></returns>
1393 public SceneObjectGroup Copy(bool userExposed) 1685 public SceneObjectGroup Copy(bool userExposed)
1394 { 1686 {
1395 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1687 SceneObjectGroup dupe;
1396 dupe.m_isBackedUp = false; 1688 try
1397 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 1689 {
1398 1690 m_dupeInProgress = true;
1399 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 1691 dupe = (SceneObjectGroup)MemberwiseClone();
1400 // attachments do not bordercross while they're being duplicated. This is hacktastic! 1692 dupe.m_isBackedUp = false;
1401 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! 1693 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1402 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1403 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1404 // then restore it's attachment state
1405
1406 // This is only necessary when userExposed is false!
1407 1694
1408 bool previousAttachmentStatus = dupe.RootPart.IsAttachment; 1695 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1409 1696 // attachments do not bordercross while they're being duplicated. This is hacktastic!
1410 if (!userExposed) 1697 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
1411 dupe.RootPart.IsAttachment = true; 1698 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1699 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1700 // then restore it's attachment state
1412 1701
1413 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 1702 // This is only necessary when userExposed is false!
1414 1703
1415 if (!userExposed) 1704 bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
1416 {
1417 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1418 }
1419 1705
1420 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 1706 if (!userExposed)
1421 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 1707 dupe.RootPart.IsAttachment = true;
1422 1708
1423 if (userExposed) 1709 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
1424 dupe.m_rootPart.TrimPermissions();
1425 1710
1426 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1711 if (!userExposed)
1427
1428 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1429 { 1712 {
1430 return p1.LinkNum.CompareTo(p2.LinkNum); 1713 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1431 } 1714 }
1432 );
1433 1715
1434 foreach (SceneObjectPart part in partList) 1716 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1435 { 1717 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1436 if (part.UUID != m_rootPart.UUID) 1718
1719 if (userExposed)
1720 dupe.m_rootPart.TrimPermissions();
1721
1722 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1723
1724 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1725 {
1726 return p1.LinkNum.CompareTo(p2.LinkNum);
1727 }
1728 );
1729
1730 foreach (SceneObjectPart part in partList)
1437 { 1731 {
1438 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 1732 if (part.UUID != m_rootPart.UUID)
1439 newPart.LinkNum = part.LinkNum; 1733 {
1440 } 1734 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1441 1735
1442 // Need to duplicate the physics actor as well 1736 newPart.LinkNum = part.LinkNum;
1443 if (part.PhysActor != null && userExposed) 1737 }
1738
1739 // Need to duplicate the physics actor as well
1740 if (part.PhysActor != null && userExposed)
1741 {
1742 PrimitiveBaseShape pbs = part.Shape;
1743
1744 part.PhysActor
1745 = m_scene.PhysicsScene.AddPrimShape(
1746 string.Format("{0}/{1}", part.Name, part.UUID),
1747 pbs,
1748 part.AbsolutePosition,
1749 part.Scale,
1750 part.RotationOffset,
1751 part.PhysActor.IsPhysical);
1752 part.PhysActor.SetMaterial((int)part.Material);
1753
1754 part.PhysActor.LocalID = part.LocalId;
1755 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1756 }
1757 }
1758 if (userExposed)
1444 { 1759 {
1445 PrimitiveBaseShape pbs = part.Shape; 1760 dupe.UpdateParentIDs();
1446 1761 dupe.HasGroupChanged = true;
1447 part.PhysActor 1762 dupe.AttachToBackup();
1448 = m_scene.PhysicsScene.AddPrimShape( 1763
1449 string.Format("{0}/{1}", part.Name, part.UUID), 1764 ScheduleGroupForFullUpdate();
1450 pbs,
1451 part.AbsolutePosition,
1452 part.Scale,
1453 part.RotationOffset,
1454 part.PhysActor.IsPhysical);
1455
1456 part.PhysActor.LocalID = part.LocalId;
1457 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1458 } 1765 }
1459 } 1766 }
1460 1767 finally
1461 if (userExposed)
1462 { 1768 {
1463 dupe.UpdateParentIDs(); 1769 m_dupeInProgress = false;
1464 dupe.HasGroupChanged = true;
1465 dupe.AttachToBackup();
1466
1467 ScheduleGroupForFullUpdate();
1468 } 1770 }
1469
1470 return dupe; 1771 return dupe;
1471 } 1772 }
1472 1773
@@ -1657,13 +1958,40 @@ namespace OpenSim.Region.Framework.Scenes
1657 } 1958 }
1658 } 1959 }
1659 1960
1961 public void rotLookAt(Quaternion target, float strength, float damping)
1962 {
1963 SceneObjectPart rootpart = m_rootPart;
1964 if (rootpart != null)
1965 {
1966 if (IsAttachment)
1967 {
1968 /*
1969 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1970 if (avatar != null)
1971 {
1972 Rotate the Av?
1973 } */
1974 }
1975 else
1976 {
1977 if (rootpart.PhysActor != null)
1978 { // APID must be implemented in your physics system for this to function.
1979 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1980 rootpart.PhysActor.APIDStrength = strength;
1981 rootpart.PhysActor.APIDDamping = damping;
1982 rootpart.PhysActor.APIDActive = true;
1983 }
1984 }
1985 }
1986 }
1987
1660 public void stopLookAt() 1988 public void stopLookAt()
1661 { 1989 {
1662 SceneObjectPart rootpart = m_rootPart; 1990 SceneObjectPart rootpart = m_rootPart;
1663 if (rootpart != null) 1991 if (rootpart != null)
1664 { 1992 {
1665 if (rootpart.PhysActor != null) 1993 if (rootpart.PhysActor != null)
1666 { 1994 { // APID must be implemented in your physics system for this to function.
1667 rootpart.PhysActor.APIDActive = false; 1995 rootpart.PhysActor.APIDActive = false;
1668 } 1996 }
1669 } 1997 }
@@ -1729,6 +2057,8 @@ namespace OpenSim.Region.Framework.Scenes
1729 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2057 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1730 { 2058 {
1731 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2059 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2060 newPart.SetParent(this);
2061
1732 AddPart(newPart); 2062 AddPart(newPart);
1733 2063
1734 SetPartAsNonRoot(newPart); 2064 SetPartAsNonRoot(newPart);
@@ -1875,11 +2205,11 @@ namespace OpenSim.Region.Framework.Scenes
1875 /// Immediately send a full update for this scene object. 2205 /// Immediately send a full update for this scene object.
1876 /// </summary> 2206 /// </summary>
1877 public void SendGroupFullUpdate() 2207 public void SendGroupFullUpdate()
1878 { 2208 {
1879 if (IsDeleted) 2209 if (IsDeleted)
1880 return; 2210 return;
1881 2211
1882// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2212// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1883 2213
1884 RootPart.SendFullUpdateToAllClients(); 2214 RootPart.SendFullUpdateToAllClients();
1885 2215
@@ -2068,12 +2398,15 @@ namespace OpenSim.Region.Framework.Scenes
2068 part.LinkNum += objectGroup.PrimCount; 2398 part.LinkNum += objectGroup.PrimCount;
2069 } 2399 }
2070 } 2400 }
2401 }
2071 2402
2072 linkPart.LinkNum = 2; 2403 linkPart.LinkNum = 2;
2073 2404
2074 linkPart.SetParent(this); 2405 linkPart.SetParent(this);
2075 linkPart.CreateSelected = true; 2406 linkPart.CreateSelected = true;
2076 2407
2408 lock (m_parts.SyncRoot)
2409 {
2077 //if (linkPart.PhysActor != null) 2410 //if (linkPart.PhysActor != null)
2078 //{ 2411 //{
2079 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2412 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
@@ -2231,6 +2564,8 @@ namespace OpenSim.Region.Framework.Scenes
2231 /// <param name="objectGroup"></param> 2564 /// <param name="objectGroup"></param>
2232 public virtual void DetachFromBackup() 2565 public virtual void DetachFromBackup()
2233 { 2566 {
2567 m_scene.SceneGraph.FireDetachFromBackup(this);
2568
2234 if (m_isBackedUp) 2569 if (m_isBackedUp)
2235 m_scene.EventManager.OnBackup -= ProcessBackup; 2570 m_scene.EventManager.OnBackup -= ProcessBackup;
2236 2571
@@ -2535,6 +2870,17 @@ namespace OpenSim.Region.Framework.Scenes
2535 } 2870 }
2536 } 2871 }
2537 2872
2873
2874
2875 /// <summary>
2876 /// Gets the number of parts
2877 /// </summary>
2878 /// <returns></returns>
2879 public int GetPartCount()
2880 {
2881 return Parts.Count();
2882 }
2883
2538 /// <summary> 2884 /// <summary>
2539 /// Update the texture entry for this part 2885 /// Update the texture entry for this part
2540 /// </summary> 2886 /// </summary>
@@ -2596,11 +2942,9 @@ namespace OpenSim.Region.Framework.Scenes
2596 scale.Y = m_scene.m_maxNonphys; 2942 scale.Y = m_scene.m_maxNonphys;
2597 if (scale.Z > m_scene.m_maxNonphys) 2943 if (scale.Z > m_scene.m_maxNonphys)
2598 scale.Z = m_scene.m_maxNonphys; 2944 scale.Z = m_scene.m_maxNonphys;
2599
2600 SceneObjectPart part = GetChildPart(localID); 2945 SceneObjectPart part = GetChildPart(localID);
2601 if (part != null) 2946 if (part != null)
2602 { 2947 {
2603 part.Resize(scale);
2604 if (part.PhysActor != null) 2948 if (part.PhysActor != null)
2605 { 2949 {
2606 if (part.PhysActor.IsPhysical) 2950 if (part.PhysActor.IsPhysical)
@@ -2615,7 +2959,7 @@ namespace OpenSim.Region.Framework.Scenes
2615 part.PhysActor.Size = scale; 2959 part.PhysActor.Size = scale;
2616 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2960 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2617 } 2961 }
2618 //if (part.UUID != m_rootPart.UUID) 2962 part.Resize(scale);
2619 2963
2620 HasGroupChanged = true; 2964 HasGroupChanged = true;
2621 part.TriggerScriptChangedEvent(Changed.SCALE); 2965 part.TriggerScriptChangedEvent(Changed.SCALE);
@@ -2638,7 +2982,6 @@ namespace OpenSim.Region.Framework.Scenes
2638 SceneObjectPart part = GetChildPart(localID); 2982 SceneObjectPart part = GetChildPart(localID);
2639 if (part != null) 2983 if (part != null)
2640 { 2984 {
2641 part.IgnoreUndoUpdate = true;
2642 if (scale.X > m_scene.m_maxNonphys) 2985 if (scale.X > m_scene.m_maxNonphys)
2643 scale.X = m_scene.m_maxNonphys; 2986 scale.X = m_scene.m_maxNonphys;
2644 if (scale.Y > m_scene.m_maxNonphys) 2987 if (scale.Y > m_scene.m_maxNonphys)
@@ -2675,7 +3018,7 @@ namespace OpenSim.Region.Framework.Scenes
2675 3018
2676 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3019 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2677 { 3020 {
2678 if (oldSize.X * x > m_scene.m_maxPhys) 3021 if (oldSize.X*x > m_scene.m_maxPhys)
2679 { 3022 {
2680 f = m_scene.m_maxPhys / oldSize.X; 3023 f = m_scene.m_maxPhys / oldSize.X;
2681 a = f / x; 3024 a = f / x;
@@ -2683,7 +3026,7 @@ namespace OpenSim.Region.Framework.Scenes
2683 y *= a; 3026 y *= a;
2684 z *= a; 3027 z *= a;
2685 } 3028 }
2686 if (oldSize.Y * y > m_scene.m_maxPhys) 3029 if (oldSize.Y*y > m_scene.m_maxPhys)
2687 { 3030 {
2688 f = m_scene.m_maxPhys / oldSize.Y; 3031 f = m_scene.m_maxPhys / oldSize.Y;
2689 a = f / y; 3032 a = f / y;
@@ -2691,7 +3034,7 @@ namespace OpenSim.Region.Framework.Scenes
2691 y *= a; 3034 y *= a;
2692 z *= a; 3035 z *= a;
2693 } 3036 }
2694 if (oldSize.Z * z > m_scene.m_maxPhys) 3037 if (oldSize.Z*z > m_scene.m_maxPhys)
2695 { 3038 {
2696 f = m_scene.m_maxPhys / oldSize.Z; 3039 f = m_scene.m_maxPhys / oldSize.Z;
2697 a = f / z; 3040 a = f / z;
@@ -2702,7 +3045,7 @@ namespace OpenSim.Region.Framework.Scenes
2702 } 3045 }
2703 else 3046 else
2704 { 3047 {
2705 if (oldSize.X * x > m_scene.m_maxNonphys) 3048 if (oldSize.X*x > m_scene.m_maxNonphys)
2706 { 3049 {
2707 f = m_scene.m_maxNonphys / oldSize.X; 3050 f = m_scene.m_maxNonphys / oldSize.X;
2708 a = f / x; 3051 a = f / x;
@@ -2710,7 +3053,7 @@ namespace OpenSim.Region.Framework.Scenes
2710 y *= a; 3053 y *= a;
2711 z *= a; 3054 z *= a;
2712 } 3055 }
2713 if (oldSize.Y * y > m_scene.m_maxNonphys) 3056 if (oldSize.Y*y > m_scene.m_maxNonphys)
2714 { 3057 {
2715 f = m_scene.m_maxNonphys / oldSize.Y; 3058 f = m_scene.m_maxNonphys / oldSize.Y;
2716 a = f / y; 3059 a = f / y;
@@ -2718,7 +3061,7 @@ namespace OpenSim.Region.Framework.Scenes
2718 y *= a; 3061 y *= a;
2719 z *= a; 3062 z *= a;
2720 } 3063 }
2721 if (oldSize.Z * z > m_scene.m_maxNonphys) 3064 if (oldSize.Z*z > m_scene.m_maxNonphys)
2722 { 3065 {
2723 f = m_scene.m_maxNonphys / oldSize.Z; 3066 f = m_scene.m_maxNonphys / oldSize.Z;
2724 a = f / z; 3067 a = f / z;
@@ -2728,7 +3071,6 @@ namespace OpenSim.Region.Framework.Scenes
2728 } 3071 }
2729 } 3072 }
2730 obPart.IgnoreUndoUpdate = false; 3073 obPart.IgnoreUndoUpdate = false;
2731 obPart.StoreUndoState();
2732 } 3074 }
2733 } 3075 }
2734 } 3076 }
@@ -2736,8 +3078,13 @@ namespace OpenSim.Region.Framework.Scenes
2736 Vector3 prevScale = part.Scale; 3078 Vector3 prevScale = part.Scale;
2737 prevScale.X *= x; 3079 prevScale.X *= x;
2738 prevScale.Y *= y; 3080 prevScale.Y *= y;
2739 prevScale.Z *= z; 3081 prevScale.Z *= z;;
3082
3083 part.IgnoreUndoUpdate = false;
3084 part.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3085 part.IgnoreUndoUpdate = true;
2740 part.Resize(prevScale); 3086 part.Resize(prevScale);
3087 part.IgnoreUndoUpdate = false;
2741 3088
2742 parts = m_parts.GetArray(); 3089 parts = m_parts.GetArray();
2743 for (int i = 0; i < parts.Length; i++) 3090 for (int i = 0; i < parts.Length; i++)
@@ -2746,19 +3093,26 @@ namespace OpenSim.Region.Framework.Scenes
2746 obPart.IgnoreUndoUpdate = true; 3093 obPart.IgnoreUndoUpdate = true;
2747 if (obPart.UUID != m_rootPart.UUID) 3094 if (obPart.UUID != m_rootPart.UUID)
2748 { 3095 {
2749 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3096 if (obPart.UUID != m_rootPart.UUID)
2750 currentpos.X *= x; 3097 {
2751 currentpos.Y *= y; 3098 obPart.IgnoreUndoUpdate = false;
2752 currentpos.Z *= z; 3099 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
2753 Vector3 newSize = new Vector3(obPart.Scale); 3100 obPart.IgnoreUndoUpdate = true;
2754 newSize.X *= x; 3101
2755 newSize.Y *= y; 3102 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2756 newSize.Z *= z; 3103 currentpos.X *= x;
2757 obPart.Resize(newSize); 3104 currentpos.Y *= y;
2758 obPart.UpdateOffSet(currentpos); 3105 currentpos.Z *= z;
3106 Vector3 newSize = new Vector3(obPart.Scale);
3107 newSize.X *= x;
3108 newSize.Y *= y;
3109 newSize.Z *= z;
3110 obPart.Resize(newSize);
3111 obPart.UpdateOffSet(currentpos);
3112 }
3113 obPart.IgnoreUndoUpdate = false;
2759 } 3114 }
2760 obPart.IgnoreUndoUpdate = false; 3115 obPart.IgnoreUndoUpdate = false;
2761 obPart.StoreUndoState();
2762 } 3116 }
2763 3117
2764 if (part.PhysActor != null) 3118 if (part.PhysActor != null)
@@ -2768,7 +3122,6 @@ namespace OpenSim.Region.Framework.Scenes
2768 } 3122 }
2769 3123
2770 part.IgnoreUndoUpdate = false; 3124 part.IgnoreUndoUpdate = false;
2771 part.StoreUndoState();
2772 HasGroupChanged = true; 3125 HasGroupChanged = true;
2773 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE); 3126 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
2774 ScheduleGroupForTerseUpdate(); 3127 ScheduleGroupForTerseUpdate();
@@ -2785,14 +3138,11 @@ namespace OpenSim.Region.Framework.Scenes
2785 /// <param name="pos"></param> 3138 /// <param name="pos"></param>
2786 public void UpdateGroupPosition(Vector3 pos) 3139 public void UpdateGroupPosition(Vector3 pos)
2787 { 3140 {
2788 SceneObjectPart[] parts = m_parts.GetArray();
2789 for (int i = 0; i < parts.Length; i++)
2790 parts[i].StoreUndoState();
2791
2792 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3141 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2793 { 3142 {
2794 if (IsAttachment) 3143 if (IsAttachment)
2795 { 3144 {
3145 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
2796 m_rootPart.AttachedPos = pos; 3146 m_rootPart.AttachedPos = pos;
2797 } 3147 }
2798 if (RootPart.GetStatusSandbox()) 3148 if (RootPart.GetStatusSandbox())
@@ -2826,7 +3176,7 @@ namespace OpenSim.Region.Framework.Scenes
2826 3176
2827 SceneObjectPart[] parts = m_parts.GetArray(); 3177 SceneObjectPart[] parts = m_parts.GetArray();
2828 for (int i = 0; i < parts.Length; i++) 3178 for (int i = 0; i < parts.Length; i++)
2829 parts[i].StoreUndoState(); 3179 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2830 3180
2831 if (part != null) 3181 if (part != null)
2832 { 3182 {
@@ -2851,7 +3201,7 @@ namespace OpenSim.Region.Framework.Scenes
2851 { 3201 {
2852 SceneObjectPart[] parts = m_parts.GetArray(); 3202 SceneObjectPart[] parts = m_parts.GetArray();
2853 for (int i = 0; i < parts.Length; i++) 3203 for (int i = 0; i < parts.Length; i++)
2854 parts[i].StoreUndoState(); 3204 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2855 3205
2856 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3206 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2857 Vector3 oldPos = 3207 Vector3 oldPos =
@@ -2872,10 +3222,27 @@ namespace OpenSim.Region.Framework.Scenes
2872 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3222 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2873 } 3223 }
2874 3224
2875 AbsolutePosition = newPos; 3225 //We have to set undoing here because otherwise an undo state will be saved
3226 if (!m_rootPart.Undoing)
3227 {
3228 m_rootPart.Undoing = true;
3229 AbsolutePosition = newPos;
3230 m_rootPart.Undoing = false;
3231 }
3232 else
3233 {
3234 AbsolutePosition = newPos;
3235 }
2876 3236
2877 HasGroupChanged = true; 3237 HasGroupChanged = true;
2878 ScheduleGroupForTerseUpdate(); 3238 if (m_rootPart.Undoing)
3239 {
3240 ScheduleGroupForFullUpdate();
3241 }
3242 else
3243 {
3244 ScheduleGroupForTerseUpdate();
3245 }
2879 } 3246 }
2880 3247
2881 public void OffsetForNewRegion(Vector3 offset) 3248 public void OffsetForNewRegion(Vector3 offset)
@@ -2895,7 +3262,7 @@ namespace OpenSim.Region.Framework.Scenes
2895 { 3262 {
2896 SceneObjectPart[] parts = m_parts.GetArray(); 3263 SceneObjectPart[] parts = m_parts.GetArray();
2897 for (int i = 0; i < parts.Length; i++) 3264 for (int i = 0; i < parts.Length; i++)
2898 parts[i].StoreUndoState(); 3265 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2899 3266
2900 m_rootPart.UpdateRotation(rot); 3267 m_rootPart.UpdateRotation(rot);
2901 3268
@@ -2919,7 +3286,7 @@ namespace OpenSim.Region.Framework.Scenes
2919 { 3286 {
2920 SceneObjectPart[] parts = m_parts.GetArray(); 3287 SceneObjectPart[] parts = m_parts.GetArray();
2921 for (int i = 0; i < parts.Length; i++) 3288 for (int i = 0; i < parts.Length; i++)
2922 parts[i].StoreUndoState(); 3289 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2923 3290
2924 m_rootPart.UpdateRotation(rot); 3291 m_rootPart.UpdateRotation(rot);
2925 3292
@@ -2944,10 +3311,9 @@ namespace OpenSim.Region.Framework.Scenes
2944 public void UpdateSingleRotation(Quaternion rot, uint localID) 3311 public void UpdateSingleRotation(Quaternion rot, uint localID)
2945 { 3312 {
2946 SceneObjectPart part = GetChildPart(localID); 3313 SceneObjectPart part = GetChildPart(localID);
2947
2948 SceneObjectPart[] parts = m_parts.GetArray(); 3314 SceneObjectPart[] parts = m_parts.GetArray();
2949 for (int i = 0; i < parts.Length; i++) 3315 for (int i = 0; i < parts.Length; i++)
2950 parts[i].StoreUndoState(); 3316 parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2951 3317
2952 if (part != null) 3318 if (part != null)
2953 { 3319 {
@@ -2975,15 +3341,24 @@ namespace OpenSim.Region.Framework.Scenes
2975 if (part.UUID == m_rootPart.UUID) 3341 if (part.UUID == m_rootPart.UUID)
2976 { 3342 {
2977 UpdateRootRotation(rot); 3343 UpdateRootRotation(rot);
2978 AbsolutePosition = pos; 3344 if (!m_rootPart.Undoing)
3345 {
3346 m_rootPart.Undoing = true;
3347 AbsolutePosition = pos;
3348 m_rootPart.Undoing = false;
3349 }
3350 else
3351 {
3352 AbsolutePosition = pos;
3353 }
2979 } 3354 }
2980 else 3355 else
2981 { 3356 {
3357 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2982 part.IgnoreUndoUpdate = true; 3358 part.IgnoreUndoUpdate = true;
2983 part.UpdateRotation(rot); 3359 part.UpdateRotation(rot);
2984 part.OffsetPosition = pos; 3360 part.OffsetPosition = pos;
2985 part.IgnoreUndoUpdate = false; 3361 part.IgnoreUndoUpdate = false;
2986 part.StoreUndoState();
2987 } 3362 }
2988 } 3363 }
2989 } 3364 }
@@ -2997,7 +3372,13 @@ namespace OpenSim.Region.Framework.Scenes
2997 Quaternion axRot = rot; 3372 Quaternion axRot = rot;
2998 Quaternion oldParentRot = m_rootPart.RotationOffset; 3373 Quaternion oldParentRot = m_rootPart.RotationOffset;
2999 3374
3000 m_rootPart.StoreUndoState(); 3375 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3376 bool cancelUndo = false;
3377 if (!m_rootPart.Undoing)
3378 {
3379 m_rootPart.Undoing = true;
3380 cancelUndo = true;
3381 }
3001 m_rootPart.UpdateRotation(rot); 3382 m_rootPart.UpdateRotation(rot);
3002 if (m_rootPart.PhysActor != null) 3383 if (m_rootPart.PhysActor != null)
3003 { 3384 {
@@ -3021,17 +3402,12 @@ namespace OpenSim.Region.Framework.Scenes
3021 newRot *= Quaternion.Inverse(axRot); 3402 newRot *= Quaternion.Inverse(axRot);
3022 prim.RotationOffset = newRot; 3403 prim.RotationOffset = newRot;
3023 prim.ScheduleTerseUpdate(); 3404 prim.ScheduleTerseUpdate();
3405 prim.IgnoreUndoUpdate = false;
3024 } 3406 }
3025 } 3407 }
3026 3408 if (cancelUndo == true)
3027 for (int i = 0; i < parts.Length; i++)
3028 { 3409 {
3029 SceneObjectPart childpart = parts[i]; 3410 m_rootPart.Undoing = false;
3030 if (childpart != m_rootPart)
3031 {
3032 childpart.IgnoreUndoUpdate = false;
3033 childpart.StoreUndoState();
3034 }
3035 } 3411 }
3036 3412
3037 m_rootPart.ScheduleTerseUpdate(); 3413 m_rootPart.ScheduleTerseUpdate();
@@ -3257,7 +3633,6 @@ namespace OpenSim.Region.Framework.Scenes
3257 public float GetMass() 3633 public float GetMass()
3258 { 3634 {
3259 float retmass = 0f; 3635 float retmass = 0f;
3260
3261 SceneObjectPart[] parts = m_parts.GetArray(); 3636 SceneObjectPart[] parts = m_parts.GetArray();
3262 for (int i = 0; i < parts.Length; i++) 3637 for (int i = 0; i < parts.Length; i++)
3263 retmass += parts[i].GetMass(); 3638 retmass += parts[i].GetMass();
@@ -3373,6 +3748,14 @@ namespace OpenSim.Region.Framework.Scenes
3373 SetFromItemID(uuid); 3748 SetFromItemID(uuid);
3374 } 3749 }
3375 3750
3751 public void ResetOwnerChangeFlag()
3752 {
3753 ForEachPart(delegate(SceneObjectPart part)
3754 {
3755 part.ResetOwnerChangeFlag();
3756 });
3757 }
3758
3376 #endregion 3759 #endregion
3377 } 3760 }
3378} 3761}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 4fcd8f5..0297a39 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;
@@ -529,12 +539,16 @@ namespace OpenSim.Region.Framework.Scenes
529 } 539 }
530 540
531 /// <value> 541 /// <value>
532 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 542 /// Get the inventory list
533 /// </value> 543 /// </value>
534 public TaskInventoryDictionary TaskInventory 544 public TaskInventoryDictionary TaskInventory
535 { 545 {
536 get { return m_inventory.Items; } 546 get {
537 set { m_inventory.Items = value; } 547 return m_inventory.Items;
548 }
549 set {
550 m_inventory.Items = value;
551 }
538 } 552 }
539 553
540 /// <summary> 554 /// <summary>
@@ -674,14 +688,12 @@ namespace OpenSim.Region.Framework.Scenes
674 set { m_LoopSoundSlavePrims = value; } 688 set { m_LoopSoundSlavePrims = value; }
675 } 689 }
676 690
677
678 public Byte[] TextureAnimation 691 public Byte[] TextureAnimation
679 { 692 {
680 get { return m_TextureAnimation; } 693 get { return m_TextureAnimation; }
681 set { m_TextureAnimation = value; } 694 set { m_TextureAnimation = value; }
682 } 695 }
683 696
684
685 public Byte[] ParticleSystem 697 public Byte[] ParticleSystem
686 { 698 {
687 get { return m_particleSystem; } 699 get { return m_particleSystem; }
@@ -735,7 +747,6 @@ namespace OpenSim.Region.Framework.Scenes
735 set 747 set
736 { 748 {
737 m_groupPosition = value; 749 m_groupPosition = value;
738
739 PhysicsActor actor = PhysActor; 750 PhysicsActor actor = PhysActor;
740 if (actor != null) 751 if (actor != null)
741 { 752 {
@@ -755,25 +766,13 @@ namespace OpenSim.Region.Framework.Scenes
755 766
756 // Tell the physics engines that this prim changed. 767 // Tell the physics engines that this prim changed.
757 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 768 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
769
758 } 770 }
759 catch (Exception e) 771 catch (Exception e)
760 { 772 {
761 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 773 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
762 } 774 }
763 } 775 }
764
765 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
766 if (m_sitTargetAvatar != UUID.Zero)
767 {
768 if (m_parentGroup != null) // TODO can there be a SOP without a SOG?
769 {
770 ScenePresence avatar;
771 if (m_parentGroup.Scene.TryGetScenePresence(m_sitTargetAvatar, out avatar))
772 {
773 avatar.ParentPosition = GetWorldPosition();
774 }
775 }
776 }
777 } 776 }
778 } 777 }
779 778
@@ -782,7 +781,8 @@ namespace OpenSim.Region.Framework.Scenes
782 get { return m_offsetPosition; } 781 get { return m_offsetPosition; }
783 set 782 set
784 { 783 {
785 StoreUndoState(); 784 Vector3 oldpos = m_offsetPosition;
785 StoreUndoState(UndoType.STATE_PRIM_POSITION);
786 m_offsetPosition = value; 786 m_offsetPosition = value;
787 787
788 if (ParentGroup != null && !ParentGroup.IsDeleted) 788 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -796,7 +796,22 @@ namespace OpenSim.Region.Framework.Scenes
796 // Tell the physics engines that this prim changed. 796 // Tell the physics engines that this prim changed.
797 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 797 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
798 } 798 }
799
800 if (!m_parentGroup.m_dupeInProgress)
801 {
802 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
803 foreach (ScenePresence av in avs)
804 {
805 if (av.LinkedPrim == m_uuid)
806 {
807 Vector3 offset = (m_offsetPosition - oldpos);
808 av.OffsetPosition += offset;
809 av.SendAvatarDataToAllAgents();
810 }
811 }
812 }
799 } 813 }
814 TriggerScriptChangedEvent(Changed.POSITION);
800 } 815 }
801 } 816 }
802 817
@@ -838,7 +853,7 @@ namespace OpenSim.Region.Framework.Scenes
838 853
839 set 854 set
840 { 855 {
841 StoreUndoState(); 856 StoreUndoState(UndoType.STATE_PRIM_ROTATION);
842 m_rotationOffset = value; 857 m_rotationOffset = value;
843 858
844 PhysicsActor actor = PhysActor; 859 PhysicsActor actor = PhysActor;
@@ -922,7 +937,16 @@ namespace OpenSim.Region.Framework.Scenes
922 /// <summary></summary> 937 /// <summary></summary>
923 public Vector3 Acceleration 938 public Vector3 Acceleration
924 { 939 {
925 get { return m_acceleration; } 940 get
941 {
942 PhysicsActor actor = PhysActor;
943 if (actor != null)
944 {
945 m_acceleration = actor.Acceleration;
946 }
947 return m_acceleration;
948 }
949
926 set { m_acceleration = value; } 950 set { m_acceleration = value; }
927 } 951 }
928 952
@@ -1013,7 +1037,7 @@ namespace OpenSim.Region.Framework.Scenes
1013 get { return m_shape.Scale; } 1037 get { return m_shape.Scale; }
1014 set 1038 set
1015 { 1039 {
1016 StoreUndoState(); 1040 StoreUndoState(UndoType.STATE_PRIM_SCALE);
1017 if (m_shape != null) 1041 if (m_shape != null)
1018 { 1042 {
1019 m_shape.Scale = value; 1043 m_shape.Scale = value;
@@ -1081,9 +1105,10 @@ namespace OpenSim.Region.Framework.Scenes
1081 { 1105 {
1082 get { 1106 get {
1083 if (IsAttachment) 1107 if (IsAttachment)
1084 return GroupPosition; 1108 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1085 1109
1086 return m_offsetPosition + m_groupPosition; } 1110// return m_offsetPosition + m_groupPosition; }
1111 return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored!
1087 } 1112 }
1088 1113
1089 public SceneObjectGroup ParentGroup 1114 public SceneObjectGroup ParentGroup
@@ -1242,6 +1267,13 @@ namespace OpenSim.Region.Framework.Scenes
1242 _flags = value; 1267 _flags = value;
1243 } 1268 }
1244 } 1269 }
1270
1271 [XmlIgnore]
1272 public bool IsOccupied // KF If an av is sittingon this prim
1273 {
1274 get { return m_occupied; }
1275 set { m_occupied = value; }
1276 }
1245 1277
1246 1278
1247 public UUID SitTargetAvatar 1279 public UUID SitTargetAvatar
@@ -1317,14 +1349,6 @@ namespace OpenSim.Region.Framework.Scenes
1317 } 1349 }
1318 } 1350 }
1319 1351
1320 /// <summary>
1321 /// Clear all pending updates of parts to clients
1322 /// </summary>
1323 private void ClearUpdateSchedule()
1324 {
1325 m_updateFlag = 0;
1326 }
1327
1328 private void SendObjectPropertiesToClient(UUID AgentID) 1352 private void SendObjectPropertiesToClient(UUID AgentID)
1329 { 1353 {
1330 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1354 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1575,14 +1599,22 @@ namespace OpenSim.Region.Framework.Scenes
1575 // or flexible 1599 // or flexible
1576 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible)) 1600 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible))
1577 { 1601 {
1578 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( 1602 try
1579 string.Format("{0}/{1}", Name, UUID), 1603 {
1580 Shape, 1604 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
1581 AbsolutePosition, 1605 string.Format("{0}/{1}", Name, UUID),
1582 Scale, 1606 Shape,
1583 RotationOffset, 1607 AbsolutePosition,
1584 RigidBody); 1608 Scale,
1585 1609 RotationOffset,
1610 RigidBody);
1611 PhysActor.SetMaterial(Material);
1612 }
1613 catch
1614 {
1615 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid);
1616 PhysActor = null;
1617 }
1586 // Basic Physics returns null.. joy joy joy. 1618 // Basic Physics returns null.. joy joy joy.
1587 if (PhysActor != null) 1619 if (PhysActor != null)
1588 { 1620 {
@@ -1610,7 +1642,7 @@ namespace OpenSim.Region.Framework.Scenes
1610 { 1642 {
1611 m_redo.Clear(); 1643 m_redo.Clear();
1612 } 1644 }
1613 StoreUndoState(); 1645 StoreUndoState(UndoType.STATE_ALL);
1614 } 1646 }
1615 1647
1616 public byte ConvertScriptUintToByte(uint indata) 1648 public byte ConvertScriptUintToByte(uint indata)
@@ -1679,6 +1711,9 @@ namespace OpenSim.Region.Framework.Scenes
1679 1711
1680 // Move afterwards ResetIDs as it clears the localID 1712 // Move afterwards ResetIDs as it clears the localID
1681 dupe.LocalId = localID; 1713 dupe.LocalId = localID;
1714 if(dupe.PhysActor != null)
1715 dupe.PhysActor.LocalID = localID;
1716
1682 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1717 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1683 dupe._lastOwnerID = OwnerID; 1718 dupe._lastOwnerID = OwnerID;
1684 1719
@@ -1722,7 +1757,7 @@ namespace OpenSim.Region.Framework.Scenes
1722 PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); 1757 PrimitiveBaseShape shape = PrimitiveBaseShape.Create();
1723 part.Shape = shape; 1758 part.Shape = shape;
1724 1759
1725 part.Name = "Primitive"; 1760 part.Name = "Object";
1726 part._ownerID = UUID.Random(); 1761 part._ownerID = UUID.Random();
1727 1762
1728 return part; 1763 return part;
@@ -2082,12 +2117,17 @@ namespace OpenSim.Region.Framework.Scenes
2082 public Vector3 GetWorldPosition() 2117 public Vector3 GetWorldPosition()
2083 { 2118 {
2084 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2119 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
2085
2086 Vector3 axPos = OffsetPosition; 2120 Vector3 axPos = OffsetPosition;
2087
2088 axPos *= parentRot; 2121 axPos *= parentRot;
2089 Vector3 translationOffsetPosition = axPos; 2122 Vector3 translationOffsetPosition = axPos;
2090 return GroupPosition + translationOffsetPosition; 2123 if(_parentID == 0)
2124 {
2125 return GroupPosition;
2126 }
2127 else
2128 {
2129 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
2130 }
2091 } 2131 }
2092 2132
2093 /// <summary> 2133 /// <summary>
@@ -2098,7 +2138,7 @@ namespace OpenSim.Region.Framework.Scenes
2098 { 2138 {
2099 Quaternion newRot; 2139 Quaternion newRot;
2100 2140
2101 if (this.LinkNum == 0) 2141 if (this.LinkNum < 2) //KF Single or root prim
2102 { 2142 {
2103 newRot = RotationOffset; 2143 newRot = RotationOffset;
2104 } 2144 }
@@ -2744,17 +2784,18 @@ namespace OpenSim.Region.Framework.Scenes
2744 //Trys to fetch sound id from prim's inventory. 2784 //Trys to fetch sound id from prim's inventory.
2745 //Prim's inventory doesn't support non script items yet 2785 //Prim's inventory doesn't support non script items yet
2746 2786
2747 lock (TaskInventory) 2787 TaskInventory.LockItemsForRead(true);
2788
2789 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2748 { 2790 {
2749 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2791 if (item.Value.Name == sound)
2750 { 2792 {
2751 if (item.Value.Name == sound) 2793 soundID = item.Value.ItemID;
2752 { 2794 break;
2753 soundID = item.Value.ItemID;
2754 break;
2755 }
2756 } 2795 }
2757 } 2796 }
2797
2798 TaskInventory.LockItemsForRead(false);
2758 } 2799 }
2759 2800
2760 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2801 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2814,7 +2855,7 @@ namespace OpenSim.Region.Framework.Scenes
2814 /// <param name="scale"></param> 2855 /// <param name="scale"></param>
2815 public void Resize(Vector3 scale) 2856 public void Resize(Vector3 scale)
2816 { 2857 {
2817 StoreUndoState(); 2858 StoreUndoState(UndoType.STATE_PRIM_SCALE);
2818 m_shape.Scale = scale; 2859 m_shape.Scale = scale;
2819 2860
2820 ParentGroup.HasGroupChanged = true; 2861 ParentGroup.HasGroupChanged = true;
@@ -2823,38 +2864,7 @@ namespace OpenSim.Region.Framework.Scenes
2823 2864
2824 public void RotLookAt(Quaternion target, float strength, float damping) 2865 public void RotLookAt(Quaternion target, float strength, float damping)
2825 { 2866 {
2826 rotLookAt(target, strength, damping); 2867 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2827 }
2828
2829 public void rotLookAt(Quaternion target, float strength, float damping)
2830 {
2831 if (IsAttachment)
2832 {
2833 /*
2834 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2835 if (avatar != null)
2836 {
2837 Rotate the Av?
2838 } */
2839 }
2840 else
2841 {
2842 APIDDamp = damping;
2843 APIDStrength = strength;
2844 APIDTarget = target;
2845 }
2846 }
2847
2848 public void startLookAt(Quaternion rot, float damp, float strength)
2849 {
2850 APIDDamp = damp;
2851 APIDStrength = strength;
2852 APIDTarget = rot;
2853 }
2854
2855 public void stopLookAt()
2856 {
2857 APIDTarget = Quaternion.Identity;
2858 } 2868 }
2859 2869
2860 /// <summary> 2870 /// <summary>
@@ -2866,7 +2876,10 @@ namespace OpenSim.Region.Framework.Scenes
2866 2876
2867 if (m_parentGroup != null) 2877 if (m_parentGroup != null)
2868 { 2878 {
2869 m_parentGroup.QueueForUpdateCheck(); 2879 if (!m_parentGroup.areUpdatesSuspended)
2880 {
2881 m_parentGroup.QueueForUpdateCheck();
2882 }
2870 } 2883 }
2871 2884
2872 int timeNow = Util.UnixTimeSinceEpoch(); 2885 int timeNow = Util.UnixTimeSinceEpoch();
@@ -3083,8 +3096,8 @@ namespace OpenSim.Region.Framework.Scenes
3083 { 3096 {
3084 const float ROTATION_TOLERANCE = 0.01f; 3097 const float ROTATION_TOLERANCE = 0.01f;
3085 const float VELOCITY_TOLERANCE = 0.001f; 3098 const float VELOCITY_TOLERANCE = 0.001f;
3086 const float POSITION_TOLERANCE = 0.05f; 3099 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
3087 const int TIME_MS_TOLERANCE = 3000; 3100 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
3088 3101
3089 if (m_updateFlag == 1) 3102 if (m_updateFlag == 1)
3090 { 3103 {
@@ -3098,7 +3111,7 @@ namespace OpenSim.Region.Framework.Scenes
3098 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3111 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
3099 { 3112 {
3100 AddTerseUpdateToAllAvatars(); 3113 AddTerseUpdateToAllAvatars();
3101 ClearUpdateSchedule(); 3114
3102 3115
3103 // This causes the Scene to 'poll' physical objects every couple of frames 3116 // This causes the Scene to 'poll' physical objects every couple of frames
3104 // bad, so it's been replaced by an event driven method. 3117 // bad, so it's been replaced by an event driven method.
@@ -3116,16 +3129,18 @@ namespace OpenSim.Region.Framework.Scenes
3116 m_lastAngularVelocity = AngularVelocity; 3129 m_lastAngularVelocity = AngularVelocity;
3117 m_lastTerseSent = Environment.TickCount; 3130 m_lastTerseSent = Environment.TickCount;
3118 } 3131 }
3132 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
3133 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
3119 } 3134 }
3120 else 3135 else
3121 { 3136 {
3122 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 3137 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3123 { 3138 {
3124 AddFullUpdateToAllAvatars(); 3139 AddFullUpdateToAllAvatars();
3125 ClearUpdateSchedule(); 3140 m_updateFlag = 0; //Same here
3126 } 3141 }
3127 } 3142 }
3128 ClearUpdateSchedule(); 3143 m_updateFlag = 0;
3129 } 3144 }
3130 3145
3131 /// <summary> 3146 /// <summary>
@@ -3153,17 +3168,16 @@ namespace OpenSim.Region.Framework.Scenes
3153 if (!UUID.TryParse(sound, out soundID)) 3168 if (!UUID.TryParse(sound, out soundID))
3154 { 3169 {
3155 // search sound file from inventory 3170 // search sound file from inventory
3156 lock (TaskInventory) 3171 TaskInventory.LockItemsForRead(true);
3172 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3157 { 3173 {
3158 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3174 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3159 { 3175 {
3160 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3176 soundID = item.Value.ItemID;
3161 { 3177 break;
3162 soundID = item.Value.ItemID;
3163 break;
3164 }
3165 } 3178 }
3166 } 3179 }
3180 TaskInventory.LockItemsForRead(false);
3167 } 3181 }
3168 3182
3169 if (soundID == UUID.Zero) 3183 if (soundID == UUID.Zero)
@@ -3593,7 +3607,7 @@ namespace OpenSim.Region.Framework.Scenes
3593 3607
3594 public void StopLookAt() 3608 public void StopLookAt()
3595 { 3609 {
3596 m_parentGroup.stopLookAt(); 3610 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3597 3611
3598 m_parentGroup.ScheduleGroupForTerseUpdate(); 3612 m_parentGroup.ScheduleGroupForTerseUpdate();
3599 } 3613 }
@@ -3620,10 +3634,9 @@ namespace OpenSim.Region.Framework.Scenes
3620 m_parentGroup.ScheduleGroupForTerseUpdate(); 3634 m_parentGroup.ScheduleGroupForTerseUpdate();
3621 //m_parentGroup.ScheduleGroupForFullUpdate(); 3635 //m_parentGroup.ScheduleGroupForFullUpdate();
3622 } 3636 }
3623 3637 public void StoreUndoState(UndoType type)
3624 public void StoreUndoState()
3625 { 3638 {
3626 if (!Undoing) 3639 if (!Undoing && (m_parentGroup == null || m_parentGroup.RootPart == null || !m_parentGroup.RootPart.Undoing))
3627 { 3640 {
3628 if (!IgnoreUndoUpdate) 3641 if (!IgnoreUndoUpdate)
3629 { 3642 {
@@ -3634,17 +3647,25 @@ namespace OpenSim.Region.Framework.Scenes
3634 if (m_undo.Count > 0) 3647 if (m_undo.Count > 0)
3635 { 3648 {
3636 UndoState last = m_undo.Peek(); 3649 UndoState last = m_undo.Peek();
3637 if (last != null) 3650
3638 {
3639 if (last.Compare(this))
3640 return;
3641 }
3642 } 3651 }
3643 3652
3644 if (m_parentGroup.GetSceneMaxUndo() > 0) 3653 if (m_parentGroup.GetSceneMaxUndo() > 0)
3645 { 3654 {
3646 UndoState nUndo = new UndoState(this); 3655 UndoState lastUndo = m_undo.Peek();
3647 3656
3657 UndoState nUndo = new UndoState(this, type);
3658
3659 if (lastUndo != null)
3660 {
3661 TimeSpan ts = DateTime.Now.Subtract(lastUndo.LastUpdated);
3662 if (ts.TotalMilliseconds < 500)
3663 {
3664 //Delete the last entry since it was less than 500 milliseconds ago
3665 nUndo.Merge(lastUndo);
3666 m_undo.Pop();
3667 }
3668 }
3648 m_undo.Push(nUndo); 3669 m_undo.Push(nUndo);
3649 } 3670 }
3650 3671
@@ -4121,11 +4142,13 @@ namespace OpenSim.Region.Framework.Scenes
4121 if (m_undo.Count > 0) 4142 if (m_undo.Count > 0)
4122 { 4143 {
4123 UndoState nUndo = null; 4144 UndoState nUndo = null;
4145 UndoState goback = m_undo.Pop();
4124 if (m_parentGroup.GetSceneMaxUndo() > 0) 4146 if (m_parentGroup.GetSceneMaxUndo() > 0)
4125 { 4147 {
4126 nUndo = new UndoState(this); 4148 nUndo = new UndoState(this, goback.Type);
4127 } 4149 }
4128 UndoState goback = m_undo.Pop(); 4150
4151
4129 if (goback != null) 4152 if (goback != null)
4130 { 4153 {
4131 goback.PlaybackState(this); 4154 goback.PlaybackState(this);
@@ -4140,13 +4163,13 @@ namespace OpenSim.Region.Framework.Scenes
4140 { 4163 {
4141 lock (m_redo) 4164 lock (m_redo)
4142 { 4165 {
4166 UndoState gofwd = m_redo.Pop();
4143 if (m_parentGroup.GetSceneMaxUndo() > 0) 4167 if (m_parentGroup.GetSceneMaxUndo() > 0)
4144 { 4168 {
4145 UndoState nUndo = new UndoState(this); 4169 UndoState nUndo = new UndoState(this, gofwd.Type);
4146 4170
4147 m_undo.Push(nUndo); 4171 m_undo.Push(nUndo);
4148 } 4172 }
4149 UndoState gofwd = m_redo.Pop();
4150 if (gofwd != null) 4173 if (gofwd != null)
4151 gofwd.PlayfwdState(this); 4174 gofwd.PlayfwdState(this);
4152 } 4175 }
@@ -4410,6 +4433,7 @@ namespace OpenSim.Region.Framework.Scenes
4410 Scale, 4433 Scale,
4411 RotationOffset, 4434 RotationOffset,
4412 UsePhysics); 4435 UsePhysics);
4436 PhysActor.SetMaterial(Material);
4413 4437
4414 pa = PhysActor; 4438 pa = PhysActor;
4415 if (pa != null) 4439 if (pa != null)
@@ -4595,8 +4619,9 @@ namespace OpenSim.Region.Framework.Scenes
4595 { 4619 {
4596 m_shape.TextureEntry = textureEntry; 4620 m_shape.TextureEntry = textureEntry;
4597 TriggerScriptChangedEvent(Changed.TEXTURE); 4621 TriggerScriptChangedEvent(Changed.TEXTURE);
4598 4622 m_updateFlag = 1;
4599 ParentGroup.HasGroupChanged = true; 4623 ParentGroup.HasGroupChanged = true;
4624
4600 //This is madness.. 4625 //This is madness..
4601 //ParentGroup.ScheduleGroupForFullUpdate(); 4626 //ParentGroup.ScheduleGroupForFullUpdate();
4602 //This is sparta 4627 //This is sparta
@@ -4829,5 +4854,17 @@ namespace OpenSim.Region.Framework.Scenes
4829 Color color = Color; 4854 Color color = Color;
4830 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4855 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4831 } 4856 }
4857
4858 public void ResetOwnerChangeFlag()
4859 {
4860 List<UUID> inv = Inventory.GetInventoryList();
4861
4862 foreach (UUID itemID in inv)
4863 {
4864 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4865 item.OwnerChanged = false;
4866 Inventory.UpdateInventoryItem(item, false, false);
4867 }
4868 }
4832 } 4869 }
4833} 4870}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 1177378..da1b983 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -48,6 +48,8 @@ namespace OpenSim.Region.Framework.Scenes
48 private string m_inventoryFileName = String.Empty; 48 private string m_inventoryFileName = String.Empty;
49 private byte[] m_inventoryFileData = new byte[0]; 49 private byte[] m_inventoryFileData = new byte[0];
50 private uint m_inventoryFileNameSerial = 0; 50 private uint m_inventoryFileNameSerial = 0;
51
52 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
51 53
52 /// <value> 54 /// <value>
53 /// The part to which the inventory belongs. 55 /// The part to which the inventory belongs.
@@ -84,7 +86,9 @@ namespace OpenSim.Region.Framework.Scenes
84 /// </value> 86 /// </value>
85 protected internal TaskInventoryDictionary Items 87 protected internal TaskInventoryDictionary Items
86 { 88 {
87 get { return m_items; } 89 get {
90 return m_items;
91 }
88 set 92 set
89 { 93 {
90 m_items = value; 94 m_items = value;
@@ -120,39 +124,45 @@ namespace OpenSim.Region.Framework.Scenes
120 /// <param name="linkNum">Link number for the part</param> 124 /// <param name="linkNum">Link number for the part</param>
121 public void ResetInventoryIDs() 125 public void ResetInventoryIDs()
122 { 126 {
123 if (null == m_part || null == m_part.ParentGroup) 127 m_items.LockItemsForWrite(true);
124 return; 128
125 129 if (Items.Count == 0)
126 lock (m_items)
127 { 130 {
128 if (0 == m_items.Count) 131 m_items.LockItemsForWrite(false);
129 return; 132 return;
133 }
130 134
131 IList<TaskInventoryItem> items = GetInventoryItems(); 135 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
132 m_items.Clear(); 136 Items.Clear();
133 137
134 foreach (TaskInventoryItem item in items) 138 foreach (TaskInventoryItem item in items)
135 { 139 {
136 item.ResetIDs(m_part.UUID); 140 item.ResetIDs(m_part.UUID);
137 m_items.Add(item.ItemID, item); 141 Items.Add(item.ItemID, item);
138 }
139 } 142 }
143 m_items.LockItemsForWrite(false);
140 } 144 }
141 145
142 public void ResetObjectID() 146 public void ResetObjectID()
143 { 147 {
144 lock (Items) 148 m_items.LockItemsForWrite(true);
149
150 if (Items.Count == 0)
145 { 151 {
146 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 152 m_items.LockItemsForWrite(false);
147 Items.Clear(); 153 return;
148 154 }
149 foreach (TaskInventoryItem item in items) 155
150 { 156 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
151 item.ParentPartID = m_part.UUID; 157 Items.Clear();
152 item.ParentID = m_part.UUID; 158
153 Items.Add(item.ItemID, item); 159 foreach (TaskInventoryItem item in items)
154 } 160 {
161 item.ParentPartID = m_part.UUID;
162 item.ParentID = m_part.UUID;
163 Items.Add(item.ItemID, item);
155 } 164 }
165 m_items.LockItemsForWrite(false);
156 } 166 }
157 167
158 /// <summary> 168 /// <summary>
@@ -161,12 +171,11 @@ namespace OpenSim.Region.Framework.Scenes
161 /// <param name="ownerId"></param> 171 /// <param name="ownerId"></param>
162 public void ChangeInventoryOwner(UUID ownerId) 172 public void ChangeInventoryOwner(UUID ownerId)
163 { 173 {
164 lock (Items) 174 m_items.LockItemsForWrite(true);
175 if (0 == Items.Count)
165 { 176 {
166 if (0 == Items.Count) 177 m_items.LockItemsForWrite(false);
167 { 178 return;
168 return;
169 }
170 } 179 }
171 180
172 HasInventoryChanged = true; 181 HasInventoryChanged = true;
@@ -180,6 +189,7 @@ namespace OpenSim.Region.Framework.Scenes
180 item.OwnerID = ownerId; 189 item.OwnerID = ownerId;
181 } 190 }
182 } 191 }
192 m_items.LockItemsForWrite(false);
183 } 193 }
184 194
185 /// <summary> 195 /// <summary>
@@ -188,12 +198,11 @@ namespace OpenSim.Region.Framework.Scenes
188 /// <param name="groupID"></param> 198 /// <param name="groupID"></param>
189 public void ChangeInventoryGroup(UUID groupID) 199 public void ChangeInventoryGroup(UUID groupID)
190 { 200 {
191 lock (Items) 201 m_items.LockItemsForWrite(true);
202 if (0 == Items.Count)
192 { 203 {
193 if (0 == Items.Count) 204 m_items.LockItemsForWrite(false);
194 { 205 return;
195 return;
196 }
197 } 206 }
198 207
199 // Don't let this set the HasGroupChanged flag for attachments 208 // Don't let this set the HasGroupChanged flag for attachments
@@ -205,12 +214,15 @@ namespace OpenSim.Region.Framework.Scenes
205 m_part.ParentGroup.HasGroupChanged = true; 214 m_part.ParentGroup.HasGroupChanged = true;
206 } 215 }
207 216
208 List<TaskInventoryItem> items = GetInventoryItems(); 217 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
209 foreach (TaskInventoryItem item in items) 218 foreach (TaskInventoryItem item in items)
210 { 219 {
211 if (groupID != item.GroupID) 220 if (groupID != item.GroupID)
221 {
212 item.GroupID = groupID; 222 item.GroupID = groupID;
223 }
213 } 224 }
225 m_items.LockItemsForWrite(false);
214 } 226 }
215 227
216 /// <summary> 228 /// <summary>
@@ -218,9 +230,14 @@ namespace OpenSim.Region.Framework.Scenes
218 /// </summary> 230 /// </summary>
219 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 231 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
220 { 232 {
221 List<TaskInventoryItem> scripts = GetInventoryScripts(); 233 Items.LockItemsForRead(true);
222 foreach (TaskInventoryItem item in scripts) 234 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
223 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 235 Items.LockItemsForRead(false);
236 foreach (TaskInventoryItem item in items)
237 {
238 if ((int)InventoryType.LSL == item.InvType)
239 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
240 }
224 } 241 }
225 242
226 public ArrayList GetScriptErrors(UUID itemID) 243 public ArrayList GetScriptErrors(UUID itemID)
@@ -253,9 +270,18 @@ namespace OpenSim.Region.Framework.Scenes
253 /// </param> 270 /// </param>
254 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 271 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
255 { 272 {
256 List<TaskInventoryItem> scripts = GetInventoryScripts(); 273 Items.LockItemsForRead(true);
257 foreach (TaskInventoryItem item in scripts) 274 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
258 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 275 Items.LockItemsForRead(false);
276
277 foreach (TaskInventoryItem item in items)
278 {
279 if ((int)InventoryType.LSL == item.InvType)
280 {
281 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
282 m_part.RemoveScriptEvents(item.ItemID);
283 }
284 }
259 } 285 }
260 286
261 /// <summary> 287 /// <summary>
@@ -271,7 +297,10 @@ namespace OpenSim.Region.Framework.Scenes
271 // item.Name, item.ItemID, Name, UUID); 297 // item.Name, item.ItemID, Name, UUID);
272 298
273 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 299 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
300 {
301 StoreScriptError(item.ItemID, "no permission");
274 return; 302 return;
303 }
275 304
276 m_part.AddFlag(PrimFlags.Scripted); 305 m_part.AddFlag(PrimFlags.Scripted);
277 306
@@ -280,14 +309,13 @@ namespace OpenSim.Region.Framework.Scenes
280 if (stateSource == 2 && // Prim crossing 309 if (stateSource == 2 && // Prim crossing
281 m_part.ParentGroup.Scene.m_trustBinaries) 310 m_part.ParentGroup.Scene.m_trustBinaries)
282 { 311 {
283 lock (m_items) 312 m_items.LockItemsForWrite(true);
284 { 313 m_items[item.ItemID].PermsMask = 0;
285 m_items[item.ItemID].PermsMask = 0; 314 m_items[item.ItemID].PermsGranter = UUID.Zero;
286 m_items[item.ItemID].PermsGranter = UUID.Zero; 315 m_items.LockItemsForWrite(false);
287 }
288
289 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 316 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
290 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 317 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
318 StoreScriptErrors(item.ItemID, null);
291 m_part.ParentGroup.AddActiveScriptCount(1); 319 m_part.ParentGroup.AddActiveScriptCount(1);
292 m_part.ScheduleFullUpdate(); 320 m_part.ScheduleFullUpdate();
293 return; 321 return;
@@ -296,6 +324,8 @@ namespace OpenSim.Region.Framework.Scenes
296 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 324 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
297 if (null == asset) 325 if (null == asset)
298 { 326 {
327 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
328 StoreScriptError(item.ItemID, msg);
299 m_log.ErrorFormat( 329 m_log.ErrorFormat(
300 "[PRIM INVENTORY]: " + 330 "[PRIM INVENTORY]: " +
301 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 331 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -307,15 +337,17 @@ namespace OpenSim.Region.Framework.Scenes
307 if (m_part.ParentGroup.m_savedScriptState != null) 337 if (m_part.ParentGroup.m_savedScriptState != null)
308 RestoreSavedScriptState(item.OldItemID, item.ItemID); 338 RestoreSavedScriptState(item.OldItemID, item.ItemID);
309 339
310 lock (m_items) 340 m_items.LockItemsForWrite(true);
311 { 341
312 m_items[item.ItemID].PermsMask = 0; 342 m_items[item.ItemID].PermsMask = 0;
313 m_items[item.ItemID].PermsGranter = UUID.Zero; 343 m_items[item.ItemID].PermsGranter = UUID.Zero;
314 } 344
345 m_items.LockItemsForWrite(false);
315 346
316 string script = Utils.BytesToString(asset.Data); 347 string script = Utils.BytesToString(asset.Data);
317 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 348 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
318 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 349 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
350 StoreScriptErrors(item.ItemID, null);
319 m_part.ParentGroup.AddActiveScriptCount(1); 351 m_part.ParentGroup.AddActiveScriptCount(1);
320 m_part.ScheduleFullUpdate(); 352 m_part.ScheduleFullUpdate();
321 } 353 }
@@ -379,21 +411,145 @@ namespace OpenSim.Region.Framework.Scenes
379 411
380 /// <summary> 412 /// <summary>
381 /// Start a script which is in this prim's inventory. 413 /// Start a script which is in this prim's inventory.
414 /// Some processing may occur in the background, but this routine returns asap.
382 /// </summary> 415 /// </summary>
383 /// <param name="itemId"> 416 /// <param name="itemId">
384 /// A <see cref="UUID"/> 417 /// A <see cref="UUID"/>
385 /// </param> 418 /// </param>
386 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 419 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
387 { 420 {
388 TaskInventoryItem item = GetInventoryItem(itemId); 421 lock (m_scriptErrors)
389 if (item != null) 422 {
390 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 423 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
424 m_scriptErrors.Remove(itemId);
425 }
426 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
427 }
428
429 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
430 {
431 m_items.LockItemsForRead(true);
432 if (m_items.ContainsKey(itemId))
433 {
434 if (m_items.ContainsKey(itemId))
435 {
436 m_items.LockItemsForRead(false);
437 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
438 }
439 else
440 {
441 m_items.LockItemsForRead(false);
442 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
443 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
444 StoreScriptError(itemId, msg);
445 m_log.ErrorFormat(
446 "[PRIM INVENTORY]: " +
447 "Couldn't start script with ID {0} since it {1}", itemId, msg);
448 }
449 }
391 else 450 else
451 {
452 m_items.LockItemsForRead(false);
453 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
454 StoreScriptError(itemId, msg);
392 m_log.ErrorFormat( 455 m_log.ErrorFormat(
393 "[PRIM INVENTORY]: " + 456 "[PRIM INVENTORY]: " +
394 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 457 "Couldn't start script with ID {0} since it {1}", itemId, msg);
395 itemId, m_part.Name, m_part.UUID, 458 }
396 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 459
460 }
461
462 /// <summary>
463 /// Start a script which is in this prim's inventory and return any compilation error messages.
464 /// </summary>
465 /// <param name="itemId">
466 /// A <see cref="UUID"/>
467 /// </param>
468 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
469 {
470 ArrayList errors;
471
472 // Indicate to CreateScriptInstanceInternal() we want it to
473 // post any compilation/loading error messages
474 lock (m_scriptErrors)
475 {
476 m_scriptErrors[itemId] = null;
477 }
478
479 // Perform compilation/loading
480 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
481
482 // Wait for and retrieve any errors
483 lock (m_scriptErrors)
484 {
485 while ((errors = m_scriptErrors[itemId]) == null)
486 {
487 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
488 {
489 m_log.ErrorFormat(
490 "[PRIM INVENTORY]: " +
491 "timedout waiting for script {0} errors", itemId);
492 errors = m_scriptErrors[itemId];
493 if (errors == null)
494 {
495 errors = new ArrayList(1);
496 errors.Add("timedout waiting for errors");
497 }
498 break;
499 }
500 }
501 m_scriptErrors.Remove(itemId);
502 }
503 return errors;
504 }
505
506 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
507 private void StoreScriptErrors(UUID itemId, ArrayList errors)
508 {
509 lock (m_scriptErrors)
510 {
511 // If compilation/loading initiated via CreateScriptInstance(),
512 // it does not want the errors, so just get out
513 if (!m_scriptErrors.ContainsKey(itemId))
514 {
515 return;
516 }
517
518 // Initiated via CreateScriptInstanceEr(), if we know what the
519 // errors are, save them and wake CreateScriptInstanceEr().
520 if (errors != null)
521 {
522 m_scriptErrors[itemId] = errors;
523 System.Threading.Monitor.PulseAll(m_scriptErrors);
524 return;
525 }
526 }
527
528 // Initiated via CreateScriptInstanceEr() but we don't know what
529 // the errors are yet, so retrieve them from the script engine.
530 // This may involve some waiting internal to GetScriptErrors().
531 errors = GetScriptErrors(itemId);
532
533 // Get a default non-null value to indicate success.
534 if (errors == null)
535 {
536 errors = new ArrayList();
537 }
538
539 // Post to CreateScriptInstanceEr() and wake it up
540 lock (m_scriptErrors)
541 {
542 m_scriptErrors[itemId] = errors;
543 System.Threading.Monitor.PulseAll(m_scriptErrors);
544 }
545 }
546
547 // Like StoreScriptErrors(), but just posts a single string message
548 private void StoreScriptError(UUID itemId, string message)
549 {
550 ArrayList errors = new ArrayList(1);
551 errors.Add(message);
552 StoreScriptErrors(itemId, errors);
397 } 553 }
398 554
399 /// <summary> 555 /// <summary>
@@ -406,15 +562,7 @@ namespace OpenSim.Region.Framework.Scenes
406 /// </param> 562 /// </param>
407 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 563 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
408 { 564 {
409 bool scriptPresent = false; 565 if (m_items.ContainsKey(itemId))
410
411 lock (m_items)
412 {
413 if (m_items.ContainsKey(itemId))
414 scriptPresent = true;
415 }
416
417 if (scriptPresent)
418 { 566 {
419 if (!sceneObjectBeingDeleted) 567 if (!sceneObjectBeingDeleted)
420 m_part.RemoveScriptEvents(itemId); 568 m_part.RemoveScriptEvents(itemId);
@@ -439,14 +587,16 @@ namespace OpenSim.Region.Framework.Scenes
439 /// <returns></returns> 587 /// <returns></returns>
440 private bool InventoryContainsName(string name) 588 private bool InventoryContainsName(string name)
441 { 589 {
442 lock (m_items) 590 m_items.LockItemsForRead(true);
591 foreach (TaskInventoryItem item in m_items.Values)
443 { 592 {
444 foreach (TaskInventoryItem item in m_items.Values) 593 if (item.Name == name)
445 { 594 {
446 if (item.Name == name) 595 m_items.LockItemsForRead(false);
447 return true; 596 return true;
448 } 597 }
449 } 598 }
599 m_items.LockItemsForRead(false);
450 return false; 600 return false;
451 } 601 }
452 602
@@ -488,8 +638,9 @@ namespace OpenSim.Region.Framework.Scenes
488 /// <param name="item"></param> 638 /// <param name="item"></param>
489 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 639 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
490 { 640 {
491 List<TaskInventoryItem> il = GetInventoryItems(); 641 m_items.LockItemsForRead(true);
492 642 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
643 m_items.LockItemsForRead(false);
493 foreach (TaskInventoryItem i in il) 644 foreach (TaskInventoryItem i in il)
494 { 645 {
495 if (i.Name == item.Name) 646 if (i.Name == item.Name)
@@ -527,14 +678,14 @@ namespace OpenSim.Region.Framework.Scenes
527 item.Name = name; 678 item.Name = name;
528 item.GroupID = m_part.GroupID; 679 item.GroupID = m_part.GroupID;
529 680
530 lock (m_items) 681 m_items.LockItemsForWrite(true);
531 m_items.Add(item.ItemID, item); 682 m_items.Add(item.ItemID, item);
532 683 m_items.LockItemsForWrite(false);
533 if (allowedDrop) 684 if (allowedDrop)
534 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 685 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
535 else 686 else
536 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 687 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
537 688
538 m_inventorySerial++; 689 m_inventorySerial++;
539 //m_inventorySerial += 2; 690 //m_inventorySerial += 2;
540 HasInventoryChanged = true; 691 HasInventoryChanged = true;
@@ -550,15 +701,15 @@ namespace OpenSim.Region.Framework.Scenes
550 /// <param name="items"></param> 701 /// <param name="items"></param>
551 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 702 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
552 { 703 {
553 lock (m_items) 704 m_items.LockItemsForWrite(true);
705 foreach (TaskInventoryItem item in items)
554 { 706 {
555 foreach (TaskInventoryItem item in items) 707 m_items.Add(item.ItemID, item);
556 { 708// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
557 m_items.Add(item.ItemID, item);
558// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
559 }
560 m_inventorySerial++;
561 } 709 }
710 m_items.LockItemsForWrite(false);
711
712 m_inventorySerial++;
562 } 713 }
563 714
564 /// <summary> 715 /// <summary>
@@ -569,10 +720,9 @@ namespace OpenSim.Region.Framework.Scenes
569 public TaskInventoryItem GetInventoryItem(UUID itemId) 720 public TaskInventoryItem GetInventoryItem(UUID itemId)
570 { 721 {
571 TaskInventoryItem item; 722 TaskInventoryItem item;
572 723 m_items.LockItemsForRead(true);
573 lock (m_items) 724 m_items.TryGetValue(itemId, out item);
574 m_items.TryGetValue(itemId, out item); 725 m_items.LockItemsForRead(false);
575
576 return item; 726 return item;
577 } 727 }
578 728
@@ -588,15 +738,16 @@ namespace OpenSim.Region.Framework.Scenes
588 { 738 {
589 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 739 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
590 740
591 lock (m_items) 741 m_items.LockItemsForRead(true);
742
743 foreach (TaskInventoryItem item in m_items.Values)
592 { 744 {
593 foreach (TaskInventoryItem item in m_items.Values) 745 if (item.Name == name)
594 { 746 items.Add(item);
595 if (item.Name == name)
596 items.Add(item);
597 }
598 } 747 }
599 748
749 m_items.LockItemsForRead(false);
750
600 return items; 751 return items;
601 } 752 }
602 753
@@ -679,9 +830,9 @@ namespace OpenSim.Region.Framework.Scenes
679 830
680 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 831 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
681 { 832 {
682 TaskInventoryItem it = GetInventoryItem(item.ItemID); 833 m_items.LockItemsForWrite(true);
683 if (it != null)
684 834
835 if (m_items.ContainsKey(item.ItemID))
685 { 836 {
686 item.ParentID = m_part.UUID; 837 item.ParentID = m_part.UUID;
687 item.ParentPartID = m_part.UUID; 838 item.ParentPartID = m_part.UUID;
@@ -693,14 +844,10 @@ namespace OpenSim.Region.Framework.Scenes
693 item.GroupID = m_part.GroupID; 844 item.GroupID = m_part.GroupID;
694 845
695 if (item.AssetID == UUID.Zero) 846 if (item.AssetID == UUID.Zero)
696 item.AssetID = it.AssetID; 847 item.AssetID = m_items[item.ItemID].AssetID;
697
698 lock (m_items)
699 {
700 m_items[item.ItemID] = item;
701 m_inventorySerial++;
702 }
703 848
849 m_items[item.ItemID] = item;
850 m_inventorySerial++;
704 if (fireScriptEvents) 851 if (fireScriptEvents)
705 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 852 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
706 if (considerChanged) 853 if (considerChanged)
@@ -708,6 +855,7 @@ namespace OpenSim.Region.Framework.Scenes
708 HasInventoryChanged = true; 855 HasInventoryChanged = true;
709 m_part.ParentGroup.HasGroupChanged = true; 856 m_part.ParentGroup.HasGroupChanged = true;
710 } 857 }
858 m_items.LockItemsForWrite(false);
711 return true; 859 return true;
712 } 860 }
713 else 861 else
@@ -718,8 +866,9 @@ namespace OpenSim.Region.Framework.Scenes
718 item.ItemID, m_part.Name, m_part.UUID, 866 item.ItemID, m_part.Name, m_part.UUID,
719 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 867 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
720 } 868 }
721 return false; 869 m_items.LockItemsForWrite(false);
722 870
871 return false;
723 } 872 }
724 873
725 /// <summary> 874 /// <summary>
@@ -730,37 +879,53 @@ namespace OpenSim.Region.Framework.Scenes
730 /// in this prim's inventory.</returns> 879 /// in this prim's inventory.</returns>
731 public int RemoveInventoryItem(UUID itemID) 880 public int RemoveInventoryItem(UUID itemID)
732 { 881 {
733 TaskInventoryItem item = GetInventoryItem(itemID); 882 m_items.LockItemsForRead(true);
734 if (item != null) 883
884 if (m_items.ContainsKey(itemID))
735 { 885 {
736 int type = m_items[itemID].InvType; 886 int type = m_items[itemID].InvType;
887 m_items.LockItemsForRead(false);
737 if (type == 10) // Script 888 if (type == 10) // Script
738 { 889 {
739 m_part.RemoveScriptEvents(itemID);
740 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 890 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
741 } 891 }
892 m_items.LockItemsForWrite(true);
742 m_items.Remove(itemID); 893 m_items.Remove(itemID);
894 m_items.LockItemsForWrite(false);
743 m_inventorySerial++; 895 m_inventorySerial++;
744 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 896 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
745 897
746 HasInventoryChanged = true; 898 HasInventoryChanged = true;
747 m_part.ParentGroup.HasGroupChanged = true; 899 m_part.ParentGroup.HasGroupChanged = true;
748 900
749 if (!ContainsScripts()) 901 int scriptcount = 0;
902 m_items.LockItemsForRead(true);
903 foreach (TaskInventoryItem item in m_items.Values)
904 {
905 if (item.Type == 10)
906 {
907 scriptcount++;
908 }
909 }
910 m_items.LockItemsForRead(false);
911
912
913 if (scriptcount <= 0)
914 {
750 m_part.RemFlag(PrimFlags.Scripted); 915 m_part.RemFlag(PrimFlags.Scripted);
916 }
751 917
752 m_part.ScheduleFullUpdate(); 918 m_part.ScheduleFullUpdate();
753 919
754 return type; 920 return type;
755
756 } 921 }
757 else 922 else
758 { 923 {
924 m_items.LockItemsForRead(false);
759 m_log.ErrorFormat( 925 m_log.ErrorFormat(
760 "[PRIM INVENTORY]: " + 926 "[PRIM INVENTORY]: " +
761 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 927 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
762 itemID, m_part.Name, m_part.UUID, 928 itemID, m_part.Name, m_part.UUID);
763 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
764 } 929 }
765 930
766 return -1; 931 return -1;
@@ -789,73 +954,81 @@ namespace OpenSim.Region.Framework.Scenes
789 954
790 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 955 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
791 956
792 lock (m_items) 957 Items.LockItemsForRead(true);
958
959 if (m_inventorySerial == 0) // No inventory
793 { 960 {
794 if (m_inventorySerial == 0) // No inventory 961 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
795 { 962 return;
796 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 963 }
797 return;
798 }
799 964
800 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, 965 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
801 Util.StringToBytes256(m_inventoryFileName)); 966 Util.StringToBytes256(m_inventoryFileName));
802 967
803 if (!changed) 968 if (!changed)
969 {
970 if (m_inventoryFileData.Length > 2)
804 { 971 {
805 if (m_inventoryFileData.Length > 2) 972 xferManager.AddNewFile(m_inventoryFileName,
806 { 973 m_inventoryFileData);
807 xferManager.AddNewFile(m_inventoryFileName, 974 return;
808 m_inventoryFileData);
809 return;
810 }
811 } 975 }
976 }
812 977
813 foreach (TaskInventoryItem item in m_items.Values) 978 bool includeAssets = false;
814 { 979 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
815 UUID ownerID = item.OwnerID; 980 includeAssets = true;
816 uint everyoneMask = 0; 981
817 uint baseMask = item.BasePermissions; 982 foreach (TaskInventoryItem item in m_items.Values)
818 uint ownerMask = item.CurrentPermissions; 983 {
819 uint groupMask = item.GroupPermissions; 984 UUID ownerID = item.OwnerID;
985 uint everyoneMask = 0;
986 uint baseMask = item.BasePermissions;
987 uint ownerMask = item.CurrentPermissions;
988 uint groupMask = item.GroupPermissions;
820 989
821 invString.AddItemStart(); 990 invString.AddItemStart();
822 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 991 invString.AddNameValueLine("item_id", item.ItemID.ToString());
823 invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); 992 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
824 993
825 invString.AddPermissionsStart(); 994 invString.AddPermissionsStart();
826 995
827 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 996 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
828 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 997 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
829 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 998 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
830 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); 999 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
831 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); 1000 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
832 1001
833 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 1002 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
834 invString.AddNameValueLine("owner_id", ownerID.ToString()); 1003 invString.AddNameValueLine("owner_id", ownerID.ToString());
835 1004
836 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1005 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
837 1006
838 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1007 invString.AddNameValueLine("group_id", item.GroupID.ToString());
839 invString.AddSectionEnd(); 1008 invString.AddSectionEnd();
840 1009
1010 if (includeAssets)
841 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1011 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
842 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); 1012 else
843 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); 1013 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
844 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); 1014 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
1015 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
1016 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
845 1017
846 invString.AddSaleStart(); 1018 invString.AddSaleStart();
847 invString.AddNameValueLine("sale_type", "not"); 1019 invString.AddNameValueLine("sale_type", "not");
848 invString.AddNameValueLine("sale_price", "0"); 1020 invString.AddNameValueLine("sale_price", "0");
849 invString.AddSectionEnd(); 1021 invString.AddSectionEnd();
850 1022
851 invString.AddNameValueLine("name", item.Name + "|"); 1023 invString.AddNameValueLine("name", item.Name + "|");
852 invString.AddNameValueLine("desc", item.Description + "|"); 1024 invString.AddNameValueLine("desc", item.Description + "|");
853 1025
854 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1026 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
855 invString.AddSectionEnd(); 1027 invString.AddSectionEnd();
856 }
857 } 1028 }
858 1029
1030 Items.LockItemsForRead(false);
1031
859 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1032 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
860 1033
861 if (m_inventoryFileData.Length > 2) 1034 if (m_inventoryFileData.Length > 2)
@@ -872,10 +1045,11 @@ namespace OpenSim.Region.Framework.Scenes
872 { 1045 {
873 if (HasInventoryChanged) 1046 if (HasInventoryChanged)
874 { 1047 {
875 HasInventoryChanged = false; 1048 Items.LockItemsForRead(true);
876 List<TaskInventoryItem> items = GetInventoryItems(); 1049 datastore.StorePrimInventory(m_part.UUID, Items.Values);
877 datastore.StorePrimInventory(m_part.UUID, items); 1050 Items.LockItemsForRead(false);
878 1051
1052 HasInventoryChanged = false;
879 } 1053 }
880 } 1054 }
881 1055
@@ -942,89 +1116,75 @@ namespace OpenSim.Region.Framework.Scenes
942 { 1116 {
943 uint mask=0x7fffffff; 1117 uint mask=0x7fffffff;
944 1118
945 lock (m_items) 1119 foreach (TaskInventoryItem item in m_items.Values)
946 { 1120 {
947 foreach (TaskInventoryItem item in m_items.Values) 1121 if (item.InvType != (int)InventoryType.Object)
948 { 1122 {
949 if (item.InvType != (int)InventoryType.Object) 1123 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
950 { 1124 mask &= ~((uint)PermissionMask.Copy >> 13);
951 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1125 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
952 mask &= ~((uint)PermissionMask.Copy >> 13); 1126 mask &= ~((uint)PermissionMask.Transfer >> 13);
953 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1127 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
954 mask &= ~((uint)PermissionMask.Transfer >> 13); 1128 mask &= ~((uint)PermissionMask.Modify >> 13);
955 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
956 mask &= ~((uint)PermissionMask.Modify >> 13);
957 }
958 else
959 {
960 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
961 mask &= ~((uint)PermissionMask.Copy >> 13);
962 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
963 mask &= ~((uint)PermissionMask.Transfer >> 13);
964 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
965 mask &= ~((uint)PermissionMask.Modify >> 13);
966 }
967
968 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
969 mask &= ~(uint)PermissionMask.Copy;
970 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
971 mask &= ~(uint)PermissionMask.Transfer;
972 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
973 mask &= ~(uint)PermissionMask.Modify;
974 } 1129 }
1130 else
1131 {
1132 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1133 mask &= ~((uint)PermissionMask.Copy >> 13);
1134 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1135 mask &= ~((uint)PermissionMask.Transfer >> 13);
1136 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1137 mask &= ~((uint)PermissionMask.Modify >> 13);
1138 }
1139
1140 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1141 mask &= ~(uint)PermissionMask.Copy;
1142 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1143 mask &= ~(uint)PermissionMask.Transfer;
1144 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1145 mask &= ~(uint)PermissionMask.Modify;
975 } 1146 }
976
977 return mask; 1147 return mask;
978 } 1148 }
979 1149
980 public void ApplyNextOwnerPermissions() 1150 public void ApplyNextOwnerPermissions()
981 { 1151 {
982 lock (m_items) 1152 foreach (TaskInventoryItem item in m_items.Values)
983 { 1153 {
984 foreach (TaskInventoryItem item in m_items.Values) 1154 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
985 { 1155 {
986 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1156 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
987 { 1157 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
988 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1158 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
989 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1159 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
990 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1160 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
991 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1161 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
992 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
993 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
994 }
995 item.CurrentPermissions &= item.NextPermissions;
996 item.BasePermissions &= item.NextPermissions;
997 item.EveryonePermissions &= item.NextPermissions;
998 item.OwnerChanged = true;
999 } 1162 }
1163 item.OwnerChanged = true;
1164 item.CurrentPermissions &= item.NextPermissions;
1165 item.BasePermissions &= item.NextPermissions;
1166 item.EveryonePermissions &= item.NextPermissions;
1000 } 1167 }
1001 } 1168 }
1002 1169
1003 public void ApplyGodPermissions(uint perms) 1170 public void ApplyGodPermissions(uint perms)
1004 { 1171 {
1005 lock (m_items) 1172 foreach (TaskInventoryItem item in m_items.Values)
1006 { 1173 {
1007 foreach (TaskInventoryItem item in m_items.Values) 1174 item.CurrentPermissions = perms;
1008 { 1175 item.BasePermissions = perms;
1009 item.CurrentPermissions = perms;
1010 item.BasePermissions = perms;
1011 }
1012 } 1176 }
1013 } 1177 }
1014 1178
1015 public bool ContainsScripts() 1179 public bool ContainsScripts()
1016 { 1180 {
1017 lock (m_items) 1181 foreach (TaskInventoryItem item in m_items.Values)
1018 { 1182 {
1019 foreach (TaskInventoryItem item in m_items.Values) 1183 if (item.InvType == (int)InventoryType.LSL)
1020 { 1184 {
1021 if (item.InvType == (int)InventoryType.LSL) 1185 return true;
1022 {
1023 return true;
1024 }
1025 } 1186 }
1026 } 1187 }
1027
1028 return false; 1188 return false;
1029 } 1189 }
1030 1190
@@ -1032,11 +1192,8 @@ namespace OpenSim.Region.Framework.Scenes
1032 { 1192 {
1033 List<UUID> ret = new List<UUID>(); 1193 List<UUID> ret = new List<UUID>();
1034 1194
1035 lock (m_items) 1195 foreach (TaskInventoryItem item in m_items.Values)
1036 { 1196 ret.Add(item.ItemID);
1037 foreach (TaskInventoryItem item in m_items.Values)
1038 ret.Add(item.ItemID);
1039 }
1040 1197
1041 return ret; 1198 return ret;
1042 } 1199 }
@@ -1067,31 +1224,46 @@ namespace OpenSim.Region.Framework.Scenes
1067 1224
1068 public Dictionary<UUID, string> GetScriptStates() 1225 public Dictionary<UUID, string> GetScriptStates()
1069 { 1226 {
1227 return GetScriptStates(false);
1228 }
1229
1230 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1231 {
1070 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 1232 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
1071 1233
1072 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1234 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1073 if (engines == null) // No engine at all 1235 if (engines == null) // No engine at all
1074 return ret; 1236 return ret;
1075 1237
1076 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1238 Items.LockItemsForRead(true);
1077 1239 foreach (TaskInventoryItem item in m_items.Values)
1078 foreach (TaskInventoryItem item in scripts)
1079 { 1240 {
1080 foreach (IScriptModule e in engines) 1241 if (item.InvType == (int)InventoryType.LSL)
1081 { 1242 {
1082 if (e != null) 1243 foreach (IScriptModule e in engines)
1083 { 1244 {
1084 string n = e.GetXMLState(item.ItemID); 1245 if (e != null)
1085 if (n != String.Empty)
1086 { 1246 {
1087 if (!ret.ContainsKey(item.ItemID)) 1247 string n = e.GetXMLState(item.ItemID);
1088 ret[item.ItemID] = n; 1248 if (n != String.Empty)
1089 break; 1249 {
1250 if (oldIDs)
1251 {
1252 if (!ret.ContainsKey(item.OldItemID))
1253 ret[item.OldItemID] = n;
1254 }
1255 else
1256 {
1257 if (!ret.ContainsKey(item.ItemID))
1258 ret[item.ItemID] = n;
1259 }
1260 break;
1261 }
1090 } 1262 }
1091 } 1263 }
1092 } 1264 }
1093 } 1265 }
1094 1266 Items.LockItemsForRead(false);
1095 return ret; 1267 return ret;
1096 } 1268 }
1097 1269
@@ -1101,21 +1273,27 @@ namespace OpenSim.Region.Framework.Scenes
1101 if (engines == null) 1273 if (engines == null)
1102 return; 1274 return;
1103 1275
1104 List<TaskInventoryItem> scripts = GetInventoryScripts();
1105 1276
1106 foreach (TaskInventoryItem item in scripts) 1277 Items.LockItemsForRead(true);
1278
1279 foreach (TaskInventoryItem item in m_items.Values)
1107 { 1280 {
1108 foreach (IScriptModule engine in engines) 1281 if (item.InvType == (int)InventoryType.LSL)
1109 { 1282 {
1110 if (engine != null) 1283 foreach (IScriptModule engine in engines)
1111 { 1284 {
1112 if (item.OwnerChanged) 1285 if (engine != null)
1113 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1286 {
1114 item.OwnerChanged = false; 1287 if (item.OwnerChanged)
1115 engine.ResumeScript(item.ItemID); 1288 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1289 item.OwnerChanged = false;
1290 engine.ResumeScript(item.ItemID);
1291 }
1116 } 1292 }
1117 } 1293 }
1118 } 1294 }
1295
1296 Items.LockItemsForRead(false);
1119 } 1297 }
1120 } 1298 }
1121} 1299}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 46234f9..557fc42 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,7 +461,8 @@ 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 else 467 else
449 { 468 {
@@ -492,7 +511,8 @@ namespace OpenSim.Region.Framework.Scenes
492 } 511 }
493 } 512 }
494 513
495 m_pos = value; 514 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
515 m_pos = value;
496 m_parentPosition = Vector3.Zero; 516 m_parentPosition = Vector3.Zero;
497 } 517 }
498 } 518 }
@@ -536,10 +556,39 @@ namespace OpenSim.Region.Framework.Scenes
536 } 556 }
537 } 557 }
538 558
559 public Quaternion OffsetRotation
560 {
561 get { return m_offsetRotation; }
562 set { m_offsetRotation = value; }
563 }
564
539 public Quaternion Rotation 565 public Quaternion Rotation
540 { 566 {
541 get { return m_bodyRot; } 567 get {
542 set { m_bodyRot = value; } 568 if (m_parentID != 0)
569 {
570 if (m_offsetRotation != null)
571 {
572 return m_offsetRotation;
573 }
574 else
575 {
576 return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
577 }
578
579 }
580 else
581 {
582 return m_bodyRot;
583 }
584 }
585 set {
586 m_bodyRot = value;
587 if (m_parentID != 0)
588 {
589 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
590 }
591 }
543 } 592 }
544 593
545 public Quaternion PreviousRotation 594 public Quaternion PreviousRotation
@@ -564,11 +613,21 @@ namespace OpenSim.Region.Framework.Scenes
564 613
565 private uint m_parentID; 614 private uint m_parentID;
566 615
616
617 private UUID m_linkedPrim;
618
567 public uint ParentID 619 public uint ParentID
568 { 620 {
569 get { return m_parentID; } 621 get { return m_parentID; }
570 set { m_parentID = value; } 622 set { m_parentID = value; }
571 } 623 }
624
625 public UUID LinkedPrim
626 {
627 get { return m_linkedPrim; }
628 set { m_linkedPrim = value; }
629 }
630
572 public float Health 631 public float Health
573 { 632 {
574 get { return m_health; } 633 get { return m_health; }
@@ -690,7 +749,7 @@ namespace OpenSim.Region.Framework.Scenes
690 CreateSceneViewer(); 749 CreateSceneViewer();
691 m_animator = new ScenePresenceAnimator(this); 750 m_animator = new ScenePresenceAnimator(this);
692 } 751 }
693 752
694 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() 753 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
695 { 754 {
696 m_rootRegionHandle = reginfo.RegionHandle; 755 m_rootRegionHandle = reginfo.RegionHandle;
@@ -722,10 +781,7 @@ namespace OpenSim.Region.Framework.Scenes
722 m_reprioritization_timer.AutoReset = false; 781 m_reprioritization_timer.AutoReset = false;
723 782
724 AdjustKnownSeeds(); 783 AdjustKnownSeeds();
725
726 // TODO: I think, this won't send anything, as we are still a child here...
727 Animator.TrySetMovementAnimation("STAND"); 784 Animator.TrySetMovementAnimation("STAND");
728
729 // we created a new ScenePresence (a new child agent) in a fresh region. 785 // we created a new ScenePresence (a new child agent) in a fresh region.
730 // Request info about all the (root) agents in this region 786 // Request info about all the (root) agents in this region
731 // Note: This won't send data *to* other clients in that region (children don't send) 787 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -776,25 +832,47 @@ namespace OpenSim.Region.Framework.Scenes
776 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 832 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
777 Dir_Vectors[4] = Vector3.UnitZ; //UP 833 Dir_Vectors[4] = Vector3.UnitZ; //UP
778 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 834 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
779 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 835 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
780 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 836 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
781 Dir_Vectors[7] = -Vector3.UnitX; //BACK 837 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
838 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
839 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
782 } 840 }
783 841
784 private Vector3[] GetWalkDirectionVectors() 842 private Vector3[] GetWalkDirectionVectors()
785 { 843 {
786 Vector3[] vector = new Vector3[9]; 844 Vector3[] vector = new Vector3[11];
787 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 845 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
788 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 846 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
789 vector[2] = Vector3.UnitY; //LEFT 847 vector[2] = Vector3.UnitY; //LEFT
790 vector[3] = -Vector3.UnitY; //RIGHT 848 vector[3] = -Vector3.UnitY; //RIGHT
791 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 849 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
792 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 850 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
793 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 851 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
794 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 852 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
795 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 853 vector[8] = Vector3.UnitY; //LEFT_NUDGE
854 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
855 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
796 return vector; 856 return vector;
797 } 857 }
858
859 private bool[] GetDirectionIsNudge()
860 {
861 bool[] isNudge = new bool[11];
862 isNudge[0] = false; //FORWARD
863 isNudge[1] = false; //BACK
864 isNudge[2] = false; //LEFT
865 isNudge[3] = false; //RIGHT
866 isNudge[4] = false; //UP
867 isNudge[5] = false; //DOWN
868 isNudge[6] = true; //FORWARD_NUDGE
869 isNudge[7] = true; //BACK_NUDGE
870 isNudge[8] = true; //LEFT_NUDGE
871 isNudge[9] = true; //RIGHT_NUDGE
872 isNudge[10] = true; //DOWN_Nudge
873 return isNudge;
874 }
875
798 876
799 #endregion 877 #endregion
800 878
@@ -856,6 +934,54 @@ namespace OpenSim.Region.Framework.Scenes
856 pos.Y = crossedBorder.BorderLine.Z - 1; 934 pos.Y = crossedBorder.BorderLine.Z - 1;
857 } 935 }
858 936
937 //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
938 //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
939 //they'll bypass the landing point. But I can't think of any decent way of fixing this.
940 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
941 if (land != null)
942 {
943 if (KnownChildRegionHandles.Count == 0)
944 {
945 //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
946 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)
947 {
948 pos = land.LandData.UserLocation;
949 }
950 }
951
952 land.SendLandUpdateToClient(ControllingClient);
953 }
954
955 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
956 {
957 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
958
959 if (pos.X < 0)
960 {
961 emergencyPos.X = (int)Constants.RegionSize + pos.X;
962 if (!(pos.Y < 0))
963 emergencyPos.Y = pos.Y;
964 if (!(pos.Z < 0))
965 emergencyPos.Z = pos.Z;
966 }
967 if (pos.Y < 0)
968 {
969 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
970 if (!(pos.X < 0))
971 emergencyPos.X = pos.X;
972 if (!(pos.Z < 0))
973 emergencyPos.Z = pos.Z;
974 }
975 if (pos.Z < 0)
976 {
977 emergencyPos.Z = 128;
978 if (!(pos.Y < 0))
979 emergencyPos.Y = pos.Y;
980 if (!(pos.X < 0))
981 emergencyPos.X = pos.X;
982 }
983 }
984
859 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 985 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
860 { 986 {
861 m_log.WarnFormat( 987 m_log.WarnFormat(
@@ -984,12 +1110,17 @@ namespace OpenSim.Region.Framework.Scenes
984 { 1110 {
985 if (PhysicsActor != null) 1111 if (PhysicsActor != null)
986 { 1112 {
987 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1113 try
988 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; 1114 {
989 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1115 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
990 m_physicsActor.UnSubscribeEvents(); 1116 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
991 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1117 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
992 PhysicsActor = null; 1118 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1119 m_physicsActor.UnSubscribeEvents();
1120 PhysicsActor = null;
1121 }
1122 catch
1123 { }
993 } 1124 }
994 } 1125 }
995 1126
@@ -1000,9 +1131,10 @@ namespace OpenSim.Region.Framework.Scenes
1000 public void Teleport(Vector3 pos) 1131 public void Teleport(Vector3 pos)
1001 { 1132 {
1002 bool isFlying = false; 1133 bool isFlying = false;
1134
1003 if (m_physicsActor != null) 1135 if (m_physicsActor != null)
1004 isFlying = m_physicsActor.Flying; 1136 isFlying = m_physicsActor.Flying;
1005 1137
1006 RemoveFromPhysicalScene(); 1138 RemoveFromPhysicalScene();
1007 Velocity = Vector3.Zero; 1139 Velocity = Vector3.Zero;
1008 AbsolutePosition = pos; 1140 AbsolutePosition = pos;
@@ -1014,6 +1146,7 @@ namespace OpenSim.Region.Framework.Scenes
1014 } 1146 }
1015 1147
1016 SendTerseUpdateToAllClients(); 1148 SendTerseUpdateToAllClients();
1149
1017 } 1150 }
1018 1151
1019 public void TeleportWithMomentum(Vector3 pos) 1152 public void TeleportWithMomentum(Vector3 pos)
@@ -1232,6 +1365,7 @@ namespace OpenSim.Region.Framework.Scenes
1232 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1365 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1233 1366
1234 m_pos = m_LastFinitePos; 1367 m_pos = m_LastFinitePos;
1368
1235 if (!m_pos.IsFinite()) 1369 if (!m_pos.IsFinite())
1236 { 1370 {
1237 m_pos.X = 127f; 1371 m_pos.X = 127f;
@@ -1298,7 +1432,6 @@ namespace OpenSim.Region.Framework.Scenes
1298 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1432 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1299 } 1433 }
1300 } 1434 }
1301
1302 lock (scriptedcontrols) 1435 lock (scriptedcontrols)
1303 { 1436 {
1304 if (scriptedcontrols.Count > 0) 1437 if (scriptedcontrols.Count > 0)
@@ -1313,6 +1446,9 @@ namespace OpenSim.Region.Framework.Scenes
1313 1446
1314 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1447 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1315 { 1448 {
1449 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1450 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1451
1316 // TODO: This doesn't prevent the user from walking yet. 1452 // TODO: This doesn't prevent the user from walking yet.
1317 // Setting parent ID would fix this, if we knew what value 1453 // Setting parent ID would fix this, if we knew what value
1318 // to use. Or we could add a m_isSitting variable. 1454 // to use. Or we could add a m_isSitting variable.
@@ -1361,12 +1497,20 @@ namespace OpenSim.Region.Framework.Scenes
1361 if (actor.Flying != oldflying) 1497 if (actor.Flying != oldflying)
1362 update_movementflag = true; 1498 update_movementflag = true;
1363 1499
1500 if (m_animator.m_jumping) // add for jumping
1501 update_movementflag = true;
1502
1364 if (q != m_bodyRot) 1503 if (q != m_bodyRot)
1365 { 1504 {
1366 m_bodyRot = q; 1505 m_bodyRot = q;
1367 update_rotation = true; 1506 update_rotation = true;
1368 } 1507 }
1369 1508
1509 //guilty until proven innocent..
1510 bool Nudging = true;
1511 //Basically, if there is at least one non-nudge control then we don't need
1512 //to worry about stopping the avatar
1513
1370 if (m_parentID == 0) 1514 if (m_parentID == 0)
1371 { 1515 {
1372 bool bAllowUpdateMoveToPosition = false; 1516 bool bAllowUpdateMoveToPosition = false;
@@ -1381,9 +1525,12 @@ namespace OpenSim.Region.Framework.Scenes
1381 else 1525 else
1382 dirVectors = Dir_Vectors; 1526 dirVectors = Dir_Vectors;
1383 1527
1384 // The fact that m_movementflag is a byte needs to be fixed 1528 bool[] isNudge = GetDirectionIsNudge();
1385 // it really should be a uint 1529
1386 uint nudgehack = 250; 1530
1531
1532
1533
1387 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1534 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1388 { 1535 {
1389 if (((uint)flags & (uint)DCF) != 0) 1536 if (((uint)flags & (uint)DCF) != 0)
@@ -1393,40 +1540,28 @@ namespace OpenSim.Region.Framework.Scenes
1393 try 1540 try
1394 { 1541 {
1395 agent_control_v3 += dirVectors[i]; 1542 agent_control_v3 += dirVectors[i];
1396 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1543 if (isNudge[i] == false)
1544 {
1545 Nudging = false;
1546 }
1397 } 1547 }
1398 catch (IndexOutOfRangeException) 1548 catch (IndexOutOfRangeException)
1399 { 1549 {
1400 // Why did I get this? 1550 // Why did I get this?
1401 } 1551 }
1402 1552
1403 if ((m_movementflag & (byte)(uint)DCF) == 0) 1553 if ((m_movementflag & (uint)DCF) == 0)
1404 { 1554 {
1405 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1406 {
1407 m_movementflag |= (byte)nudgehack;
1408 }
1409 m_movementflag += (byte)(uint)DCF; 1555 m_movementflag += (byte)(uint)DCF;
1410 update_movementflag = true; 1556 update_movementflag = true;
1411 } 1557 }
1412 } 1558 }
1413 else 1559 else
1414 { 1560 {
1415 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1561 if ((m_movementflag & (uint)DCF) != 0)
1416 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1417 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1418 ) // This or is for Nudge forward
1419 { 1562 {
1420 m_movementflag -= ((byte)(uint)DCF); 1563 m_movementflag -= (byte)(uint)DCF;
1421
1422 update_movementflag = true; 1564 update_movementflag = true;
1423 /*
1424 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1425 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1426 {
1427 m_log.Debug("Removed Hack flag");
1428 }
1429 */
1430 } 1565 }
1431 else 1566 else
1432 { 1567 {
@@ -1435,7 +1570,6 @@ namespace OpenSim.Region.Framework.Scenes
1435 } 1570 }
1436 i++; 1571 i++;
1437 } 1572 }
1438
1439 //Paupaw:Do Proper PID for Autopilot here 1573 //Paupaw:Do Proper PID for Autopilot here
1440 if (bResetMoveToPosition) 1574 if (bResetMoveToPosition)
1441 { 1575 {
@@ -1470,6 +1604,9 @@ namespace OpenSim.Region.Framework.Scenes
1470 // Ignore z component of vector 1604 // Ignore z component of vector
1471 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1605 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1472 LocalVectorToTarget2D.Normalize(); 1606 LocalVectorToTarget2D.Normalize();
1607
1608 //We're not nudging
1609 Nudging = false;
1473 agent_control_v3 += LocalVectorToTarget2D; 1610 agent_control_v3 += LocalVectorToTarget2D;
1474 1611
1475 // update avatar movement flags. the avatar coordinate system is as follows: 1612 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1560,13 +1697,13 @@ namespace OpenSim.Region.Framework.Scenes
1560 // m_log.DebugFormat( 1697 // m_log.DebugFormat(
1561 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1698 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1562 1699
1563 AddNewMovement(agent_control_v3, q); 1700 AddNewMovement(agent_control_v3, q, Nudging);
1564 1701
1565 1702
1566 } 1703 }
1567 } 1704 }
1568 1705
1569 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1706 if (update_movementflag && !SitGround)
1570 Animator.UpdateMovementAnimations(); 1707 Animator.UpdateMovementAnimations();
1571 1708
1572 m_scene.EventManager.TriggerOnClientMovement(this); 1709 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1581,7 +1718,6 @@ namespace OpenSim.Region.Framework.Scenes
1581 m_sitAtAutoTarget = false; 1718 m_sitAtAutoTarget = false;
1582 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1719 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1583 //proxy.PCode = (byte)PCode.ParticleSystem; 1720 //proxy.PCode = (byte)PCode.ParticleSystem;
1584
1585 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1721 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1586 proxyObjectGroup.AttachToScene(m_scene); 1722 proxyObjectGroup.AttachToScene(m_scene);
1587 1723
@@ -1623,7 +1759,7 @@ namespace OpenSim.Region.Framework.Scenes
1623 } 1759 }
1624 m_moveToPositionInProgress = true; 1760 m_moveToPositionInProgress = true;
1625 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1761 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1626 } 1762 }
1627 catch (Exception ex) 1763 catch (Exception ex)
1628 { 1764 {
1629 //Why did I get this error? 1765 //Why did I get this error?
@@ -1645,7 +1781,7 @@ namespace OpenSim.Region.Framework.Scenes
1645 Velocity = Vector3.Zero; 1781 Velocity = Vector3.Zero;
1646 SendAvatarDataToAllAgents(); 1782 SendAvatarDataToAllAgents();
1647 1783
1648 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1784 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1649 } 1785 }
1650 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1786 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1651 m_requestedSitTargetUUID = UUID.Zero; 1787 m_requestedSitTargetUUID = UUID.Zero;
@@ -1682,25 +1818,22 @@ namespace OpenSim.Region.Framework.Scenes
1682 1818
1683 if (m_parentID != 0) 1819 if (m_parentID != 0)
1684 { 1820 {
1685 m_log.Debug("StandupCode Executed"); 1821 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1686 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1687 if (part != null) 1822 if (part != null)
1688 { 1823 {
1824 part.TaskInventory.LockItemsForRead(true);
1689 TaskInventoryDictionary taskIDict = part.TaskInventory; 1825 TaskInventoryDictionary taskIDict = part.TaskInventory;
1690 if (taskIDict != null) 1826 if (taskIDict != null)
1691 { 1827 {
1692 lock (taskIDict) 1828 foreach (UUID taskID in taskIDict.Keys)
1693 { 1829 {
1694 foreach (UUID taskID in taskIDict.Keys) 1830 UnRegisterControlEventsToScript(LocalId, taskID);
1695 { 1831 taskIDict[taskID].PermsMask &= ~(
1696 UnRegisterControlEventsToScript(LocalId, taskID); 1832 2048 | //PERMISSION_CONTROL_CAMERA
1697 taskIDict[taskID].PermsMask &= ~( 1833 4); // PERMISSION_TAKE_CONTROLS
1698 2048 | //PERMISSION_CONTROL_CAMERA
1699 4); // PERMISSION_TAKE_CONTROLS
1700 }
1701 } 1834 }
1702
1703 } 1835 }
1836 part.TaskInventory.LockItemsForRead(false);
1704 // Reset sit target. 1837 // Reset sit target.
1705 if (part.GetAvatarOnSitTarget() == UUID) 1838 if (part.GetAvatarOnSitTarget() == UUID)
1706 part.SitTargetAvatar = UUID.Zero; 1839 part.SitTargetAvatar = UUID.Zero;
@@ -1709,16 +1842,55 @@ namespace OpenSim.Region.Framework.Scenes
1709 m_parentPosition = part.GetWorldPosition(); 1842 m_parentPosition = part.GetWorldPosition();
1710 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1843 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1711 } 1844 }
1845 // part.GetWorldRotation() is the rotation of the object being sat on
1846 // Rotation is the sittiing Av's rotation
1847
1848 Quaternion partRot;
1849// if (part.LinkNum == 1)
1850// { // Root prim of linkset
1851// partRot = part.ParentGroup.RootPart.RotationOffset;
1852// }
1853// else
1854// { // single or child prim
1855
1856// }
1857 if (part == null) //CW: Part may be gone. llDie() for example.
1858 {
1859 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1860 }
1861 else
1862 {
1863 partRot = part.GetWorldRotation();
1864 }
1865
1866 Quaternion partIRot = Quaternion.Inverse(partRot);
1712 1867
1868 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1869 Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
1870
1871
1713 if (m_physicsActor == null) 1872 if (m_physicsActor == null)
1714 { 1873 {
1715 AddToPhysicalScene(false); 1874 AddToPhysicalScene(false);
1716 } 1875 }
1717 1876 //CW: If the part isn't null then we can set the current position
1718 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1877 if (part != null)
1719 m_parentPosition = Vector3.Zero; 1878 {
1720 1879 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
1721 m_parentID = 0; 1880 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1881 part.IsOccupied = false;
1882 part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
1883 }
1884 else
1885 {
1886 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1887 AbsolutePosition = m_lastWorldPosition;
1888 }
1889
1890 m_parentPosition = Vector3.Zero;
1891 m_parentID = 0;
1892 m_linkedPrim = UUID.Zero;
1893 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1722 SendAvatarDataToAllAgents(); 1894 SendAvatarDataToAllAgents();
1723 m_requestedSitTargetID = 0; 1895 m_requestedSitTargetID = 0;
1724 if (m_physicsActor != null && m_appearance != null) 1896 if (m_physicsActor != null && m_appearance != null)
@@ -1727,7 +1899,6 @@ namespace OpenSim.Region.Framework.Scenes
1727 SetHeight(m_appearance.AvatarHeight); 1899 SetHeight(m_appearance.AvatarHeight);
1728 } 1900 }
1729 } 1901 }
1730
1731 Animator.TrySetMovementAnimation("STAND"); 1902 Animator.TrySetMovementAnimation("STAND");
1732 } 1903 }
1733 1904
@@ -1758,13 +1929,9 @@ namespace OpenSim.Region.Framework.Scenes
1758 Vector3 avSitOffSet = part.SitTargetPosition; 1929 Vector3 avSitOffSet = part.SitTargetPosition;
1759 Quaternion avSitOrientation = part.SitTargetOrientation; 1930 Quaternion avSitOrientation = part.SitTargetOrientation;
1760 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1931 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1761 1932 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1762 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1933 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1763 bool SitTargetisSet = 1934 if (SitTargetisSet && !SitTargetOccupied)
1764 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1765 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1766
1767 if (SitTargetisSet && SitTargetUnOccupied)
1768 { 1935 {
1769 //switch the target to this prim 1936 //switch the target to this prim
1770 return part; 1937 return part;
@@ -1778,85 +1945,167 @@ namespace OpenSim.Region.Framework.Scenes
1778 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 1945 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1779 { 1946 {
1780 bool autopilot = true; 1947 bool autopilot = true;
1948 Vector3 autopilotTarget = new Vector3();
1949 Quaternion sitOrientation = Quaternion.Identity;
1781 Vector3 pos = new Vector3(); 1950 Vector3 pos = new Vector3();
1782 Quaternion sitOrientation = pSitOrientation;
1783 Vector3 cameraEyeOffset = Vector3.Zero; 1951 Vector3 cameraEyeOffset = Vector3.Zero;
1784 Vector3 cameraAtOffset = Vector3.Zero; 1952 Vector3 cameraAtOffset = Vector3.Zero;
1785 bool forceMouselook = false; 1953 bool forceMouselook = false;
1786 1954
1787 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1955 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1788 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1956 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1789 if (part != null) 1957 if (part == null) return;
1790 { 1958
1791 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1959 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1792 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 1960 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1793 1961
1794 // Is a sit target available? 1962 // part is the prim to sit on
1795 Vector3 avSitOffSet = part.SitTargetPosition; 1963 // offset is the world-ref vector distance from that prim center to the click-spot
1796 Quaternion avSitOrientation = part.SitTargetOrientation; 1964 // UUID is the UUID of the Avatar doing the clicking
1797 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1965
1798 1966 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1799 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1967
1800 bool SitTargetisSet = 1968 // Is a sit target available?
1801 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1969 Vector3 avSitOffSet = part.SitTargetPosition;
1802 ( 1970 Quaternion avSitOrientation = part.SitTargetOrientation;
1803 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1971
1804 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 1972 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1805 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 1973 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1806 ) 1974 Quaternion partRot;
1807 )); 1975// if (part.LinkNum == 1)
1808 1976// { // Root prim of linkset
1809 if (SitTargetisSet && SitTargetUnOccupied) 1977// partRot = part.ParentGroup.RootPart.RotationOffset;
1810 { 1978// }
1811 part.SitTargetAvatar = UUID; 1979// else
1812 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1980// { // single or child prim
1813 sitOrientation = avSitOrientation; 1981 partRot = part.GetWorldRotation();
1814 autopilot = false; 1982// }
1815 } 1983 Quaternion partIRot = Quaternion.Inverse(partRot);
1816 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 1984//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1817 1985 // Sit analysis rewritten by KF 091125
1818 pos = part.AbsolutePosition + offset; 1986 if (SitTargetisSet) // scipted sit
1819 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 1987 {
1820 //{ 1988 if (!part.IsOccupied)
1821 // offset = pos; 1989 {
1822 //autopilot = false; 1990//Console.WriteLine("Scripted, unoccupied");
1823 //} 1991 part.SitTargetAvatar = UUID; // set that Av will be on it
1824 if (m_physicsActor != null) 1992 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1825 { 1993
1826 // If we're not using the client autopilot, we're immediately warping the avatar to the location 1994 Quaternion nrot = avSitOrientation;
1827 // We can remove the physicsActor until they stand up. 1995 if (!part.IsRoot)
1828 m_sitAvatarHeight = m_physicsActor.Size.Z;
1829
1830 if (autopilot)
1831 { 1996 {
1832 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1997 nrot = part.RotationOffset * avSitOrientation;
1833 {
1834 autopilot = false;
1835
1836 RemoveFromPhysicalScene();
1837 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1838 }
1839 } 1998 }
1840 else 1999 sitOrientation = nrot; // Change rotatione to the scripted one
2000 OffsetRotation = nrot;
2001 autopilot = false; // Jump direct to scripted llSitPos()
2002 }
2003 else
2004 {
2005//Console.WriteLine("Scripted, occupied");
2006 return;
2007 }
2008 }
2009 else // Not Scripted
2010 {
2011 if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
2012 {
2013 // large prim & offset, ignore if other Avs sitting
2014// offset.Z -= 0.05f;
2015 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
2016 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
2017
2018//Console.WriteLine(" offset ={0}", offset);
2019//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
2020//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
2021
2022 }
2023 else // small offset
2024 {
2025//Console.WriteLine("Small offset");
2026 if (!part.IsOccupied)
2027 {
2028 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
2029 autopilotTarget = part.AbsolutePosition;
2030//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
2031 }
2032 else return; // occupied small
2033 } // end large/small
2034 } // end Scripted/not
2035
2036 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2037
2038 cameraAtOffset = part.GetCameraAtOffset();
2039 cameraEyeOffset = part.GetCameraEyeOffset();
2040 forceMouselook = part.GetForceMouselook();
2041 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
2042 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
2043
2044 if (m_physicsActor != null)
2045 {
2046 // If we're not using the client autopilot, we're immediately warping the avatar to the location
2047 // We can remove the physicsActor until they stand up.
2048 m_sitAvatarHeight = m_physicsActor.Size.Z;
2049 if (autopilot)
2050 { // its not a scripted sit
2051// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
2052 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
1841 { 2053 {
2054 autopilot = false; // close enough
2055 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2056 Not using the part's position because returning the AV to the last known standing
2057 position is likely to be more friendly, isn't it? */
1842 RemoveFromPhysicalScene(); 2058 RemoveFromPhysicalScene();
1843 } 2059 Velocity = Vector3.Zero;
2060 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
2061 } // else the autopilot will get us close
2062 }
2063 else
2064 { // its a scripted sit
2065 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2066 I *am* using the part's position this time because we have no real idea how far away
2067 the avatar is from the sit target. */
2068 RemoveFromPhysicalScene();
2069 Velocity = Vector3.Zero;
1844 } 2070 }
1845
1846 cameraAtOffset = part.GetCameraAtOffset();
1847 cameraEyeOffset = part.GetCameraEyeOffset();
1848 forceMouselook = part.GetForceMouselook();
1849 } 2071 }
1850 2072 else return; // physactor is null!
1851 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 2073
1852 m_requestedSitTargetUUID = targetID; 2074 Vector3 offsetr; // = offset * partIRot;
2075 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
2076 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
2077 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
2078 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
2079 //offsetr = offset * partIRot;
2080//
2081 // else
2082 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
2083 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
2084 // (offset * partRot);
2085 // }
2086
2087//Console.WriteLine(" ");
2088//Console.WriteLine("link number ={0}", part.LinkNum);
2089//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2090//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2091//Console.WriteLine("Click offst ={0}", offset);
2092//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2093//Console.WriteLine("offsetr ={0}", offsetr);
2094//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2095//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2096
2097 //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
2098 ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2099
2100 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1853 // This calls HandleAgentSit twice, once from here, and the client calls 2101 // This calls HandleAgentSit twice, once from here, and the client calls
1854 // HandleAgentSit itself after it gets to the location 2102 // HandleAgentSit itself after it gets to the location
1855 // It doesn't get to the location until we've moved them there though 2103 // It doesn't get to the location until we've moved them there though
1856 // which happens in HandleAgentSit :P 2104 // which happens in HandleAgentSit :P
1857 m_autopilotMoving = autopilot; 2105 m_autopilotMoving = autopilot;
1858 m_autoPilotTarget = pos; 2106 m_autoPilotTarget = autopilotTarget;
1859 m_sitAtAutoTarget = autopilot; 2107 m_sitAtAutoTarget = autopilot;
2108 m_initialSitTarget = autopilotTarget;
1860 if (!autopilot) 2109 if (!autopilot)
1861 HandleAgentSit(remoteClient, UUID); 2110 HandleAgentSit(remoteClient, UUID);
1862 } 2111 }
@@ -2151,47 +2400,130 @@ namespace OpenSim.Region.Framework.Scenes
2151 { 2400 {
2152 if (part != null) 2401 if (part != null)
2153 { 2402 {
2403//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2154 if (part.GetAvatarOnSitTarget() == UUID) 2404 if (part.GetAvatarOnSitTarget() == UUID)
2155 { 2405 {
2406//Console.WriteLine("Scripted Sit");
2407 // Scripted sit
2156 Vector3 sitTargetPos = part.SitTargetPosition; 2408 Vector3 sitTargetPos = part.SitTargetPosition;
2157 Quaternion sitTargetOrient = part.SitTargetOrientation; 2409 Quaternion sitTargetOrient = part.SitTargetOrientation;
2158
2159 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2160 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2161
2162 //Quaternion result = (sitTargetOrient * vq) * nq;
2163
2164 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2410 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2165 m_pos += SIT_TARGET_ADJUSTMENT; 2411 m_pos += SIT_TARGET_ADJUSTMENT;
2412 if (!part.IsRoot)
2413 {
2414 m_pos *= part.RotationOffset;
2415 }
2166 m_bodyRot = sitTargetOrient; 2416 m_bodyRot = sitTargetOrient;
2167 //Rotation = sitTargetOrient;
2168 m_parentPosition = part.AbsolutePosition; 2417 m_parentPosition = part.AbsolutePosition;
2169 2418 part.IsOccupied = true;
2170 //SendTerseUpdateToAllClients(); 2419 part.ParentGroup.AddAvatar(agentID);
2171 } 2420 }
2172 else 2421 else
2173 { 2422 {
2174 m_pos -= part.AbsolutePosition; 2423 // if m_avUnscriptedSitPos is zero then Av sits above center
2424 // Else Av sits at m_avUnscriptedSitPos
2425
2426 // Non-scripted sit by Kitto Flora 21Nov09
2427 // Calculate angle of line from prim to Av
2428 Quaternion partIRot;
2429// if (part.LinkNum == 1)
2430// { // Root prim of linkset
2431// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2432// }
2433// else
2434// { // single or child prim
2435 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2436// }
2437 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2438 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2439 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2440 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2441 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2442 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2443 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2444 // Av sits at world euler <0,0, z>, translated by part rotation
2445 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2446
2175 m_parentPosition = part.AbsolutePosition; 2447 m_parentPosition = part.AbsolutePosition;
2176 } 2448 part.IsOccupied = true;
2449 part.ParentGroup.AddAvatar(agentID);
2450 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2451 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2452 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2453 m_avUnscriptedSitPos; // adds click offset, if any
2454 //Set up raytrace to find top surface of prim
2455 Vector3 size = part.Scale;
2456 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2457 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2458 Vector3 down = new Vector3(0f, 0f, -1f);
2459//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2460 m_scene.PhysicsScene.RaycastWorld(
2461 start, // Vector3 position,
2462 down, // Vector3 direction,
2463 mag, // float length,
2464 SitAltitudeCallback); // retMethod
2465 } // end scripted/not
2177 } 2466 }
2178 else 2467 else // no Av
2179 { 2468 {
2180 return; 2469 return;
2181 } 2470 }
2182 } 2471 }
2183 m_parentID = m_requestedSitTargetID;
2184 2472
2473 //We want our offsets to reference the root prim, not the child we may have sat on
2474 if (!part.IsRoot)
2475 {
2476 m_parentID = part.ParentGroup.RootPart.LocalId;
2477 m_pos += part.OffsetPosition;
2478 }
2479 else
2480 {
2481 m_parentID = m_requestedSitTargetID;
2482 }
2483
2484 m_linkedPrim = part.UUID;
2485 if (part.GetAvatarOnSitTarget() != UUID)
2486 {
2487 m_offsetRotation = m_offsetRotation / part.RotationOffset;
2488 }
2185 Velocity = Vector3.Zero; 2489 Velocity = Vector3.Zero;
2186 RemoveFromPhysicalScene(); 2490 RemoveFromPhysicalScene();
2187
2188 Animator.TrySetMovementAnimation(sitAnimation); 2491 Animator.TrySetMovementAnimation(sitAnimation);
2189 SendAvatarDataToAllAgents(); 2492 SendAvatarDataToAllAgents();
2190 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2191 // So we're also sending a terse update (which has avatar rotation)
2192 // [Update] We do now.
2193 //SendTerseUpdateToAllClients(); 2493 //SendTerseUpdateToAllClients();
2194 } 2494 }
2495
2496 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2497 {
2498 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2499 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2500 if(hitYN)
2501 {
2502 // m_pos = Av offset from prim center to make look like on center
2503 // m_parentPosition = Actual center pos of prim
2504 // collisionPoint = spot on prim where we want to sit
2505 // collisionPoint.Z = global sit surface height
2506 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2507 Quaternion partIRot;
2508// if (part.LinkNum == 1)
2509/// { // Root prim of linkset
2510// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2511// }
2512// else
2513// { // single or child prim
2514 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2515// }
2516 if (m_initialSitTarget != null)
2517 {
2518 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2519 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2520 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2521 m_pos += offset;
2522 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2523 }
2524
2525 }
2526 } // End SitAltitudeCallback KF.
2195 2527
2196 /// <summary> 2528 /// <summary>
2197 /// Event handler for the 'Always run' setting on the client 2529 /// Event handler for the 'Always run' setting on the client
@@ -2221,12 +2553,13 @@ namespace OpenSim.Region.Framework.Scenes
2221 /// </summary> 2553 /// </summary>
2222 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2554 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2223 /// <param name="rotation">The direction in which this avatar should now face. 2555 /// <param name="rotation">The direction in which this avatar should now face.
2224 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2556 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2225 { 2557 {
2226 if (m_isChildAgent) 2558 if (m_isChildAgent)
2227 { 2559 {
2228 // WHAT??? 2560 // WHAT???
2229 m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!"); 2561 m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent");
2562
2230 return; 2563 return;
2231 } 2564 }
2232 2565
@@ -2235,15 +2568,26 @@ namespace OpenSim.Region.Framework.Scenes
2235 Rotation = rotation; 2568 Rotation = rotation;
2236 Vector3 direc = vec * rotation; 2569 Vector3 direc = vec * rotation;
2237 direc.Normalize(); 2570 direc.Normalize();
2571 PhysicsActor actor = m_physicsActor;
2572
2573 if (actor.Flying != m_flyingOld) // add for fly velocity control
2574 {
2575 m_flyingOld = actor.Flying; // add for fly velocity control
2576 if (!actor.Flying) m_wasFlying = true; // add for fly velocity control
2577 }
2578
2579 if (m_physicsActor.IsColliding == true) m_wasFlying = false; // add for fly velocity control
2580
2581 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2238 2582
2239 direc *= 0.03f * 128f * m_speedModifier; 2583 direc *= 0.03f * 128f * m_speedModifier;
2240 2584
2241 PhysicsActor actor = m_physicsActor;
2242 if (actor != null) 2585 if (actor != null)
2243 { 2586 {
2244 if (actor.Flying) 2587 if (actor.Flying)
2245 { 2588 {
2246 direc *= 4.0f; 2589// rm speed mod direc *= 4.0f;
2590 direc *= 5.2f; // for speed mod
2247 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2591 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
2248 //bool colliding = (m_physicsActor.IsColliding==true); 2592 //bool colliding = (m_physicsActor.IsColliding==true);
2249 //if (controlland) 2593 //if (controlland)
@@ -2256,22 +2600,34 @@ namespace OpenSim.Region.Framework.Scenes
2256 // m_log.Info("[AGENT]: Stop FLying"); 2600 // m_log.Info("[AGENT]: Stop FLying");
2257 //} 2601 //}
2258 } 2602 }
2603 if (Animator.m_falling && m_wasFlying) // if falling from flying, disable motion add
2604 {
2605 direc *= 0.0f;
2606 }
2607 /* This jumping section removed to SPA
2259 else if (!actor.Flying && actor.IsColliding) 2608 else if (!actor.Flying && actor.IsColliding)
2260 { 2609 {
2261 if (direc.Z > 2.0f) 2610 if (direc.Z > 2.0f)
2262 { 2611 {
2263 direc.Z *= 3.0f; 2612 if(m_animator.m_animTickJump == -1)
2264 2613 {
2265 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2614 direc.Z *= 3.0f; // jump
2266 Animator.TrySetMovementAnimation("PREJUMP"); 2615 }
2267 Animator.TrySetMovementAnimation("JUMP"); 2616 else
2617 {
2618 direc.Z *= 0.1f; // prejump
2619 }
2620 / * Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
2621 Animator.TrySetMovementAnimation("PREJUMP");
2622 Animator.TrySetMovementAnimation("JUMP");
2623 * /
2268 } 2624 }
2269 } 2625 } */
2270 } 2626 }
2271 2627
2272 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2628 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2273 m_forceToApply = direc; 2629 m_forceToApply = direc;
2274 2630 m_isNudging = Nudging;
2275 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2631 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2276 } 2632 }
2277 2633
@@ -2320,6 +2676,9 @@ namespace OpenSim.Region.Framework.Scenes
2320 2676
2321 CheckForSignificantMovement(); // sends update to the modules. 2677 CheckForSignificantMovement(); // sends update to the modules.
2322 } 2678 }
2679
2680 //Sending prim updates AFTER the avatar terse updates are sent
2681 SendPrimUpdates();
2323 } 2682 }
2324 2683
2325 #endregion 2684 #endregion
@@ -3082,6 +3441,7 @@ namespace OpenSim.Region.Framework.Scenes
3082 m_callbackURI = cAgent.CallbackURI; 3441 m_callbackURI = cAgent.CallbackURI;
3083 3442
3084 m_pos = cAgent.Position; 3443 m_pos = cAgent.Position;
3444
3085 m_velocity = cAgent.Velocity; 3445 m_velocity = cAgent.Velocity;
3086 m_CameraCenter = cAgent.Center; 3446 m_CameraCenter = cAgent.Center;
3087 m_CameraAtAxis = cAgent.AtAxis; 3447 m_CameraAtAxis = cAgent.AtAxis;
@@ -3200,20 +3560,45 @@ namespace OpenSim.Region.Framework.Scenes
3200 /// </summary> 3560 /// </summary>
3201 public override void UpdateMovement() 3561 public override void UpdateMovement()
3202 { 3562 {
3203 if (m_forceToApply.HasValue) 3563 if (Animator!=null) // add for jumping
3204 { 3564 { // add for jumping
3205 Vector3 force = m_forceToApply.Value; 3565 // if (!m_animator.m_jumping) // add for jumping
3566 // { // add for jumping
3206 3567
3207 m_updateflag = true; 3568 if (m_forceToApply.HasValue) // this section realigned
3208 3569 {
3209 // The magic constant 0.95f seems to make walking feel less jerky,
3210 // probably because it hackishly accounts for the overall latency of
3211 // these Velocity updates -- Diva
3212 Velocity = force * .95F;
3213 3570
3214 m_forceToApply = null; 3571 Vector3 force = m_forceToApply.Value;
3215 } 3572 m_updateflag = true;
3216 } 3573if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3574 Velocity = force;
3575//Console.WriteLine("UM1 {0}", Velocity);
3576 m_forceToApply = null;
3577 }
3578 else
3579 {
3580 if (m_isNudging)
3581 {
3582 Vector3 force = Vector3.Zero;
3583
3584 m_updateflag = true;
3585if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3586 Velocity = force;
3587//Console.WriteLine("UM2 {0}", Velocity);
3588 m_isNudging = false;
3589 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3590 }
3591 else // add for jumping
3592 { // add for jumping
3593 Vector3 force = Vector3.Zero; // add for jumping
3594if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3595//Console.WriteLine("UM3 {0}", Velocity);
3596 Velocity = force; // add for jumping
3597 }
3598 }
3599 // } // end realign
3600 } // add for jumping
3601 } // add for jumping
3217 3602
3218 /// <summary> 3603 /// <summary>
3219 /// Adds a physical representation of the avatar to the Physics plugin 3604 /// Adds a physical representation of the avatar to the Physics plugin
@@ -3227,10 +3612,8 @@ namespace OpenSim.Region.Framework.Scenes
3227 3612
3228 Vector3 pVec = AbsolutePosition; 3613 Vector3 pVec = AbsolutePosition;
3229 3614
3230 // Old bug where the height was in centimeters instead of meters
3231 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, 3615 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
3232 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying); 3616 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
3233
3234 scene.AddPhysicsActorTaint(m_physicsActor); 3617 scene.AddPhysicsActorTaint(m_physicsActor);
3235 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3618 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3236 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3619 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
@@ -3254,18 +3637,29 @@ namespace OpenSim.Region.Framework.Scenes
3254 { 3637 {
3255 if (e == null) 3638 if (e == null)
3256 return; 3639 return;
3257 3640
3258 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3641 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3259 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3260 // as of this comment the interval is set in AddToPhysicalScene 3642 // as of this comment the interval is set in AddToPhysicalScene
3261 if (Animator!=null) 3643 if (Animator!=null)
3262 Animator.UpdateMovementAnimations(); 3644 {
3645 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3646 { // else its will lock out other animation changes, like ground sit.
3647 Animator.UpdateMovementAnimations();
3648 m_updateCount--;
3649 }
3650 }
3263 3651
3264 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3652 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3265 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3653 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3266 3654
3267 CollisionPlane = Vector4.UnitW; 3655 CollisionPlane = Vector4.UnitW;
3268 3656
3657 if (m_lastColCount != coldata.Count)
3658 {
3659 m_updateCount = UPDATE_COUNT;
3660 m_lastColCount = coldata.Count;
3661 }
3662
3269 if (coldata.Count != 0 && Animator != null) 3663 if (coldata.Count != 0 && Animator != null)
3270 { 3664 {
3271 switch (Animator.CurrentMovementAnimation) 3665 switch (Animator.CurrentMovementAnimation)
@@ -3295,6 +3689,148 @@ namespace OpenSim.Region.Framework.Scenes
3295 } 3689 }
3296 } 3690 }
3297 3691
3692 List<uint> thisHitColliders = new List<uint>();
3693 List<uint> endedColliders = new List<uint>();
3694 List<uint> startedColliders = new List<uint>();
3695
3696 foreach (uint localid in coldata.Keys)
3697 {
3698 thisHitColliders.Add(localid);
3699 if (!m_lastColliders.Contains(localid))
3700 {
3701 startedColliders.Add(localid);
3702 }
3703 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3704 }
3705
3706 // calculate things that ended colliding
3707 foreach (uint localID in m_lastColliders)
3708 {
3709 if (!thisHitColliders.Contains(localID))
3710 {
3711 endedColliders.Add(localID);
3712 }
3713 }
3714 //add the items that started colliding this time to the last colliders list.
3715 foreach (uint localID in startedColliders)
3716 {
3717 m_lastColliders.Add(localID);
3718 }
3719 // remove things that ended colliding from the last colliders list
3720 foreach (uint localID in endedColliders)
3721 {
3722 m_lastColliders.Remove(localID);
3723 }
3724
3725 // do event notification
3726 if (startedColliders.Count > 0)
3727 {
3728 ColliderArgs StartCollidingMessage = new ColliderArgs();
3729 List<DetectedObject> colliding = new List<DetectedObject>();
3730 foreach (uint localId in startedColliders)
3731 {
3732 if (localId == 0)
3733 continue;
3734
3735 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3736 string data = "";
3737 if (obj != null)
3738 {
3739 DetectedObject detobj = new DetectedObject();
3740 detobj.keyUUID = obj.UUID;
3741 detobj.nameStr = obj.Name;
3742 detobj.ownerUUID = obj.OwnerID;
3743 detobj.posVector = obj.AbsolutePosition;
3744 detobj.rotQuat = obj.GetWorldRotation();
3745 detobj.velVector = obj.Velocity;
3746 detobj.colliderType = 0;
3747 detobj.groupUUID = obj.GroupID;
3748 colliding.Add(detobj);
3749 }
3750 }
3751
3752 if (colliding.Count > 0)
3753 {
3754 StartCollidingMessage.Colliders = colliding;
3755
3756 foreach (SceneObjectGroup att in Attachments)
3757 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3758 }
3759 }
3760
3761 if (endedColliders.Count > 0)
3762 {
3763 ColliderArgs EndCollidingMessage = new ColliderArgs();
3764 List<DetectedObject> colliding = new List<DetectedObject>();
3765 foreach (uint localId in endedColliders)
3766 {
3767 if (localId == 0)
3768 continue;
3769
3770 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3771 string data = "";
3772 if (obj != null)
3773 {
3774 DetectedObject detobj = new DetectedObject();
3775 detobj.keyUUID = obj.UUID;
3776 detobj.nameStr = obj.Name;
3777 detobj.ownerUUID = obj.OwnerID;
3778 detobj.posVector = obj.AbsolutePosition;
3779 detobj.rotQuat = obj.GetWorldRotation();
3780 detobj.velVector = obj.Velocity;
3781 detobj.colliderType = 0;
3782 detobj.groupUUID = obj.GroupID;
3783 colliding.Add(detobj);
3784 }
3785 }
3786
3787 if (colliding.Count > 0)
3788 {
3789 EndCollidingMessage.Colliders = colliding;
3790
3791 foreach (SceneObjectGroup att in Attachments)
3792 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
3793 }
3794 }
3795
3796 if (thisHitColliders.Count > 0)
3797 {
3798 ColliderArgs CollidingMessage = new ColliderArgs();
3799 List<DetectedObject> colliding = new List<DetectedObject>();
3800 foreach (uint localId in thisHitColliders)
3801 {
3802 if (localId == 0)
3803 continue;
3804
3805 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3806 string data = "";
3807 if (obj != null)
3808 {
3809 DetectedObject detobj = new DetectedObject();
3810 detobj.keyUUID = obj.UUID;
3811 detobj.nameStr = obj.Name;
3812 detobj.ownerUUID = obj.OwnerID;
3813 detobj.posVector = obj.AbsolutePosition;
3814 detobj.rotQuat = obj.GetWorldRotation();
3815 detobj.velVector = obj.Velocity;
3816 detobj.colliderType = 0;
3817 detobj.groupUUID = obj.GroupID;
3818 colliding.Add(detobj);
3819 }
3820 }
3821
3822 if (colliding.Count > 0)
3823 {
3824 CollidingMessage.Colliders = colliding;
3825
3826 lock (m_attachments)
3827 {
3828 foreach (SceneObjectGroup att in m_attachments)
3829 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
3830 }
3831 }
3832 }
3833
3298 if (m_invulnerable) 3834 if (m_invulnerable)
3299 return; 3835 return;
3300 3836
@@ -3720,6 +4256,39 @@ namespace OpenSim.Region.Framework.Scenes
3720 return; 4256 return;
3721 } 4257 }
3722 4258
4259 XmlDocument doc = new XmlDocument();
4260 string stateData = String.Empty;
4261
4262 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
4263 if (attServ != null)
4264 {
4265 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
4266 stateData = attServ.Get(ControllingClient.AgentId.ToString());
4267 if (stateData != String.Empty)
4268 {
4269 try
4270 {
4271 doc.LoadXml(stateData);
4272 }
4273 catch { }
4274 }
4275 }
4276
4277 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
4278
4279 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
4280 if (nodes.Count > 0)
4281 {
4282 foreach (XmlNode n in nodes)
4283 {
4284 XmlElement elem = (XmlElement)n;
4285 string itemID = elem.GetAttribute("ItemID");
4286 string xml = elem.InnerXml;
4287
4288 itemData[new UUID(itemID)] = xml;
4289 }
4290 }
4291
3723 List<AvatarAttachment> attachments = m_appearance.GetAttachments(); 4292 List<AvatarAttachment> attachments = m_appearance.GetAttachments();
3724 foreach (AvatarAttachment attach in attachments) 4293 foreach (AvatarAttachment attach in attachments)
3725 { 4294 {
@@ -3740,7 +4309,30 @@ namespace OpenSim.Region.Framework.Scenes
3740 4309
3741 try 4310 try
3742 { 4311 {
3743 m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); 4312 string xmlData;
4313 XmlDocument d = new XmlDocument();
4314 UUID asset;
4315 if (itemData.TryGetValue(itemID, out xmlData))
4316 {
4317 d.LoadXml(xmlData);
4318 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
4319
4320 // Rez from inventory
4321 asset
4322 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
4323
4324 }
4325 else
4326 {
4327 // Rez from inventory (with a null doc to let
4328 // CHANGED_OWNER happen)
4329 asset
4330 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
4331 }
4332
4333 m_log.InfoFormat(
4334 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2}",
4335 p, itemID, asset);
3744 } 4336 }
3745 catch (Exception e) 4337 catch (Exception e)
3746 { 4338 {
@@ -3773,6 +4365,15 @@ namespace OpenSim.Region.Framework.Scenes
3773 m_reprioritization_called = false; 4365 m_reprioritization_called = false;
3774 } 4366 }
3775 } 4367 }
4368
4369 private Vector3 Quat2Euler(Quaternion rot){
4370 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4371 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4372 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4373 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4374 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4375 return(new Vector3(x,y,z));
4376 }
3776 4377
3777 public void SaveChangedAttachments() 4378 public void SaveChangedAttachments()
3778 { 4379 {
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 605521a..b2b3ad9 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -102,7 +102,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
102 sceneObject.AddPart(part); 102 sceneObject.AddPart(part);
103 part.LinkNum = linkNum; 103 part.LinkNum = linkNum;
104 part.TrimPermissions(); 104 part.TrimPermissions();
105 part.StoreUndoState(); 105 part.StoreUndoState(UndoType.STATE_ALL);
106 reader.Close(); 106 reader.Close();
107 sr.Close(); 107 sr.Close();
108 } 108 }
@@ -220,7 +220,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
220 if (originalLinkNum != 0) 220 if (originalLinkNum != 0)
221 part.LinkNum = originalLinkNum; 221 part.LinkNum = originalLinkNum;
222 222
223 part.StoreUndoState(); 223 part.StoreUndoState(UndoType.STATE_ALL);
224 reader.Close(); 224 reader.Close();
225 sr.Close(); 225 sr.Close();
226 } 226 }
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