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.cs7
-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.cs267
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs511
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs50
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs224
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs700
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs294
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs754
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs1070
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneViewer.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs16
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs168
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
19 files changed, 3169 insertions, 1208 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 8feb022..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
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index fd62535..4ce7a6c 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;
@@ -766,6 +770,26 @@ namespace OpenSim.Region.Framework.Scenes
766 } 770 }
767 } 771 }
768 } 772 }
773 public void TriggerTerrainUpdate()
774 {
775 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
776 if (handlerTerrainUpdate != null)
777 {
778 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
779 {
780 try
781 {
782 d();
783 }
784 catch (Exception e)
785 {
786 m_log.ErrorFormat(
787 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
788 e.Message, e.StackTrace);
789 }
790 }
791 }
792 }
769 793
770 public void TriggerTerrainTick() 794 public void TriggerTerrainTick()
771 { 795 {
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 73dd531..0748954 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;
@@ -328,6 +310,7 @@ namespace OpenSim.Region.Framework.Scenes
328 { 310 {
329 if (UUID.Zero == transactionID) 311 if (UUID.Zero == transactionID)
330 { 312 {
313 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
331 item.Name = itemUpd.Name; 314 item.Name = itemUpd.Name;
332 item.Description = itemUpd.Description; 315 item.Description = itemUpd.Description;
333 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions)) 316 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
@@ -700,6 +683,8 @@ namespace OpenSim.Region.Framework.Scenes
700 return; 683 return;
701 } 684 }
702 685
686 if (newName == null) newName = item.Name;
687
703 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 688 AssetBase asset = AssetService.Get(item.AssetID.ToString());
704 689
705 if (asset != null) 690 if (asset != null)
@@ -753,6 +738,24 @@ namespace OpenSim.Region.Framework.Scenes
753 } 738 }
754 739
755 /// <summary> 740 /// <summary>
741 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
742 /// </summary>
743 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
744 {
745 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
746 foreach (InventoryItemBase b in items)
747 {
748 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
749 InventoryItemBase n = InventoryService.GetItem(b);
750 n.Folder = destfolder;
751 moveitems.Add(n);
752 remoteClient.SendInventoryItemCreateUpdate(n, 0);
753 }
754
755 MoveInventoryItem(remoteClient, moveitems);
756 }
757
758 /// <summary>
756 /// Move an item within the agent's inventory. 759 /// Move an item within the agent's inventory.
757 /// </summary> 760 /// </summary>
758 /// <param name="remoteClient"></param> 761 /// <param name="remoteClient"></param>
@@ -985,8 +988,12 @@ namespace OpenSim.Region.Framework.Scenes
985 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 988 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
986 { 989 {
987 SceneObjectPart part = GetSceneObjectPart(localID); 990 SceneObjectPart part = GetSceneObjectPart(localID);
988 SceneObjectGroup group = part.ParentGroup; 991 SceneObjectGroup group = null;
989 if (group != null) 992 if (part != null)
993 {
994 group = part.ParentGroup;
995 }
996 if (part != null && group != null)
990 { 997 {
991 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) 998 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
992 return; 999 return;
@@ -1222,6 +1229,10 @@ namespace OpenSim.Region.Framework.Scenes
1222 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1229 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1223 return; 1230 return;
1224 1231
1232 bool overrideNoMod = false;
1233 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1234 overrideNoMod = true;
1235
1225 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1236 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1226 { 1237 {
1227 // object cannot copy items to an object owned by a different owner 1238 // object cannot copy items to an object owned by a different owner
@@ -1231,7 +1242,7 @@ namespace OpenSim.Region.Framework.Scenes
1231 } 1242 }
1232 1243
1233 // must have both move and modify permission to put an item in an object 1244 // must have both move and modify permission to put an item in an object
1234 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1245 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1235 { 1246 {
1236 return; 1247 return;
1237 } 1248 }
@@ -1290,6 +1301,14 @@ namespace OpenSim.Region.Framework.Scenes
1290 1301
1291 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1302 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1292 { 1303 {
1304 SceneObjectPart destPart = GetSceneObjectPart(destID);
1305 if (destPart != null) // Move into a prim
1306 {
1307 foreach(UUID itemID in items)
1308 MoveTaskInventoryItem(destID, host, itemID);
1309 return destID; // Prim folder ID == prim ID
1310 }
1311
1293 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1312 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1294 1313
1295 UUID newFolderID = UUID.Random(); 1314 UUID newFolderID = UUID.Random();
@@ -1435,13 +1454,6 @@ namespace OpenSim.Region.Framework.Scenes
1435 { 1454 {
1436 agentTransactions.HandleTaskItemUpdateFromTransaction( 1455 agentTransactions.HandleTaskItemUpdateFromTransaction(
1437 remoteClient, part, transactionID, currentItem); 1456 remoteClient, part, transactionID, currentItem);
1438
1439 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1440 remoteClient.SendAgentAlertMessage("Notecard saved", false);
1441 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1442 remoteClient.SendAgentAlertMessage("Script saved", false);
1443 else
1444 remoteClient.SendAgentAlertMessage("Item saved", false);
1445 } 1457 }
1446 1458
1447 // Base ALWAYS has move 1459 // Base ALWAYS has move
@@ -1582,7 +1594,7 @@ namespace OpenSim.Region.Framework.Scenes
1582 return; 1594 return;
1583 1595
1584 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1596 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1585 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1597 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1586 remoteClient.AgentId); 1598 remoteClient.AgentId);
1587 AssetService.Store(asset); 1599 AssetService.Store(asset);
1588 1600
@@ -1735,23 +1747,32 @@ namespace OpenSim.Region.Framework.Scenes
1735 // build a list of eligible objects 1747 // build a list of eligible objects
1736 List<uint> deleteIDs = new List<uint>(); 1748 List<uint> deleteIDs = new List<uint>();
1737 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1749 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1738 1750 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1739 // Start with true for both, then remove the flags if objects
1740 // that we can't derez are part of the selection
1741 bool permissionToTake = true;
1742 bool permissionToTakeCopy = true;
1743 bool permissionToDelete = true;
1744 1751
1745 foreach (uint localID in localIDs) 1752 foreach (uint localID in localIDs)
1746 { 1753 {
1754 // Start with true for both, then remove the flags if objects
1755 // that we can't derez are part of the selection
1756 bool permissionToTake = true;
1757 bool permissionToTakeCopy = true;
1758 bool permissionToDelete = true;
1759
1747 // Invalid id 1760 // Invalid id
1748 SceneObjectPart part = GetSceneObjectPart(localID); 1761 SceneObjectPart part = GetSceneObjectPart(localID);
1749 if (part == null) 1762 if (part == null)
1763 {
1764 //Client still thinks the object exists, kill it
1765 deleteIDs.Add(localID);
1750 continue; 1766 continue;
1767 }
1751 1768
1752 // Already deleted by someone else 1769 // Already deleted by someone else
1753 if (part.ParentGroup == null || part.ParentGroup.IsDeleted) 1770 if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
1771 {
1772 //Client still thinks the object exists, kill it
1773 deleteIDs.Add(localID);
1754 continue; 1774 continue;
1775 }
1755 1776
1756 // Can't delete child prims 1777 // Can't delete child prims
1757 if (part != part.ParentGroup.RootPart) 1778 if (part != part.ParentGroup.RootPart)
@@ -1759,9 +1780,6 @@ namespace OpenSim.Region.Framework.Scenes
1759 1780
1760 SceneObjectGroup grp = part.ParentGroup; 1781 SceneObjectGroup grp = part.ParentGroup;
1761 1782
1762 deleteIDs.Add(localID);
1763 deleteGroups.Add(grp);
1764
1765 if (remoteClient == null) 1783 if (remoteClient == null)
1766 { 1784 {
1767 // Autoreturn has a null client. Nothing else does. So 1785 // Autoreturn has a null client. Nothing else does. So
@@ -1778,80 +1796,104 @@ namespace OpenSim.Region.Framework.Scenes
1778 } 1796 }
1779 else 1797 else
1780 { 1798 {
1781 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1799 if (action == DeRezAction.TakeCopy)
1800 {
1801 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1802 permissionToTakeCopy = false;
1803 }
1804 else
1805 {
1782 permissionToTakeCopy = false; 1806 permissionToTakeCopy = false;
1783 1807 }
1784 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1808 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1785 permissionToTake = false; 1809 permissionToTake = false;
1786 1810
1787 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1811 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1788 permissionToDelete = false; 1812 permissionToDelete = false;
1789 } 1813 }
1790 }
1791 1814
1792 // Handle god perms 1815 // Handle god perms
1793 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1816 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1794 { 1817 {
1795 permissionToTake = true; 1818 permissionToTake = true;
1796 permissionToTakeCopy = true; 1819 permissionToTakeCopy = true;
1797 permissionToDelete = true; 1820 permissionToDelete = true;
1798 } 1821 }
1799 1822
1800 // If we're re-saving, we don't even want to delete 1823 // If we're re-saving, we don't even want to delete
1801 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1824 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1802 permissionToDelete = false; 1825 permissionToDelete = false;
1803 1826
1804 // if we want to take a copy, we also don't want to delete 1827 // if we want to take a copy, we also don't want to delete
1805 // Note: after this point, the permissionToTakeCopy flag 1828 // Note: after this point, the permissionToTakeCopy flag
1806 // becomes irrelevant. It already includes the permissionToTake 1829 // becomes irrelevant. It already includes the permissionToTake
1807 // permission and after excluding no copy items here, we can 1830 // permission and after excluding no copy items here, we can
1808 // just use that. 1831 // just use that.
1809 if (action == DeRezAction.TakeCopy) 1832 if (action == DeRezAction.TakeCopy)
1810 { 1833 {
1811 // If we don't have permission, stop right here 1834 // If we don't have permission, stop right here
1812 if (!permissionToTakeCopy) 1835 if (!permissionToTakeCopy)
1813 return; 1836 return;
1814 1837
1815 permissionToTake = true; 1838 permissionToTake = true;
1816 // Don't delete 1839 // Don't delete
1817 permissionToDelete = false; 1840 permissionToDelete = false;
1818 } 1841 }
1819 1842
1820 if (action == DeRezAction.Return) 1843 if (action == DeRezAction.Return)
1821 {
1822 if (remoteClient != null)
1823 { 1844 {
1824 if (Permissions.CanReturnObjects( 1845 if (remoteClient != null)
1825 null,
1826 remoteClient.AgentId,
1827 deleteGroups))
1828 { 1846 {
1829 permissionToTake = true; 1847 if (Permissions.CanReturnObjects(
1830 permissionToDelete = true; 1848 null,
1831 1849 remoteClient.AgentId,
1832 foreach (SceneObjectGroup g in deleteGroups) 1850 deleteGroups))
1833 { 1851 {
1834 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1852 permissionToTake = true;
1853 permissionToDelete = true;
1854
1855 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1835 } 1856 }
1836 } 1857 }
1858 else // Auto return passes through here with null agent
1859 {
1860 permissionToTake = true;
1861 permissionToDelete = true;
1862 }
1837 } 1863 }
1838 else // Auto return passes through here with null agent 1864
1865 if (permissionToTake && (!permissionToDelete))
1866 takeGroups.Add(grp);
1867
1868 if (permissionToDelete)
1839 { 1869 {
1840 permissionToTake = true; 1870 if (permissionToTake)
1841 permissionToDelete = true; 1871 deleteGroups.Add(grp);
1872 deleteIDs.Add(grp.LocalId);
1842 } 1873 }
1843 } 1874 }
1844 1875
1845 if (permissionToTake) 1876 SendKillObject(deleteIDs);
1877
1878 if (deleteGroups.Count > 0)
1846 { 1879 {
1880 foreach (SceneObjectGroup g in deleteGroups)
1881 deleteIDs.Remove(g.LocalId);
1882
1847 m_asyncSceneObjectDeleter.DeleteToInventory( 1883 m_asyncSceneObjectDeleter.DeleteToInventory(
1848 action, destinationID, deleteGroups, remoteClient, 1884 action, destinationID, deleteGroups, remoteClient,
1849 permissionToDelete); 1885 true);
1886 }
1887 if (takeGroups.Count > 0)
1888 {
1889 m_asyncSceneObjectDeleter.DeleteToInventory(
1890 action, destinationID, takeGroups, remoteClient,
1891 false);
1850 } 1892 }
1851 else if (permissionToDelete) 1893 if (deleteIDs.Count > 0)
1852 { 1894 {
1853 foreach (SceneObjectGroup g in deleteGroups) 1895 foreach (SceneObjectGroup g in deleteGroups)
1854 DeleteSceneObject(g, false); 1896 DeleteSceneObject(g, true);
1855 } 1897 }
1856 } 1898 }
1857 1899
@@ -1903,21 +1945,29 @@ namespace OpenSim.Region.Framework.Scenes
1903 else // oopsies 1945 else // oopsies
1904 item.Folder = UUID.Zero; 1946 item.Folder = UUID.Zero;
1905 1947
1948 // Set up base perms properly
1949 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
1950 permsBase &= grp.RootPart.BaseMask;
1951 permsBase |= (uint)PermissionMask.Move;
1952
1953 // Make sure we don't lock it
1954 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
1955
1906 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions()) 1956 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
1907 { 1957 {
1908 item.BasePermissions = grp.RootPart.NextOwnerMask; 1958 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
1909 item.CurrentPermissions = grp.RootPart.NextOwnerMask; 1959 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
1910 item.NextPermissions = grp.RootPart.NextOwnerMask; 1960 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1911 item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask; 1961 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
1912 item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask; 1962 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
1913 } 1963 }
1914 else 1964 else
1915 { 1965 {
1916 item.BasePermissions = grp.RootPart.BaseMask; 1966 item.BasePermissions = permsBase;
1917 item.CurrentPermissions = grp.RootPart.OwnerMask; 1967 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
1918 item.NextPermissions = grp.RootPart.NextOwnerMask; 1968 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1919 item.EveryOnePermissions = grp.RootPart.EveryoneMask; 1969 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
1920 item.GroupPermissions = grp.RootPart.GroupMask; 1970 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
1921 } 1971 }
1922 item.CreationDate = Util.UnixTimeSinceEpoch(); 1972 item.CreationDate = Util.UnixTimeSinceEpoch();
1923 1973
@@ -2023,6 +2073,9 @@ namespace OpenSim.Region.Framework.Scenes
2023 2073
2024 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2074 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2025 { 2075 {
2076 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2077 return;
2078
2026 SceneObjectPart part = GetSceneObjectPart(objectID); 2079 SceneObjectPart part = GetSceneObjectPart(objectID);
2027 if (part == null) 2080 if (part == null)
2028 return; 2081 return;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index e1fedf4..48beb9c 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -49,6 +49,7 @@ namespace OpenSim.Region.Framework.Scenes
49 public delegate bool DuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition); 49 public delegate bool DuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition);
50 public delegate bool EditObjectHandler(UUID objectID, UUID editorID, Scene scene); 50 public delegate bool EditObjectHandler(UUID objectID, UUID editorID, Scene scene);
51 public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene); 51 public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene);
52 public delegate bool ViewObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene);
52 public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene); 53 public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene);
53 public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene); 54 public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene);
54 public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene); 55 public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene);
@@ -116,6 +117,7 @@ namespace OpenSim.Region.Framework.Scenes
116 public event DuplicateObjectHandler OnDuplicateObject; 117 public event DuplicateObjectHandler OnDuplicateObject;
117 public event EditObjectHandler OnEditObject; 118 public event EditObjectHandler OnEditObject;
118 public event EditObjectInventoryHandler OnEditObjectInventory; 119 public event EditObjectInventoryHandler OnEditObjectInventory;
120 public event ViewObjectInventoryHandler OnViewObjectInventory;
119 public event MoveObjectHandler OnMoveObject; 121 public event MoveObjectHandler OnMoveObject;
120 public event ObjectEntryHandler OnObjectEntry; 122 public event ObjectEntryHandler OnObjectEntry;
121 public event ReturnObjectsHandler OnReturnObjects; 123 public event ReturnObjectsHandler OnReturnObjects;
@@ -401,6 +403,21 @@ namespace OpenSim.Region.Framework.Scenes
401 return true; 403 return true;
402 } 404 }
403 405
406 public bool CanViewObjectInventory(UUID objectID, UUID editorID)
407 {
408 ViewObjectInventoryHandler handler = OnViewObjectInventory;
409 if (handler != null)
410 {
411 Delegate[] list = handler.GetInvocationList();
412 foreach (ViewObjectInventoryHandler h in list)
413 {
414 if (h(objectID, editorID, m_scene) == false)
415 return false;
416 }
417 }
418 return true;
419 }
420
404 #endregion 421 #endregion
405 422
406 #region MOVE OBJECT 423 #region MOVE OBJECT
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index f0acc38..0e3cffb 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -93,6 +93,7 @@ namespace OpenSim.Region.Framework.Scenes
93 // TODO: need to figure out how allow client agents but deny 93 // TODO: need to figure out how allow client agents but deny
94 // root agents when ACL denies access to root agent 94 // root agents when ACL denies access to root agent
95 public bool m_strictAccessControl = true; 95 public bool m_strictAccessControl = true;
96 public bool m_seeIntoBannedRegion = false;
96 public int MaxUndoCount = 5; 97 public int MaxUndoCount = 5;
97 public bool LoginsDisabled = true; 98 public bool LoginsDisabled = true;
98 public bool LoadingPrims; 99 public bool LoadingPrims;
@@ -111,6 +112,7 @@ namespace OpenSim.Region.Framework.Scenes
111 protected ModuleLoader m_moduleLoader; 112 protected ModuleLoader m_moduleLoader;
112 protected AgentCircuitManager m_authenticateHandler; 113 protected AgentCircuitManager m_authenticateHandler;
113 protected SceneCommunicationService m_sceneGridService; 114 protected SceneCommunicationService m_sceneGridService;
115 protected ISnmpModule m_snmpService = null;
114 116
115 protected ISimulationDataService m_SimulationDataService; 117 protected ISimulationDataService m_SimulationDataService;
116 protected IEstateDataService m_EstateDataService; 118 protected IEstateDataService m_EstateDataService;
@@ -167,7 +169,7 @@ namespace OpenSim.Region.Framework.Scenes
167 private int m_update_events = 1; 169 private int m_update_events = 1;
168 private int m_update_backup = 200; 170 private int m_update_backup = 200;
169 private int m_update_terrain = 50; 171 private int m_update_terrain = 50;
170// private int m_update_land = 1; 172 private int m_update_land = 10;
171 private int m_update_coarse_locations = 50; 173 private int m_update_coarse_locations = 50;
172 174
173 private int frameMS; 175 private int frameMS;
@@ -181,6 +183,7 @@ namespace OpenSim.Region.Framework.Scenes
181 private int landMS; 183 private int landMS;
182 private int lastCompletedFrame; 184 private int lastCompletedFrame;
183 185
186 public bool CombineRegions = false;
184 private bool m_physics_enabled = true; 187 private bool m_physics_enabled = true;
185 private bool m_scripts_enabled = true; 188 private bool m_scripts_enabled = true;
186 private string m_defaultScriptEngine; 189 private string m_defaultScriptEngine;
@@ -189,6 +192,8 @@ namespace OpenSim.Region.Framework.Scenes
189 private volatile bool shuttingdown; 192 private volatile bool shuttingdown;
190 193
191 private int m_lastUpdate; 194 private int m_lastUpdate;
195 private int m_lastIncoming;
196 private int m_lastOutgoing;
192 private bool m_firstHeartbeat = true; 197 private bool m_firstHeartbeat = true;
193 198
194 private object m_deleting_scene_object = new object(); 199 private object m_deleting_scene_object = new object();
@@ -240,6 +245,19 @@ namespace OpenSim.Region.Framework.Scenes
240 get { return m_sceneGridService; } 245 get { return m_sceneGridService; }
241 } 246 }
242 247
248 public ISnmpModule SnmpService
249 {
250 get
251 {
252 if (m_snmpService == null)
253 {
254 m_snmpService = RequestModuleInterface<ISnmpModule>();
255 }
256
257 return m_snmpService;
258 }
259 }
260
243 public ISimulationDataService SimulationDataService 261 public ISimulationDataService SimulationDataService
244 { 262 {
245 get 263 get
@@ -563,7 +581,10 @@ namespace OpenSim.Region.Framework.Scenes
563 m_regInfo = regInfo; 581 m_regInfo = regInfo;
564 m_regionHandle = m_regInfo.RegionHandle; 582 m_regionHandle = m_regInfo.RegionHandle;
565 m_regionName = m_regInfo.RegionName; 583 m_regionName = m_regInfo.RegionName;
584 m_datastore = m_regInfo.DataStore;
566 m_lastUpdate = Util.EnvironmentTickCount(); 585 m_lastUpdate = Util.EnvironmentTickCount();
586 m_lastIncoming = 0;
587 m_lastOutgoing = 0;
567 588
568 m_physicalPrim = physicalPrim; 589 m_physicalPrim = physicalPrim;
569 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor; 590 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor;
@@ -577,6 +598,8 @@ namespace OpenSim.Region.Framework.Scenes
577 #region Region Settings 598 #region Region Settings
578 599
579 // Load region settings 600 // Load region settings
601 m_regInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(m_regInfo.RegionID);
602
580 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID); 603 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID);
581 if (estateDataService != null) 604 if (estateDataService != null)
582 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false); 605 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -638,9 +661,10 @@ namespace OpenSim.Region.Framework.Scenes
638 //Animation states 661 //Animation states
639 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 662 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
640 // TODO: Change default to true once the feature is supported 663 // TODO: Change default to true once the feature is supported
641 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 664 m_usePreJump = startupConfig.GetBoolean("enableprejump", true);
642
643 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 665 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
666
667 m_log.DebugFormat("[SCENE]: prejump is {0}", m_usePreJump ? "ON" : "OFF");
644 if (RegionInfo.NonphysPrimMax > 0) 668 if (RegionInfo.NonphysPrimMax > 0)
645 { 669 {
646 m_maxNonphys = RegionInfo.NonphysPrimMax; 670 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -672,6 +696,7 @@ namespace OpenSim.Region.Framework.Scenes
672 m_persistAfter *= 10000000; 696 m_persistAfter *= 10000000;
673 697
674 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 698 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
699 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
675 700
676 IConfig packetConfig = m_config.Configs["PacketPool"]; 701 IConfig packetConfig = m_config.Configs["PacketPool"];
677 if (packetConfig != null) 702 if (packetConfig != null)
@@ -681,6 +706,8 @@ namespace OpenSim.Region.Framework.Scenes
681 } 706 }
682 707
683 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 708 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
709 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
710 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
684 711
685 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 712 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
686 if (m_generateMaptiles) 713 if (m_generateMaptiles)
@@ -705,9 +732,9 @@ namespace OpenSim.Region.Framework.Scenes
705 } 732 }
706 } 733 }
707 } 734 }
708 catch 735 catch (Exception e)
709 { 736 {
710 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 737 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
711 } 738 }
712 739
713 #endregion Region Config 740 #endregion Region Config
@@ -1078,7 +1105,9 @@ namespace OpenSim.Region.Framework.Scenes
1078 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1105 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1079 if (HeartbeatThread != null) 1106 if (HeartbeatThread != null)
1080 { 1107 {
1108 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1081 HeartbeatThread.Abort(); 1109 HeartbeatThread.Abort();
1110 Watchdog.RemoveThread(HeartbeatThread.ManagedThreadId);
1082 HeartbeatThread = null; 1111 HeartbeatThread = null;
1083 } 1112 }
1084 m_lastUpdate = Util.EnvironmentTickCount(); 1113 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1202,9 +1231,6 @@ namespace OpenSim.Region.Framework.Scenes
1202 { 1231 {
1203 while (!shuttingdown) 1232 while (!shuttingdown)
1204 Update(); 1233 Update();
1205
1206 m_lastUpdate = Util.EnvironmentTickCount();
1207 m_firstHeartbeat = false;
1208 } 1234 }
1209 catch (ThreadAbortException) 1235 catch (ThreadAbortException)
1210 { 1236 {
@@ -1311,12 +1337,12 @@ namespace OpenSim.Region.Framework.Scenes
1311 terrainMS = Util.EnvironmentTickCountSubtract(terMS); 1337 terrainMS = Util.EnvironmentTickCountSubtract(terMS);
1312 } 1338 }
1313 1339
1314 //if (Frame % m_update_land == 0) 1340 // if (Frame % m_update_land == 0)
1315 //{ 1341 // {
1316 // int ldMS = Util.EnvironmentTickCount(); 1342 // int ldMS = Util.EnvironmentTickCount();
1317 // UpdateLand(); 1343 // UpdateLand();
1318 // landMS = Util.EnvironmentTickCountSubtract(ldMS); 1344 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1319 //} 1345 // }
1320 1346
1321 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); 1347 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
1322 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; 1348 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
@@ -1382,12 +1408,16 @@ namespace OpenSim.Region.Framework.Scenes
1382 maintc = Util.EnvironmentTickCountSubtract(maintc); 1408 maintc = Util.EnvironmentTickCountSubtract(maintc);
1383 maintc = (int)(m_timespan * 1000) - maintc; 1409 maintc = (int)(m_timespan * 1000) - maintc;
1384 1410
1411
1412 m_lastUpdate = Util.EnvironmentTickCount();
1413 m_firstHeartbeat = false;
1414
1385 if (maintc > 0) 1415 if (maintc > 0)
1386 Thread.Sleep(maintc); 1416 Thread.Sleep(maintc);
1387 1417
1388 // Tell the watchdog that this thread is still alive 1418 // Tell the watchdog that this thread is still alive
1389 Watchdog.UpdateThread(); 1419 Watchdog.UpdateThread();
1390 } 1420 }
1391 1421
1392 public void AddGroupTarget(SceneObjectGroup grp) 1422 public void AddGroupTarget(SceneObjectGroup grp)
1393 { 1423 {
@@ -1403,9 +1433,9 @@ namespace OpenSim.Region.Framework.Scenes
1403 1433
1404 private void CheckAtTargets() 1434 private void CheckAtTargets()
1405 { 1435 {
1406 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1436 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1407 lock (m_groupsWithTargets) 1437 lock (m_groupsWithTargets)
1408 objs = m_groupsWithTargets.Values; 1438 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1409 1439
1410 foreach (SceneObjectGroup entry in objs) 1440 foreach (SceneObjectGroup entry in objs)
1411 entry.checkAtTargets(); 1441 entry.checkAtTargets();
@@ -1728,14 +1758,24 @@ namespace OpenSim.Region.Framework.Scenes
1728 /// <returns></returns> 1758 /// <returns></returns>
1729 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1759 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1730 { 1760 {
1761
1762 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1763 Vector3 wpos = Vector3.Zero;
1764 // Check for water surface intersection from above
1765 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1766 {
1767 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1768 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1769 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1770 wpos.Z = wheight;
1771 }
1772
1731 Vector3 pos = Vector3.Zero; 1773 Vector3 pos = Vector3.Zero;
1732 if (RayEndIsIntersection == (byte)1) 1774 if (RayEndIsIntersection == (byte)1)
1733 { 1775 {
1734 pos = RayEnd; 1776 pos = RayEnd;
1735 return pos;
1736 } 1777 }
1737 1778 else if (RayTargetID != UUID.Zero)
1738 if (RayTargetID != UUID.Zero)
1739 { 1779 {
1740 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1780 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1741 1781
@@ -1757,7 +1797,7 @@ namespace OpenSim.Region.Framework.Scenes
1757 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1797 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1758 1798
1759 // Un-comment out the following line to Get Raytrace results printed to the console. 1799 // Un-comment out the following line to Get Raytrace results printed to the console.
1760 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1800 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1761 float ScaleOffset = 0.5f; 1801 float ScaleOffset = 0.5f;
1762 1802
1763 // If we hit something 1803 // If we hit something
@@ -1780,13 +1820,10 @@ namespace OpenSim.Region.Framework.Scenes
1780 //pos.Z -= 0.25F; 1820 //pos.Z -= 0.25F;
1781 1821
1782 } 1822 }
1783
1784 return pos;
1785 } 1823 }
1786 else 1824 else
1787 { 1825 {
1788 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1826 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1789
1790 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1827 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1791 1828
1792 // Un-comment the following line to print the raytrace results to the console. 1829 // Un-comment the following line to print the raytrace results to the console.
@@ -1795,13 +1832,12 @@ namespace OpenSim.Region.Framework.Scenes
1795 if (ei.HitTF) 1832 if (ei.HitTF)
1796 { 1833 {
1797 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1834 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1798 } else 1835 }
1836 else
1799 { 1837 {
1800 // fall back to our stupid functionality 1838 // fall back to our stupid functionality
1801 pos = RayEnd; 1839 pos = RayEnd;
1802 } 1840 }
1803
1804 return pos;
1805 } 1841 }
1806 } 1842 }
1807 else 1843 else
@@ -1812,8 +1848,12 @@ namespace OpenSim.Region.Framework.Scenes
1812 //increase height so its above the ground. 1848 //increase height so its above the ground.
1813 //should be getting the normal of the ground at the rez point and using that? 1849 //should be getting the normal of the ground at the rez point and using that?
1814 pos.Z += scale.Z / 2f; 1850 pos.Z += scale.Z / 2f;
1815 return pos; 1851// return pos;
1816 } 1852 }
1853
1854 // check against posible water intercept
1855 if (wpos.Z > pos.Z) pos = wpos;
1856 return pos;
1817 } 1857 }
1818 1858
1819 1859
@@ -1893,7 +1933,10 @@ namespace OpenSim.Region.Framework.Scenes
1893 public bool AddRestoredSceneObject( 1933 public bool AddRestoredSceneObject(
1894 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1934 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1895 { 1935 {
1896 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1936 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1937 if (result)
1938 sceneObject.IsDeleted = false;
1939 return result;
1897 } 1940 }
1898 1941
1899 /// <summary> 1942 /// <summary>
@@ -1982,6 +2025,15 @@ namespace OpenSim.Region.Framework.Scenes
1982 /// </summary> 2025 /// </summary>
1983 public void DeleteAllSceneObjects() 2026 public void DeleteAllSceneObjects()
1984 { 2027 {
2028 DeleteAllSceneObjects(false);
2029 }
2030
2031 /// <summary>
2032 /// Delete every object from the scene. This does not include attachments worn by avatars.
2033 /// </summary>
2034 public void DeleteAllSceneObjects(bool exceptNoCopy)
2035 {
2036 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
1985 lock (Entities) 2037 lock (Entities)
1986 { 2038 {
1987 EntityBase[] entities = Entities.GetEntities(); 2039 EntityBase[] entities = Entities.GetEntities();
@@ -1990,11 +2042,24 @@ namespace OpenSim.Region.Framework.Scenes
1990 if (e is SceneObjectGroup) 2042 if (e is SceneObjectGroup)
1991 { 2043 {
1992 SceneObjectGroup sog = (SceneObjectGroup)e; 2044 SceneObjectGroup sog = (SceneObjectGroup)e;
1993 if (!sog.IsAttachment) 2045 if (sog != null && !sog.IsAttachment)
1994 DeleteSceneObject((SceneObjectGroup)e, false); 2046 {
2047 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2048 {
2049 DeleteSceneObject((SceneObjectGroup)e, false);
2050 }
2051 else
2052 {
2053 toReturn.Add((SceneObjectGroup)e);
2054 }
2055 }
1995 } 2056 }
1996 } 2057 }
1997 } 2058 }
2059 if (toReturn.Count > 0)
2060 {
2061 returnObjects(toReturn.ToArray(), UUID.Zero);
2062 }
1998 } 2063 }
1999 2064
2000 /// <summary> 2065 /// <summary>
@@ -2043,6 +2108,8 @@ namespace OpenSim.Region.Framework.Scenes
2043 } 2108 }
2044 2109
2045 group.DeleteGroupFromScene(silent); 2110 group.DeleteGroupFromScene(silent);
2111 if (!silent)
2112 SendKillObject(new List<uint>() { group.LocalId });
2046 2113
2047// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2114// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2048 } 2115 }
@@ -2373,10 +2440,17 @@ namespace OpenSim.Region.Framework.Scenes
2373 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2440 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2374 public bool AddSceneObject(SceneObjectGroup sceneObject) 2441 public bool AddSceneObject(SceneObjectGroup sceneObject)
2375 { 2442 {
2443 if (sceneObject.OwnerID == UUID.Zero)
2444 {
2445 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2446 return false;
2447 }
2448
2376 // If the user is banned, we won't let any of their objects 2449 // If the user is banned, we won't let any of their objects
2377 // enter. Period. 2450 // enter. Period.
2378 // 2451 //
2379 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2452 int flags = GetUserFlags(sceneObject.OwnerID);
2453 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2380 { 2454 {
2381 m_log.Info("[INTERREGION]: Denied prim crossing for " + 2455 m_log.Info("[INTERREGION]: Denied prim crossing for " +
2382 "banned avatar"); 2456 "banned avatar");
@@ -2420,15 +2494,28 @@ namespace OpenSim.Region.Framework.Scenes
2420 2494
2421 if (AttachmentsModule != null) 2495 if (AttachmentsModule != null)
2422 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); 2496 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
2497
2498 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was found, attaching", sceneObject.UUID);
2423 } 2499 }
2424 else 2500 else
2425 { 2501 {
2502 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2426 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2503 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2427 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2504 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2428 } 2505 }
2506 if (sceneObject.OwnerID == UUID.Zero)
2507 {
2508 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2509 return false;
2510 }
2429 } 2511 }
2430 else 2512 else
2431 { 2513 {
2514 if (sceneObject.OwnerID == UUID.Zero)
2515 {
2516 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2517 return false;
2518 }
2432 AddRestoredSceneObject(sceneObject, true, false); 2519 AddRestoredSceneObject(sceneObject, true, false);
2433 2520
2434 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2521 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2467,6 +2554,24 @@ namespace OpenSim.Region.Framework.Scenes
2467 return 2; // StateSource.PrimCrossing 2554 return 2; // StateSource.PrimCrossing
2468 } 2555 }
2469 2556
2557 public int GetUserFlags(UUID user)
2558 {
2559 //Unfortunately the SP approach means that the value is cached until region is restarted
2560 /*
2561 ScenePresence sp;
2562 if (TryGetScenePresence(user, out sp))
2563 {
2564 return sp.UserFlags;
2565 }
2566 else
2567 {
2568 */
2569 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2570 if (uac == null)
2571 return 0;
2572 return uac.UserFlags;
2573 //}
2574 }
2470 #endregion 2575 #endregion
2471 2576
2472 #region Add/Remove Avatar Methods 2577 #region Add/Remove Avatar Methods
@@ -2487,6 +2592,7 @@ namespace OpenSim.Region.Framework.Scenes
2487 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2592 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2488 2593
2489 CheckHeartbeat(); 2594 CheckHeartbeat();
2595 ScenePresence presence;
2490 2596
2491 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here 2597 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here
2492 { 2598 {
@@ -2510,12 +2616,19 @@ namespace OpenSim.Region.Framework.Scenes
2510 } 2616 }
2511 } 2617 }
2512 2618
2513 if (GetScenePresence(client.AgentId) != null) 2619 if (TryGetScenePresence(client.AgentId, out presence))
2514 { 2620 {
2515 m_LastLogin = Util.EnvironmentTickCount(); 2621 m_LastLogin = Util.EnvironmentTickCount();
2516 EventManager.TriggerOnNewClient(client); 2622 EventManager.TriggerOnNewClient(client);
2517 if (vialogin) 2623 if (vialogin)
2624 {
2518 EventManager.TriggerOnClientLogin(client); 2625 EventManager.TriggerOnClientLogin(client);
2626
2627 // Send initial parcel data
2628 Vector3 pos = presence.AbsolutePosition;
2629 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2630 land.SendLandUpdateToClient(presence.ControllingClient);
2631 }
2519 } 2632 }
2520 } 2633 }
2521 2634
@@ -2566,19 +2679,12 @@ namespace OpenSim.Region.Framework.Scenes
2566 // and the scene presence and the client, if they exist 2679 // and the scene presence and the client, if they exist
2567 try 2680 try
2568 { 2681 {
2569 // We need to wait for the client to make UDP contact first. 2682 ScenePresence sp = GetScenePresence(agentID);
2570 // It's the UDP contact that creates the scene presence 2683 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2571 ScenePresence sp = WaitGetScenePresence(agentID); 2684
2572 if (sp != null) 2685 if (sp != null)
2573 {
2574 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2575
2576 sp.ControllingClient.Close(); 2686 sp.ControllingClient.Close();
2577 } 2687
2578 else
2579 {
2580 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2581 }
2582 // BANG! SLASH! 2688 // BANG! SLASH!
2583 m_authenticateHandler.RemoveCircuit(agentID); 2689 m_authenticateHandler.RemoveCircuit(agentID);
2584 2690
@@ -2678,6 +2784,7 @@ namespace OpenSim.Region.Framework.Scenes
2678 client.OnFetchInventory += HandleFetchInventory; 2784 client.OnFetchInventory += HandleFetchInventory;
2679 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2785 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2680 client.OnCopyInventoryItem += CopyInventoryItem; 2786 client.OnCopyInventoryItem += CopyInventoryItem;
2787 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2681 client.OnMoveInventoryItem += MoveInventoryItem; 2788 client.OnMoveInventoryItem += MoveInventoryItem;
2682 client.OnRemoveInventoryItem += RemoveInventoryItem; 2789 client.OnRemoveInventoryItem += RemoveInventoryItem;
2683 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2790 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2856,15 +2963,16 @@ namespace OpenSim.Region.Framework.Scenes
2856 /// </summary> 2963 /// </summary>
2857 /// <param name="agentId">The avatar's Unique ID</param> 2964 /// <param name="agentId">The avatar's Unique ID</param>
2858 /// <param name="client">The IClientAPI for the client</param> 2965 /// <param name="client">The IClientAPI for the client</param>
2859 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 2966 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2860 { 2967 {
2861 if (m_teleportModule != null) 2968 if (m_teleportModule != null)
2862 m_teleportModule.TeleportHome(agentId, client); 2969 return m_teleportModule.TeleportHome(agentId, client);
2863 else 2970 else
2864 { 2971 {
2865 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 2972 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2866 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 2973 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2867 } 2974 }
2975 return false;
2868 } 2976 }
2869 2977
2870 /// <summary> 2978 /// <summary>
@@ -2963,6 +3071,16 @@ namespace OpenSim.Region.Framework.Scenes
2963 /// <param name="flags"></param> 3071 /// <param name="flags"></param>
2964 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3072 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
2965 { 3073 {
3074 //Add half the avatar's height so that the user doesn't fall through prims
3075 ScenePresence presence;
3076 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3077 {
3078 if (presence.Appearance != null)
3079 {
3080 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3081 }
3082 }
3083
2966 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3084 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
2967 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3085 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
2968 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3086 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3039,7 +3157,9 @@ namespace OpenSim.Region.Framework.Scenes
3039 regions.Remove(RegionInfo.RegionHandle); 3157 regions.Remove(RegionInfo.RegionHandle);
3040 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3158 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3041 } 3159 }
3160 m_log.Debug("[Scene] Beginning ClientClosed");
3042 m_eventManager.TriggerClientClosed(agentID, this); 3161 m_eventManager.TriggerClientClosed(agentID, this);
3162 m_log.Debug("[Scene] Finished ClientClosed");
3043 } 3163 }
3044 catch (NullReferenceException) 3164 catch (NullReferenceException)
3045 { 3165 {
@@ -3047,7 +3167,12 @@ namespace OpenSim.Region.Framework.Scenes
3047 // Avatar is already disposed :/ 3167 // Avatar is already disposed :/
3048 } 3168 }
3049 3169
3170 m_log.Debug("[Scene] Beginning OnRemovePresence");
3050 m_eventManager.TriggerOnRemovePresence(agentID); 3171 m_eventManager.TriggerOnRemovePresence(agentID);
3172 m_log.Debug("[Scene] Finished OnRemovePresence");
3173
3174 if (avatar != null && (!avatar.IsChildAgent))
3175 avatar.SaveChangedAttachments();
3051 3176
3052 if (avatar != null && (!avatar.IsChildAgent)) 3177 if (avatar != null && (!avatar.IsChildAgent))
3053 avatar.SaveChangedAttachments(); 3178 avatar.SaveChangedAttachments();
@@ -3056,7 +3181,7 @@ namespace OpenSim.Region.Framework.Scenes
3056 delegate(IClientAPI client) 3181 delegate(IClientAPI client)
3057 { 3182 {
3058 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3183 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3059 try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); } 3184 try { client.SendKillObject(avatar.RegionHandle, new List<uint>() { avatar.LocalId}); }
3060 catch (NullReferenceException) { } 3185 catch (NullReferenceException) { }
3061 }); 3186 });
3062 3187
@@ -3067,8 +3192,11 @@ namespace OpenSim.Region.Framework.Scenes
3067 } 3192 }
3068 3193
3069 // Remove the avatar from the scene 3194 // Remove the avatar from the scene
3195 m_log.Debug("[Scene] Begin RemoveScenePresence");
3070 m_sceneGraph.RemoveScenePresence(agentID); 3196 m_sceneGraph.RemoveScenePresence(agentID);
3197 m_log.Debug("[Scene] Finished RemoveScenePresence. Removing the client manager");
3071 m_clientManager.Remove(agentID); 3198 m_clientManager.Remove(agentID);
3199 m_log.Debug("[Scene] Removed the client manager. Firing avatar.close");
3072 3200
3073 try 3201 try
3074 { 3202 {
@@ -3082,9 +3210,10 @@ namespace OpenSim.Region.Framework.Scenes
3082 { 3210 {
3083 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString()); 3211 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString());
3084 } 3212 }
3085 3213 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3086 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3214 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3087 CleanDroppedAttachments(); 3215 CleanDroppedAttachments();
3216 m_log.Debug("[Scene] The avatar has left the building");
3088 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3217 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3089 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3218 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3090 } 3219 }
@@ -3115,18 +3244,24 @@ namespace OpenSim.Region.Framework.Scenes
3115 3244
3116 #region Entities 3245 #region Entities
3117 3246
3118 public void SendKillObject(uint localID) 3247 public void SendKillObject(List<uint> localIDs)
3119 { 3248 {
3120 SceneObjectPart part = GetSceneObjectPart(localID); 3249 List<uint> deleteIDs = new List<uint>();
3121 if (part != null) // It is a prim 3250
3251 foreach (uint localID in localIDs)
3122 { 3252 {
3123 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid 3253 SceneObjectPart part = GetSceneObjectPart(localID);
3254 if (part != null) // It is a prim
3124 { 3255 {
3125 if (part.ParentGroup.RootPart != part) // Child part 3256 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid
3126 return; 3257 {
3258 if (part.ParentGroup.RootPart != part) // Child part
3259 continue;
3260 }
3127 } 3261 }
3262 deleteIDs.Add(localID);
3128 } 3263 }
3129 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); }); 3264 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); });
3130 } 3265 }
3131 3266
3132 #endregion 3267 #endregion
@@ -3144,7 +3279,6 @@ namespace OpenSim.Region.Framework.Scenes
3144 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; 3279 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
3145 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; 3280 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
3146 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; 3281 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
3147 m_sceneGridService.KiPrimitive += SendKillObject;
3148 m_sceneGridService.OnGetLandData += GetLandData; 3282 m_sceneGridService.OnGetLandData += GetLandData;
3149 } 3283 }
3150 3284
@@ -3153,7 +3287,6 @@ namespace OpenSim.Region.Framework.Scenes
3153 /// </summary> 3287 /// </summary>
3154 public void UnRegisterRegionWithComms() 3288 public void UnRegisterRegionWithComms()
3155 { 3289 {
3156 m_sceneGridService.KiPrimitive -= SendKillObject;
3157 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; 3290 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid;
3158 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; 3291 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar;
3159 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; 3292 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;
@@ -3233,13 +3366,16 @@ namespace OpenSim.Region.Framework.Scenes
3233 sp = null; 3366 sp = null;
3234 } 3367 }
3235 3368
3236 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3237 3369
3238 //On login test land permisions 3370 //On login test land permisions
3239 if (vialogin) 3371 if (vialogin)
3240 { 3372 {
3241 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3373 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3374 if (cache != null)
3375 cache.Remove(agent.firstname + " " + agent.lastname);
3376 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3242 { 3377 {
3378 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3243 return false; 3379 return false;
3244 } 3380 }
3245 } 3381 }
@@ -3262,8 +3398,13 @@ namespace OpenSim.Region.Framework.Scenes
3262 3398
3263 try 3399 try
3264 { 3400 {
3265 if (!AuthorizeUser(agent, out reason)) 3401 // Always check estate if this is a login. Always
3266 return false; 3402 // check if banned regions are to be blacked out.
3403 if (vialogin || (!m_seeIntoBannedRegion))
3404 {
3405 if (!AuthorizeUser(agent.AgentID, out reason))
3406 return false;
3407 }
3267 } 3408 }
3268 catch (Exception e) 3409 catch (Exception e)
3269 { 3410 {
@@ -3366,6 +3507,8 @@ namespace OpenSim.Region.Framework.Scenes
3366 } 3507 }
3367 } 3508 }
3368 // Honor parcel landing type and position. 3509 // Honor parcel landing type and position.
3510 /*
3511 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3369 if (land != null) 3512 if (land != null)
3370 { 3513 {
3371 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3514 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3373,26 +3516,34 @@ namespace OpenSim.Region.Framework.Scenes
3373 agent.startpos = land.LandData.UserLocation; 3516 agent.startpos = land.LandData.UserLocation;
3374 } 3517 }
3375 } 3518 }
3519 */// This is now handled properly in ScenePresence.MakeRootAgent
3376 } 3520 }
3377 3521
3378 return true; 3522 return true;
3379 } 3523 }
3380 3524
3381 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3525 private bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3382 { 3526 {
3383 3527 reason = String.Empty;
3384 bool banned = land.IsBannedFromLand(agent.AgentID); 3528 if (Permissions.IsGod(agentID))
3385 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3529 return true;
3530
3531 ILandObject land = LandChannel.GetLandObject(posX, posY);
3532 if (land == null)
3533 return false;
3534
3535 bool banned = land.IsBannedFromLand(agentID);
3536 bool restricted = land.IsRestrictedFromLand(agentID);
3386 3537
3387 if (banned || restricted) 3538 if (banned || restricted)
3388 { 3539 {
3389 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3540 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3390 if (nearestParcel != null) 3541 if (nearestParcel != null)
3391 { 3542 {
3392 //Move agent to nearest allowed 3543 //Move agent to nearest allowed
3393 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3544 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3394 agent.startpos.X = newPosition.X; 3545 posX = newPosition.X;
3395 agent.startpos.Y = newPosition.Y; 3546 posY = newPosition.Y;
3396 } 3547 }
3397 else 3548 else
3398 { 3549 {
@@ -3448,19 +3599,19 @@ namespace OpenSim.Region.Framework.Scenes
3448 /// <param name="reason">outputs the reason to this string</param> 3599 /// <param name="reason">outputs the reason to this string</param>
3449 /// <returns>True if the region accepts this agent. False if it does not. False will 3600 /// <returns>True if the region accepts this agent. False if it does not. False will
3450 /// also return a reason.</returns> 3601 /// also return a reason.</returns>
3451 protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) 3602 protected virtual bool AuthorizeUser(UUID agentID, out string reason)
3452 { 3603 {
3453 reason = String.Empty; 3604 reason = String.Empty;
3454 3605
3455 if (!m_strictAccessControl) return true; 3606 if (!m_strictAccessControl) return true;
3456 if (Permissions.IsGod(agent.AgentID)) return true; 3607 if (Permissions.IsGod(agentID)) return true;
3457 3608
3458 if (AuthorizationService != null) 3609 if (AuthorizationService != null)
3459 { 3610 {
3460 if (!AuthorizationService.IsAuthorizedForRegion(agent.AgentID.ToString(), RegionInfo.RegionID.ToString(),out reason)) 3611 if (!AuthorizationService.IsAuthorizedForRegion(agentID.ToString(), RegionInfo.RegionID.ToString(),out reason))
3461 { 3612 {
3462 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3613 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the user does not have access to the region",
3463 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3614 agentID, RegionInfo.RegionName);
3464 //reason = String.Format("You are not currently on the access list for {0}",RegionInfo.RegionName); 3615 //reason = String.Format("You are not currently on the access list for {0}",RegionInfo.RegionName);
3465 return false; 3616 return false;
3466 } 3617 }
@@ -3468,10 +3619,26 @@ namespace OpenSim.Region.Framework.Scenes
3468 3619
3469 if (m_regInfo.EstateSettings != null) 3620 if (m_regInfo.EstateSettings != null)
3470 { 3621 {
3471 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3622 int flags = GetUserFlags(agentID);
3623 if (m_regInfo.EstateSettings.IsBanned(agentID, flags))
3472 { 3624 {
3473 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3625 //Add some more info to help users
3474 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3626 if (!m_regInfo.EstateSettings.IsBanned(agentID, 32))
3627 {
3628 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the region requires age verification",
3629 agentID, RegionInfo.RegionName);
3630 reason = String.Format("Denied access to region {0}: Region requires age verification", RegionInfo.RegionName);
3631 return false;
3632 }
3633 if (!m_regInfo.EstateSettings.IsBanned(agentID, 4))
3634 {
3635 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} {1} because the region requires payment info on file",
3636 agentID, RegionInfo.RegionName);
3637 reason = String.Format("Denied access to region {0}: Region requires payment info on file", RegionInfo.RegionName);
3638 return false;
3639 }
3640 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {3} because the user is on the banlist",
3641 agentID, RegionInfo.RegionName);
3475 reason = String.Format("Denied access to region {0}: You have been banned from that region.", 3642 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
3476 RegionInfo.RegionName); 3643 RegionInfo.RegionName);
3477 return false; 3644 return false;
@@ -3488,7 +3655,7 @@ namespace OpenSim.Region.Framework.Scenes
3488 if (groupsModule != null) 3655 if (groupsModule != null)
3489 { 3656 {
3490 GroupMembershipData[] GroupMembership = 3657 GroupMembershipData[] GroupMembership =
3491 groupsModule.GetMembershipData(agent.AgentID); 3658 groupsModule.GetMembershipData(agentID);
3492 3659
3493 if (GroupMembership != null) 3660 if (GroupMembership != null)
3494 { 3661 {
@@ -3517,44 +3684,16 @@ namespace OpenSim.Region.Framework.Scenes
3517 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); 3684 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
3518 3685
3519 if (!m_regInfo.EstateSettings.PublicAccess && 3686 if (!m_regInfo.EstateSettings.PublicAccess &&
3520 !m_regInfo.EstateSettings.HasAccess(agent.AgentID) && 3687 !m_regInfo.EstateSettings.HasAccess(agentID) &&
3521 !groupAccess) 3688 !groupAccess)
3522 { 3689 {
3523 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 3690 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the user does not have access to the estate",
3524 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3691 agentID, RegionInfo.RegionName);
3525 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", 3692 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3526 RegionInfo.RegionName); 3693 RegionInfo.RegionName);
3527 return false; 3694 return false;
3528 } 3695 }
3529 3696
3530 // TODO: estate/region settings are not properly hooked up
3531 // to ILandObject.isRestrictedFromLand()
3532 // if (null != LandChannel)
3533 // {
3534 // // region seems to have local Id of 1
3535 // ILandObject land = LandChannel.GetLandObject(1);
3536 // if (null != land)
3537 // {
3538 // if (land.isBannedFromLand(agent.AgentID))
3539 // {
3540 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user has been banned from land",
3541 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3542 // reason = String.Format("Denied access to private region {0}: You are banned from that region.",
3543 // RegionInfo.RegionName);
3544 // return false;
3545 // }
3546
3547 // if (land.isRestrictedFromLand(agent.AgentID))
3548 // {
3549 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3550 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3551 // reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3552 // RegionInfo.RegionName);
3553 // return false;
3554 // }
3555 // }
3556 // }
3557
3558 return true; 3697 return true;
3559 } 3698 }
3560 3699
@@ -3658,6 +3797,13 @@ namespace OpenSim.Region.Framework.Scenes
3658 3797
3659 // We have to wait until the viewer contacts this region after receiving EAC. 3798 // We have to wait until the viewer contacts this region after receiving EAC.
3660 // That calls AddNewClient, which finally creates the ScenePresence 3799 // That calls AddNewClient, which finally creates the ScenePresence
3800 int flags = GetUserFlags(cAgentData.AgentID);
3801 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3802 {
3803 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3804 return false;
3805 }
3806
3661 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3807 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3662 if (nearestParcel == null) 3808 if (nearestParcel == null)
3663 { 3809 {
@@ -3665,6 +3811,14 @@ namespace OpenSim.Region.Framework.Scenes
3665 return false; 3811 return false;
3666 } 3812 }
3667 3813
3814 int num = m_sceneGraph.GetNumberOfScenePresences();
3815
3816 if (num >= RegionInfo.RegionSettings.AgentLimit)
3817 {
3818 if (!Permissions.IsAdministrator(cAgentData.AgentID))
3819 return false;
3820 }
3821
3668 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 3822 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
3669 3823
3670 if (childAgentUpdate != null) 3824 if (childAgentUpdate != null)
@@ -3731,12 +3885,22 @@ namespace OpenSim.Region.Framework.Scenes
3731 return false; 3885 return false;
3732 } 3886 }
3733 3887
3888 public bool IncomingCloseAgent(UUID agentID)
3889 {
3890 return IncomingCloseAgent(agentID, false);
3891 }
3892
3893 public bool IncomingCloseChildAgent(UUID agentID)
3894 {
3895 return IncomingCloseAgent(agentID, true);
3896 }
3897
3734 /// <summary> 3898 /// <summary>
3735 /// Tell a single agent to disconnect from the region. 3899 /// Tell a single agent to disconnect from the region.
3736 /// </summary> 3900 /// </summary>
3737 /// <param name="regionHandle"></param>
3738 /// <param name="agentID"></param> 3901 /// <param name="agentID"></param>
3739 public bool IncomingCloseAgent(UUID agentID) 3902 /// <param name="childOnly"></param>
3903 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3740 { 3904 {
3741 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3905 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3742 3906
@@ -3748,7 +3912,7 @@ namespace OpenSim.Region.Framework.Scenes
3748 { 3912 {
3749 m_sceneGraph.removeUserCount(false); 3913 m_sceneGraph.removeUserCount(false);
3750 } 3914 }
3751 else 3915 else if (!childOnly)
3752 { 3916 {
3753 m_sceneGraph.removeUserCount(true); 3917 m_sceneGraph.removeUserCount(true);
3754 } 3918 }
@@ -3764,9 +3928,12 @@ namespace OpenSim.Region.Framework.Scenes
3764 } 3928 }
3765 else 3929 else
3766 presence.ControllingClient.SendShutdownConnectionNotice(); 3930 presence.ControllingClient.SendShutdownConnectionNotice();
3931 presence.ControllingClient.Close(false);
3932 }
3933 else if (!childOnly)
3934 {
3935 presence.ControllingClient.Close(true);
3767 } 3936 }
3768
3769 presence.ControllingClient.Close();
3770 return true; 3937 return true;
3771 } 3938 }
3772 3939
@@ -4376,34 +4543,66 @@ namespace OpenSim.Region.Framework.Scenes
4376 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4543 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4377 } 4544 }
4378 4545
4379 public int GetHealth() 4546 public int GetHealth(out int flags, out string message)
4380 { 4547 {
4381 // Returns: 4548 // Returns:
4382 // 1 = sim is up and accepting http requests. The heartbeat has 4549 // 1 = sim is up and accepting http requests. The heartbeat has
4383 // stopped and the sim is probably locked up, but a remote 4550 // stopped and the sim is probably locked up, but a remote
4384 // admin restart may succeed 4551 // admin restart may succeed
4385 // 4552 //
4386 // 2 = Sim is up and the heartbeat is running. The sim is likely 4553 // 2 = Sim is up and the heartbeat is running. The sim is likely
4387 // usable for people within and logins _may_ work 4554 // usable for people within
4388 // 4555 //
4389 // 3 = We have seen a new user enter within the past 4 minutes 4556 // 3 = Sim is up and one packet thread is running. Sim is
4557 // unstable and will not accept new logins
4558 //
4559 // 4 = Sim is up and both packet threads are running. Sim is
4560 // likely usable
4561 //
4562 // 5 = We have seen a new user enter within the past 4 minutes
4390 // which can be seen as positive confirmation of sim health 4563 // which can be seen as positive confirmation of sim health
4391 // 4564 //
4565
4566 flags = 0;
4567 message = String.Empty;
4568
4569 CheckHeartbeat();
4570
4571 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4572 {
4573 // We're still starting
4574 // 0 means "in startup", it can't happen another way, since
4575 // to get here, we must be able to accept http connections
4576 return 0;
4577 }
4578
4392 int health=1; // Start at 1, means we're up 4579 int health=1; // Start at 1, means we're up
4393 4580
4394 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4581 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4582 {
4395 health+=1; 4583 health+=1;
4396 else 4584 flags |= 1;
4585 }
4586
4587 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4588 {
4589 health+=1;
4590 flags |= 2;
4591 }
4592
4593 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4594 {
4595 health+=1;
4596 flags |= 4;
4597 }
4598
4599 if (flags != 7)
4397 return health; 4600 return health;
4398 4601
4399 // A login in the last 4 mins? We can't be doing too badly 4602 // A login in the last 4 mins? We can't be doing too badly
4400 // 4603 //
4401 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4604 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4402 health++; 4605 health++;
4403 else
4404 return health;
4405
4406 CheckHeartbeat();
4407 4606
4408 return health; 4607 return health;
4409 } 4608 }
@@ -4596,7 +4795,7 @@ namespace OpenSim.Region.Framework.Scenes
4596 if (m_firstHeartbeat) 4795 if (m_firstHeartbeat)
4597 return; 4796 return;
4598 4797
4599 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4798 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 10000)
4600 StartTimer(); 4799 StartTimer();
4601 } 4800 }
4602 4801
@@ -4934,10 +5133,28 @@ namespace OpenSim.Region.Framework.Scenes
4934 }); 5133 });
4935 } 5134 }
4936 5135
4937 foreach (SceneObjectGroup grp in objectsToDelete) 5136 if (objectsToDelete.Count > 0)
4938 { 5137 {
4939 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID); 5138 m_log.DebugFormat("[SCENE]: Starting delete of {0} dropped attachments", objectsToDelete.Count);
4940 DeleteSceneObject(grp, true); 5139 foreach (SceneObjectGroup grp in objectsToDelete)
5140 {
5141 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5142 DeleteSceneObject(grp, true);
5143 }
5144 m_log.Debug("[SCENE]: Finished dropped attachment deletion");
5145 }
5146 }
5147
5148 public void ThreadAlive(int threadCode)
5149 {
5150 switch(threadCode)
5151 {
5152 case 1: // Incoming
5153 m_lastIncoming = Util.EnvironmentTickCount();
5154 break;
5155 case 2: // Incoming
5156 m_lastOutgoing = Util.EnvironmentTickCount();
5157 break;
4941 } 5158 }
4942 } 5159 }
4943 5160
@@ -4949,6 +5166,44 @@ namespace OpenSim.Region.Framework.Scenes
4949 // child agent creation, thereby emulating the SL behavior. 5166 // child agent creation, thereby emulating the SL behavior.
4950 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5167 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
4951 { 5168 {
5169 reason = "You are banned from the region";
5170
5171 if (Permissions.IsGod(agentID))
5172 {
5173 reason = String.Empty;
5174 return true;
5175 }
5176
5177 if (!AuthorizeUser(agentID, out reason))
5178 {
5179 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5180 return false;
5181 }
5182
5183 if (position == Vector3.Zero) // Teleport
5184 {
5185 float posX = 128.0f;
5186 float posY = 128.0f;
5187
5188 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5189 {
5190 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5191 return false;
5192 }
5193 }
5194 else // Walking
5195 {
5196 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5197 if (land == null)
5198 return false;
5199
5200 bool banned = land.IsBannedFromLand(agentID);
5201 bool restricted = land.IsRestrictedFromLand(agentID);
5202
5203 if (banned || restricted)
5204 return false;
5205 }
5206
4952 reason = String.Empty; 5207 reason = String.Empty;
4953 return true; 5208 return true;
4954 } 5209 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index c4547f2..f343bc8 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -136,6 +136,8 @@ namespace OpenSim.Region.Framework.Scenes
136 get { return m_permissions; } 136 get { return m_permissions; }
137 } 137 }
138 138
139 protected string m_datastore;
140
139 /* Used by the loadbalancer plugin on GForge */ 141 /* Used by the loadbalancer plugin on GForge */
140 protected RegionStatus m_regStatus; 142 protected RegionStatus m_regStatus;
141 public RegionStatus RegionStatus 143 public RegionStatus RegionStatus
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 837e655..19cb0c1 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;
@@ -259,46 +255,42 @@ namespace OpenSim.Region.Framework.Scenes
259 255
260 } 256 }
261 257
262 //public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle); 258 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
263 //private void SendCloseChildAgentCompleted(IAsyncResult iar)
264 //{
265 // SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
266 // icon.EndInvoke(iar);
267 //}
268 259
269 /// <summary> 260 /// <summary>
270 /// Closes a child agent on a given region 261 /// This Closes child agents on neighboring regions
262 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
271 /// </summary> 263 /// </summary>
272 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 264 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
273 { 265 {
274 266
275 m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle); 267 //m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle);
276 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 268 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
277 269
278 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); 270 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
279 uint x = 0, y = 0; 271 uint x = 0, y = 0;
280 Utils.LongToUInts(regionHandle, out x, out y); 272 Utils.LongToUInts(regionHandle, out x, out y);
281 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 273 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
282 m_scene.SimulationService.CloseAgent(destination, agentID); 274 m_scene.SimulationService.CloseChildAgent(destination, agentID);
275 }
276
277 private void SendCloseChildAgentCompleted(IAsyncResult iar)
278 {
279 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
280 icon.EndInvoke(iar);
283 } 281 }
284 282
285 /// <summary>
286 /// Closes a child agents in a collection of regions. Does so asynchronously
287 /// so that the caller doesn't wait.
288 /// </summary>
289 /// <param name="agentID"></param>
290 /// <param name="regionslst"></param>
291 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 283 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
292 { 284 {
293 Util.FireAndForget(delegate 285 foreach (ulong handle in regionslst)
294 { 286 {
295 foreach (ulong handle in regionslst) 287 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
296 { 288 d.BeginInvoke(agentID, handle,
297 SendCloseChildAgent(agentID, handle); 289 SendCloseChildAgentCompleted,
298 } 290 d);
299 }); 291 }
300 } 292 }
301 293
302 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 294 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
303 { 295 {
304 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 296 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 97af0a0..6773e08 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
@@ -135,13 +144,18 @@ namespace OpenSim.Region.Framework.Scenes
135 144
136 protected internal void Close() 145 protected internal void Close()
137 { 146 {
138 lock (m_presenceLock) 147 m_scenePresencesLock.EnterWriteLock();
148 try
139 { 149 {
140 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 150 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
141 List<ScenePresence> newlist = new List<ScenePresence>(); 151 List<ScenePresence> newlist = new List<ScenePresence>();
142 m_scenePresenceMap = newmap; 152 m_scenePresenceMap = newmap;
143 m_scenePresenceArray = newlist; 153 m_scenePresenceArray = newlist;
144 } 154 }
155 finally
156 {
157 m_scenePresencesLock.ExitWriteLock();
158 }
145 159
146 lock (SceneObjectGroupsByFullID) 160 lock (SceneObjectGroupsByFullID)
147 SceneObjectGroupsByFullID.Clear(); 161 SceneObjectGroupsByFullID.Clear();
@@ -273,6 +287,33 @@ namespace OpenSim.Region.Framework.Scenes
273 protected internal bool AddRestoredSceneObject( 287 protected internal bool AddRestoredSceneObject(
274 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 288 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
275 { 289 {
290 if (!m_parentScene.CombineRegions)
291 {
292 // KF: Check for out-of-region, move inside and make static.
293 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
294 sceneObject.RootPart.GroupPosition.Y,
295 sceneObject.RootPart.GroupPosition.Z);
296 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 ||
297 npos.X > Constants.RegionSize ||
298 npos.Y > Constants.RegionSize))
299 {
300 if (npos.X < 0.0) npos.X = 1.0f;
301 if (npos.Y < 0.0) npos.Y = 1.0f;
302 if (npos.Z < 0.0) npos.Z = 0.0f;
303 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
304 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
305
306 foreach (SceneObjectPart part in sceneObject.Parts)
307 {
308 part.GroupPosition = npos;
309 }
310 sceneObject.RootPart.Velocity = Vector3.Zero;
311 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
312 sceneObject.RootPart.Acceleration = Vector3.Zero;
313 sceneObject.RootPart.Velocity = Vector3.Zero;
314 }
315 }
316
276 if (attachToBackup && (!alreadyPersisted)) 317 if (attachToBackup && (!alreadyPersisted))
277 { 318 {
278 sceneObject.ForceInventoryPersistence(); 319 sceneObject.ForceInventoryPersistence();
@@ -482,6 +523,30 @@ namespace OpenSim.Region.Framework.Scenes
482 m_updateList[obj.UUID] = obj; 523 m_updateList[obj.UUID] = obj;
483 } 524 }
484 525
526 public void FireAttachToBackup(SceneObjectGroup obj)
527 {
528 if (OnAttachToBackup != null)
529 {
530 OnAttachToBackup(obj);
531 }
532 }
533
534 public void FireDetachFromBackup(SceneObjectGroup obj)
535 {
536 if (OnDetachFromBackup != null)
537 {
538 OnDetachFromBackup(obj);
539 }
540 }
541
542 public void FireChangeBackup(SceneObjectGroup obj)
543 {
544 if (OnChangeBackup != null)
545 {
546 OnChangeBackup(obj);
547 }
548 }
549
485 /// <summary> 550 /// <summary>
486 /// Process all pending updates 551 /// Process all pending updates
487 /// </summary> 552 /// </summary>
@@ -617,7 +682,8 @@ namespace OpenSim.Region.Framework.Scenes
617 682
618 Entities[presence.UUID] = presence; 683 Entities[presence.UUID] = presence;
619 684
620 lock (m_presenceLock) 685 m_scenePresencesLock.EnterWriteLock();
686 try
621 { 687 {
622 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 688 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
623 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 689 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -641,6 +707,10 @@ namespace OpenSim.Region.Framework.Scenes
641 m_scenePresenceMap = newmap; 707 m_scenePresenceMap = newmap;
642 m_scenePresenceArray = newlist; 708 m_scenePresenceArray = newlist;
643 } 709 }
710 finally
711 {
712 m_scenePresencesLock.ExitWriteLock();
713 }
644 } 714 }
645 715
646 /// <summary> 716 /// <summary>
@@ -655,7 +725,8 @@ namespace OpenSim.Region.Framework.Scenes
655 agentID); 725 agentID);
656 } 726 }
657 727
658 lock (m_presenceLock) 728 m_scenePresencesLock.EnterWriteLock();
729 try
659 { 730 {
660 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 731 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
661 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 732 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -677,6 +748,10 @@ namespace OpenSim.Region.Framework.Scenes
677 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 748 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
678 } 749 }
679 } 750 }
751 finally
752 {
753 m_scenePresencesLock.ExitWriteLock();
754 }
680 } 755 }
681 756
682 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 757 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -800,6 +875,11 @@ namespace OpenSim.Region.Framework.Scenes
800 return m_scenePresenceArray; 875 return m_scenePresenceArray;
801 } 876 }
802 877
878 public int GetNumberOfScenePresences()
879 {
880 return m_scenePresenceArray.Count;
881 }
882
803 /// <summary> 883 /// <summary>
804 /// Request a scene presence by UUID. Fast, indexed lookup. 884 /// Request a scene presence by UUID. Fast, indexed lookup.
805 /// </summary> 885 /// </summary>
@@ -1307,8 +1387,13 @@ namespace OpenSim.Region.Framework.Scenes
1307 { 1387 {
1308 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1388 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1309 { 1389 {
1310 if (m_parentScene.AttachmentsModule != null) 1390 // Set the new attachment point data in the object
1311 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1391 byte attachmentPoint = group.GetAttachmentPoint();
1392 group.UpdateGroupPosition(pos);
1393 group.RootPart.IsAttachment = false;
1394 group.AbsolutePosition = group.RootPart.AttachedPos;
1395 group.SetAttachmentPoint(attachmentPoint);
1396 group.HasGroupChanged = true;
1312 } 1397 }
1313 else 1398 else
1314 { 1399 {
@@ -1552,10 +1637,13 @@ namespace OpenSim.Region.Framework.Scenes
1552 /// <param name="childPrims"></param> 1637 /// <param name="childPrims"></param>
1553 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1638 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1554 { 1639 {
1640 SceneObjectGroup parentGroup = root.ParentGroup;
1641 if (parentGroup == null) return;
1555 Monitor.Enter(m_updateLock); 1642 Monitor.Enter(m_updateLock);
1643
1556 try 1644 try
1557 { 1645 {
1558 SceneObjectGroup parentGroup = root.ParentGroup; 1646 parentGroup.areUpdatesSuspended = true;
1559 1647
1560 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1648 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1561 if (parentGroup != null) 1649 if (parentGroup != null)
@@ -1567,11 +1655,6 @@ namespace OpenSim.Region.Framework.Scenes
1567 1655
1568 if (child != null) 1656 if (child != null)
1569 { 1657 {
1570 // Make sure no child prim is set for sale
1571 // So that, on delink, no prims are unwittingly
1572 // left for sale and sold off
1573 child.RootPart.ObjectSaleType = 0;
1574 child.RootPart.SalePrice = 10;
1575 childGroups.Add(child); 1658 childGroups.Add(child);
1576 } 1659 }
1577 } 1660 }
@@ -1594,12 +1677,13 @@ namespace OpenSim.Region.Framework.Scenes
1594 // occur on link to invoke this elsewhere (such as object selection) 1677 // occur on link to invoke this elsewhere (such as object selection)
1595 parentGroup.RootPart.CreateSelected = true; 1678 parentGroup.RootPart.CreateSelected = true;
1596 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1679 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1597 parentGroup.HasGroupChanged = true;
1598 parentGroup.ScheduleGroupForFullUpdate();
1599
1600 } 1680 }
1601 finally 1681 finally
1602 { 1682 {
1683 parentGroup.areUpdatesSuspended = false;
1684 parentGroup.HasGroupChanged = true;
1685 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1686 parentGroup.ScheduleGroupForFullUpdate();
1603 Monitor.Exit(m_updateLock); 1687 Monitor.Exit(m_updateLock);
1604 } 1688 }
1605 } 1689 }
@@ -1631,21 +1715,24 @@ namespace OpenSim.Region.Framework.Scenes
1631 1715
1632 SceneObjectGroup group = part.ParentGroup; 1716 SceneObjectGroup group = part.ParentGroup;
1633 if (!affectedGroups.Contains(group)) 1717 if (!affectedGroups.Contains(group))
1718 {
1719 group.areUpdatesSuspended = true;
1634 affectedGroups.Add(group); 1720 affectedGroups.Add(group);
1721 }
1635 } 1722 }
1636 } 1723 }
1637 } 1724 }
1638 1725
1639 foreach (SceneObjectPart child in childParts) 1726 if (childParts.Count > 0)
1640 { 1727 {
1641 // Unlink all child parts from their groups 1728 foreach (SceneObjectPart child in childParts)
1642 // 1729 {
1643 child.ParentGroup.DelinkFromGroup(child, true); 1730 // Unlink all child parts from their groups
1644 1731 //
1645 // These are not in affected groups and will not be 1732 child.ParentGroup.DelinkFromGroup(child, true);
1646 // handled further. Do the honors here. 1733 child.ParentGroup.HasGroupChanged = true;
1647 child.ParentGroup.HasGroupChanged = true; 1734 child.ParentGroup.ScheduleGroupForFullUpdate();
1648 child.ParentGroup.ScheduleGroupForFullUpdate(); 1735 }
1649 } 1736 }
1650 1737
1651 foreach (SceneObjectPart root in rootParts) 1738 foreach (SceneObjectPart root in rootParts)
@@ -1655,56 +1742,68 @@ namespace OpenSim.Region.Framework.Scenes
1655 // However, editing linked parts and unlinking may be different 1742 // However, editing linked parts and unlinking may be different
1656 // 1743 //
1657 SceneObjectGroup group = root.ParentGroup; 1744 SceneObjectGroup group = root.ParentGroup;
1745 group.areUpdatesSuspended = true;
1658 1746
1659 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1747 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1660 int numChildren = newSet.Count; 1748 int numChildren = newSet.Count;
1661 1749
1750 if (numChildren == 1)
1751 break;
1752
1662 // If there are prims left in a link set, but the root is 1753 // If there are prims left in a link set, but the root is
1663 // slated for unlink, we need to do this 1754 // slated for unlink, we need to do this
1755 // Unlink the remaining set
1664 // 1756 //
1665 if (numChildren != 1) 1757 bool sendEventsToRemainder = true;
1666 { 1758 if (numChildren > 1)
1667 // Unlink the remaining set 1759 sendEventsToRemainder = false;
1668 //
1669 bool sendEventsToRemainder = true;
1670 if (numChildren > 1)
1671 sendEventsToRemainder = false;
1672 1760
1673 foreach (SceneObjectPart p in newSet) 1761 foreach (SceneObjectPart p in newSet)
1762 {
1763 if (p != group.RootPart)
1674 { 1764 {
1675 if (p != group.RootPart) 1765 group.DelinkFromGroup(p, sendEventsToRemainder);
1676 group.DelinkFromGroup(p, sendEventsToRemainder); 1766 if (numChildren > 2)
1767 {
1768 p.ParentGroup.areUpdatesSuspended = true;
1769 }
1770 else
1771 {
1772 p.ParentGroup.HasGroupChanged = true;
1773 p.ParentGroup.ScheduleGroupForFullUpdate();
1774 }
1677 } 1775 }
1776 }
1777
1778 // If there is more than one prim remaining, we
1779 // need to re-link
1780 //
1781 if (numChildren > 2)
1782 {
1783 // Remove old root
1784 //
1785 if (newSet.Contains(root))
1786 newSet.Remove(root);
1678 1787
1679 // If there is more than one prim remaining, we 1788 // Preserve link ordering
1680 // need to re-link
1681 // 1789 //
1682 if (numChildren > 2) 1790 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1683 { 1791 {
1684 // Remove old root 1792 return a.LinkNum.CompareTo(b.LinkNum);
1685 // 1793 });
1686 if (newSet.Contains(root))
1687 newSet.Remove(root);
1688
1689 // Preserve link ordering
1690 //
1691 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1692 {
1693 return a.LinkNum.CompareTo(b.LinkNum);
1694 });
1695 1794
1696 // Determine new root 1795 // Determine new root
1697 // 1796 //
1698 SceneObjectPart newRoot = newSet[0]; 1797 SceneObjectPart newRoot = newSet[0];
1699 newSet.RemoveAt(0); 1798 newSet.RemoveAt(0);
1700 1799
1701 foreach (SceneObjectPart newChild in newSet) 1800 foreach (SceneObjectPart newChild in newSet)
1702 newChild.UpdateFlag = 0; 1801 newChild.UpdateFlag = 0;
1703 1802
1704 LinkObjects(newRoot, newSet); 1803 newRoot.ParentGroup.areUpdatesSuspended = true;
1705 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1804 LinkObjects(newRoot, newSet);
1706 affectedGroups.Add(newRoot.ParentGroup); 1805 if (!affectedGroups.Contains(newRoot.ParentGroup))
1707 } 1806 affectedGroups.Add(newRoot.ParentGroup);
1708 } 1807 }
1709 } 1808 }
1710 1809
@@ -1712,8 +1811,14 @@ namespace OpenSim.Region.Framework.Scenes
1712 // 1811 //
1713 foreach (SceneObjectGroup g in affectedGroups) 1812 foreach (SceneObjectGroup g in affectedGroups)
1714 { 1813 {
1814 // Child prims that have been unlinked and deleted will
1815 // return unless the root is deleted. This will remove them
1816 // from the database. They will be rewritten immediately,
1817 // minus the rows for the unlinked child prims.
1818 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1715 g.TriggerScriptChangedEvent(Changed.LINK); 1819 g.TriggerScriptChangedEvent(Changed.LINK);
1716 g.HasGroupChanged = true; // Persist 1820 g.HasGroupChanged = true; // Persist
1821 g.areUpdatesSuspended = false;
1717 g.ScheduleGroupForFullUpdate(); 1822 g.ScheduleGroupForFullUpdate();
1718 } 1823 }
1719 } 1824 }
@@ -1831,9 +1936,6 @@ namespace OpenSim.Region.Framework.Scenes
1831 child.ApplyNextOwnerPermissions(); 1936 child.ApplyNextOwnerPermissions();
1832 } 1937 }
1833 } 1938 }
1834
1835 copy.RootPart.ObjectSaleType = 0;
1836 copy.RootPart.SalePrice = 10;
1837 } 1939 }
1838 1940
1839 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 1941 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index e8095c0..0b545c4 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 ca7d9d9..759fc23 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 //{
@@ -469,6 +563,7 @@ namespace OpenSim.Region.Framework.Scenes
469 /// </summary> 563 /// </summary>
470 public SceneObjectGroup() 564 public SceneObjectGroup()
471 { 565 {
566
472 } 567 }
473 568
474 /// <summary> 569 /// <summary>
@@ -485,7 +580,7 @@ namespace OpenSim.Region.Framework.Scenes
485 /// Constructor. This object is added to the scene later via AttachToScene() 580 /// Constructor. This object is added to the scene later via AttachToScene()
486 /// </summary> 581 /// </summary>
487 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 582 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
488 { 583 {
489 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 584 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
490 } 585 }
491 586
@@ -533,6 +628,9 @@ namespace OpenSim.Region.Framework.Scenes
533 /// </summary> 628 /// </summary>
534 public virtual void AttachToBackup() 629 public virtual void AttachToBackup()
535 { 630 {
631 if (IsAttachment) return;
632 m_scene.SceneGraph.FireAttachToBackup(this);
633
536 if (InSceneBackup) 634 if (InSceneBackup)
537 { 635 {
538 //m_log.DebugFormat( 636 //m_log.DebugFormat(
@@ -648,9 +746,9 @@ namespace OpenSim.Region.Framework.Scenes
648 result.normal = inter.normal; 746 result.normal = inter.normal;
649 result.distance = inter.distance; 747 result.distance = inter.distance;
650 } 748 }
749
651 } 750 }
652 } 751 }
653
654 return result; 752 return result;
655 } 753 }
656 754
@@ -670,17 +768,19 @@ namespace OpenSim.Region.Framework.Scenes
670 minZ = 8192f; 768 minZ = 8192f;
671 769
672 SceneObjectPart[] parts = m_parts.GetArray(); 770 SceneObjectPart[] parts = m_parts.GetArray();
673 for (int i = 0; i < parts.Length; i++) 771 foreach (SceneObjectPart part in parts)
674 { 772 {
675 SceneObjectPart part = parts[i];
676
677 Vector3 worldPos = part.GetWorldPosition(); 773 Vector3 worldPos = part.GetWorldPosition();
678 Vector3 offset = worldPos - AbsolutePosition; 774 Vector3 offset = worldPos - AbsolutePosition;
679 Quaternion worldRot; 775 Quaternion worldRot;
680 if (part.ParentID == 0) 776 if (part.ParentID == 0)
777 {
681 worldRot = part.RotationOffset; 778 worldRot = part.RotationOffset;
779 }
682 else 780 else
781 {
683 worldRot = part.GetWorldRotation(); 782 worldRot = part.GetWorldRotation();
783 }
684 784
685 Vector3 frontTopLeft; 785 Vector3 frontTopLeft;
686 Vector3 frontTopRight; 786 Vector3 frontTopRight;
@@ -692,6 +792,8 @@ namespace OpenSim.Region.Framework.Scenes
692 Vector3 backBottomLeft; 792 Vector3 backBottomLeft;
693 Vector3 backBottomRight; 793 Vector3 backBottomRight;
694 794
795 // Vector3[] corners = new Vector3[8];
796
695 Vector3 orig = Vector3.Zero; 797 Vector3 orig = Vector3.Zero;
696 798
697 frontTopLeft.X = orig.X - (part.Scale.X / 2); 799 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -726,6 +828,38 @@ namespace OpenSim.Region.Framework.Scenes
726 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 828 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
727 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 829 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
728 830
831
832
833 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
834 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
835 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
836 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
837 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
838 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
839 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
840 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
841
842 //for (int i = 0; i < 8; i++)
843 //{
844 // corners[i] = corners[i] * worldRot;
845 // corners[i] += offset;
846
847 // if (corners[i].X > maxX)
848 // maxX = corners[i].X;
849 // if (corners[i].X < minX)
850 // minX = corners[i].X;
851
852 // if (corners[i].Y > maxY)
853 // maxY = corners[i].Y;
854 // if (corners[i].Y < minY)
855 // minY = corners[i].Y;
856
857 // if (corners[i].Z > maxZ)
858 // maxZ = corners[i].Y;
859 // if (corners[i].Z < minZ)
860 // minZ = corners[i].Z;
861 //}
862
729 frontTopLeft = frontTopLeft * worldRot; 863 frontTopLeft = frontTopLeft * worldRot;
730 frontTopRight = frontTopRight * worldRot; 864 frontTopRight = frontTopRight * worldRot;
731 frontBottomLeft = frontBottomLeft * worldRot; 865 frontBottomLeft = frontBottomLeft * worldRot;
@@ -747,6 +881,15 @@ namespace OpenSim.Region.Framework.Scenes
747 backTopLeft += offset; 881 backTopLeft += offset;
748 backTopRight += offset; 882 backTopRight += offset;
749 883
884 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
885 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
886 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
887 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
888 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
889 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
890 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
891 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
892
750 if (frontTopRight.X > maxX) 893 if (frontTopRight.X > maxX)
751 maxX = frontTopRight.X; 894 maxX = frontTopRight.X;
752 if (frontTopLeft.X > maxX) 895 if (frontTopLeft.X > maxX)
@@ -892,15 +1035,20 @@ namespace OpenSim.Region.Framework.Scenes
892 1035
893 public void SaveScriptedState(XmlTextWriter writer) 1036 public void SaveScriptedState(XmlTextWriter writer)
894 { 1037 {
1038 SaveScriptedState(writer, false);
1039 }
1040
1041 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1042 {
895 XmlDocument doc = new XmlDocument(); 1043 XmlDocument doc = new XmlDocument();
896 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1044 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
897 1045
898 SceneObjectPart[] parts = m_parts.GetArray(); 1046 SceneObjectPart[] parts = m_parts.GetArray();
899 for (int i = 0; i < parts.Length; i++) 1047 for (int i = 0; i < parts.Length; i++)
900 { 1048 {
901 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1049 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
902 foreach (KeyValuePair<UUID, string> kvp in pstates) 1050 foreach (KeyValuePair<UUID, string> kvp in pstates)
903 states.Add(kvp.Key, kvp.Value); 1051 states[kvp.Key] = kvp.Value;
904 } 1052 }
905 1053
906 if (states.Count > 0) 1054 if (states.Count > 0)
@@ -919,6 +1067,118 @@ namespace OpenSim.Region.Framework.Scenes
919 } 1067 }
920 } 1068 }
921 1069
1070 /// <summary>
1071 /// Add the avatar to this linkset (avatar is sat).
1072 /// </summary>
1073 /// <param name="agentID"></param>
1074 public void AddAvatar(UUID agentID)
1075 {
1076 ScenePresence presence;
1077 if (m_scene.TryGetScenePresence(agentID, out presence))
1078 {
1079 if (!m_linkedAvatars.Contains(presence))
1080 {
1081 m_linkedAvatars.Add(presence);
1082 }
1083 }
1084 }
1085
1086 /// <summary>
1087 /// Delete the avatar from this linkset (avatar is unsat).
1088 /// </summary>
1089 /// <param name="agentID"></param>
1090 public void DeleteAvatar(UUID agentID)
1091 {
1092 ScenePresence presence;
1093 if (m_scene.TryGetScenePresence(agentID, out presence))
1094 {
1095 if (m_linkedAvatars.Contains(presence))
1096 {
1097 m_linkedAvatars.Remove(presence);
1098 }
1099 }
1100 }
1101
1102 /// <summary>
1103 /// Returns the list of linked presences (avatars sat on this group)
1104 /// </summary>
1105 /// <param name="agentID"></param>
1106 public List<ScenePresence> GetLinkedAvatars()
1107 {
1108 return m_linkedAvatars;
1109 }
1110
1111 /// <summary>
1112 /// Attach this scene object to the given avatar.
1113 /// </summary>
1114 /// <param name="agentID"></param>
1115 /// <param name="attachmentpoint"></param>
1116 /// <param name="AttachOffset"></param>
1117 public void AttachToAgent(UUID agentID, uint attachmentpoint, Vector3 AttachOffset, bool silent)
1118 {
1119 ScenePresence avatar = m_scene.GetScenePresence(agentID);
1120 if (avatar != null)
1121 {
1122 // don't attach attachments to child agents
1123 if (avatar.IsChildAgent) return;
1124
1125// m_log.DebugFormat("[SOG]: Adding attachment {0} to avatar {1}", Name, avatar.Name);
1126
1127 DetachFromBackup();
1128
1129 // Remove from database and parcel prim count
1130 m_scene.DeleteFromStorage(UUID);
1131 m_scene.EventManager.TriggerParcelPrimCountTainted();
1132
1133 m_rootPart.AttachedAvatar = agentID;
1134
1135 //Anakin Lohner bug #3839
1136 lock (m_parts)
1137 {
1138 foreach (SceneObjectPart p in m_parts.GetArray())
1139 {
1140 p.AttachedAvatar = agentID;
1141 }
1142 }
1143
1144 if (m_rootPart.PhysActor != null)
1145 {
1146 m_scene.PhysicsScene.RemovePrim(m_rootPart.PhysActor);
1147 m_rootPart.PhysActor = null;
1148 }
1149
1150 AbsolutePosition = AttachOffset;
1151 m_rootPart.AttachedPos = AttachOffset;
1152 m_rootPart.IsAttachment = true;
1153
1154 m_rootPart.SetParentLocalId(avatar.LocalId);
1155 SetAttachmentPoint(Convert.ToByte(attachmentpoint));
1156
1157 avatar.AddAttachment(this);
1158
1159 if (!silent)
1160 {
1161 // Killing it here will cause the client to deselect it
1162 // It then reappears on the avatar, deselected
1163 // through the full update below
1164 //
1165 if (IsSelected)
1166 {
1167 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1168 }
1169
1170 IsSelected = false; // fudge....
1171 ScheduleGroupForFullUpdate();
1172 }
1173 }
1174 else
1175 {
1176 m_log.WarnFormat(
1177 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1178 UUID, agentID, Scene.RegionInfo.RegionName);
1179 }
1180 }
1181
922 public byte GetAttachmentPoint() 1182 public byte GetAttachmentPoint()
923 { 1183 {
924 return m_rootPart.Shape.State; 1184 return m_rootPart.Shape.State;
@@ -1045,7 +1305,10 @@ namespace OpenSim.Region.Framework.Scenes
1045 public void AddPart(SceneObjectPart part) 1305 public void AddPart(SceneObjectPart part)
1046 { 1306 {
1047 part.SetParent(this); 1307 part.SetParent(this);
1048 part.LinkNum = m_parts.Add(part.UUID, part); 1308 m_parts.Add(part.UUID, part);
1309
1310 part.LinkNum = m_parts.Count;
1311
1049 if (part.LinkNum == 2 && RootPart != null) 1312 if (part.LinkNum == 2 && RootPart != null)
1050 RootPart.LinkNum = 1; 1313 RootPart.LinkNum = 1;
1051 } 1314 }
@@ -1129,7 +1392,7 @@ namespace OpenSim.Region.Framework.Scenes
1129 1392
1130 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1393 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1131 { 1394 {
1132 part.StoreUndoState(); 1395 part.StoreUndoState(UndoType.STATE_PRIM_ALL);
1133 part.OnGrab(offsetPos, remoteClient); 1396 part.OnGrab(offsetPos, remoteClient);
1134 } 1397 }
1135 1398
@@ -1149,6 +1412,11 @@ namespace OpenSim.Region.Framework.Scenes
1149 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1412 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1150 public void DeleteGroupFromScene(bool silent) 1413 public void DeleteGroupFromScene(bool silent)
1151 { 1414 {
1415 // We need to keep track of this state in case this group is still queued for backup.
1416 m_isDeleted = true;
1417
1418 DetachFromBackup();
1419
1152 SceneObjectPart[] parts = m_parts.GetArray(); 1420 SceneObjectPart[] parts = m_parts.GetArray();
1153 for (int i = 0; i < parts.Length; i++) 1421 for (int i = 0; i < parts.Length; i++)
1154 { 1422 {
@@ -1160,13 +1428,11 @@ namespace OpenSim.Region.Framework.Scenes
1160 avatar.StandUp(); 1428 avatar.StandUp();
1161 1429
1162 if (!silent) 1430 if (!silent)
1163 {
1164 part.UpdateFlag = 0; 1431 part.UpdateFlag = 0;
1165 if (part == m_rootPart)
1166 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1167 }
1168 }); 1432 });
1169 } 1433 }
1434
1435
1170 } 1436 }
1171 1437
1172 public void AddScriptLPS(int count) 1438 public void AddScriptLPS(int count)
@@ -1263,7 +1529,12 @@ namespace OpenSim.Region.Framework.Scenes
1263 1529
1264 public void SetOwnerId(UUID userId) 1530 public void SetOwnerId(UUID userId)
1265 { 1531 {
1266 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1532 ForEachPart(delegate(SceneObjectPart part)
1533 {
1534
1535 part.OwnerID = userId;
1536
1537 });
1267 } 1538 }
1268 1539
1269 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1540 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1295,11 +1566,17 @@ namespace OpenSim.Region.Framework.Scenes
1295 return; 1566 return;
1296 } 1567 }
1297 1568
1569 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1570 return;
1571
1298 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1572 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1299 // any exception propogate upwards. 1573 // any exception propogate upwards.
1300 try 1574 try
1301 { 1575 {
1302 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1576 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1577 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1578 m_scene.LoadingPrims) // Land may not be valid yet
1579
1303 { 1580 {
1304 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1581 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1305 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1582 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1326,6 +1603,7 @@ namespace OpenSim.Region.Framework.Scenes
1326 } 1603 }
1327 } 1604 }
1328 } 1605 }
1606
1329 } 1607 }
1330 1608
1331 if (HasGroupChanged) 1609 if (HasGroupChanged)
@@ -1333,6 +1611,20 @@ namespace OpenSim.Region.Framework.Scenes
1333 // don't backup while it's selected or you're asking for changes mid stream. 1611 // don't backup while it's selected or you're asking for changes mid stream.
1334 if (isTimeToPersist() || forcedBackup) 1612 if (isTimeToPersist() || forcedBackup)
1335 { 1613 {
1614 if (m_rootPart.PhysActor != null &&
1615 (!m_rootPart.PhysActor.IsPhysical))
1616 {
1617 // Possible ghost prim
1618 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1619 {
1620 foreach (SceneObjectPart part in m_parts.GetArray())
1621 {
1622 // Re-set physics actor positions and
1623 // orientations
1624 part.GroupPosition = m_rootPart.GroupPosition;
1625 }
1626 }
1627 }
1336// m_log.DebugFormat( 1628// m_log.DebugFormat(
1337// "[SCENE]: Storing {0}, {1} in {2}", 1629// "[SCENE]: Storing {0}, {1} in {2}",
1338// Name, UUID, m_scene.RegionInfo.RegionName); 1630// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1396,81 +1688,90 @@ namespace OpenSim.Region.Framework.Scenes
1396 /// <returns></returns> 1688 /// <returns></returns>
1397 public SceneObjectGroup Copy(bool userExposed) 1689 public SceneObjectGroup Copy(bool userExposed)
1398 { 1690 {
1399 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1691 SceneObjectGroup dupe;
1400 dupe.m_isBackedUp = false; 1692 try
1401 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 1693 {
1402 1694 m_dupeInProgress = true;
1403 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 1695 dupe = (SceneObjectGroup)MemberwiseClone();
1404 // attachments do not bordercross while they're being duplicated. This is hacktastic! 1696 dupe.m_isBackedUp = false;
1405 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! 1697 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1406 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1407 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1408 // then restore it's attachment state
1409
1410 // This is only necessary when userExposed is false!
1411 1698
1412 bool previousAttachmentStatus = dupe.RootPart.IsAttachment; 1699 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1413 1700 // attachments do not bordercross while they're being duplicated. This is hacktastic!
1414 if (!userExposed) 1701 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
1415 dupe.RootPart.IsAttachment = true; 1702 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1703 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1704 // then restore it's attachment state
1416 1705
1417 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 1706 // This is only necessary when userExposed is false!
1418 1707
1419 if (!userExposed) 1708 bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
1420 {
1421 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1422 }
1423 1709
1424 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 1710 if (!userExposed)
1425 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 1711 dupe.RootPart.IsAttachment = true;
1426 1712
1427 if (userExposed) 1713 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
1428 dupe.m_rootPart.TrimPermissions();
1429 1714
1430 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1715 if (!userExposed)
1431
1432 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1433 { 1716 {
1434 return p1.LinkNum.CompareTo(p2.LinkNum); 1717 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1435 } 1718 }
1436 );
1437 1719
1438 foreach (SceneObjectPart part in partList) 1720 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1439 { 1721 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1440 if (part.UUID != m_rootPart.UUID) 1722
1723 if (userExposed)
1724 dupe.m_rootPart.TrimPermissions();
1725
1726 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1727
1728 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1729 {
1730 return p1.LinkNum.CompareTo(p2.LinkNum);
1731 }
1732 );
1733
1734 foreach (SceneObjectPart part in partList)
1441 { 1735 {
1442 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 1736 if (part.UUID != m_rootPart.UUID)
1443 newPart.LinkNum = part.LinkNum; 1737 {
1444 } 1738 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1445 1739
1446 // Need to duplicate the physics actor as well 1740 newPart.LinkNum = part.LinkNum;
1447 if (part.PhysActor != null && userExposed) 1741 }
1742
1743 // Need to duplicate the physics actor as well
1744 if (part.PhysActor != null && userExposed)
1745 {
1746 PrimitiveBaseShape pbs = part.Shape;
1747
1748 part.PhysActor
1749 = m_scene.PhysicsScene.AddPrimShape(
1750 string.Format("{0}/{1}", part.Name, part.UUID),
1751 pbs,
1752 part.AbsolutePosition,
1753 part.Scale,
1754 part.RotationOffset,
1755 part.PhysActor.IsPhysical);
1756 part.PhysActor.SetMaterial((int)part.Material);
1757
1758 part.PhysActor.LocalID = part.LocalId;
1759 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1760 }
1761 }
1762 if (userExposed)
1448 { 1763 {
1449 PrimitiveBaseShape pbs = part.Shape; 1764 dupe.UpdateParentIDs();
1450 1765 dupe.HasGroupChanged = true;
1451 part.PhysActor 1766 dupe.AttachToBackup();
1452 = m_scene.PhysicsScene.AddPrimShape( 1767
1453 string.Format("{0}/{1}", part.Name, part.UUID), 1768 ScheduleGroupForFullUpdate();
1454 pbs,
1455 part.AbsolutePosition,
1456 part.Scale,
1457 part.RotationOffset,
1458 part.PhysActor.IsPhysical);
1459
1460 part.PhysActor.LocalID = part.LocalId;
1461 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1462 } 1769 }
1463 } 1770 }
1464 1771 finally
1465 if (userExposed)
1466 { 1772 {
1467 dupe.UpdateParentIDs(); 1773 m_dupeInProgress = false;
1468 dupe.HasGroupChanged = true;
1469 dupe.AttachToBackup();
1470
1471 ScheduleGroupForFullUpdate();
1472 } 1774 }
1473
1474 return dupe; 1775 return dupe;
1475 } 1776 }
1476 1777
@@ -1615,6 +1916,7 @@ namespace OpenSim.Region.Framework.Scenes
1615 return Vector3.Zero; 1916 return Vector3.Zero;
1616 } 1917 }
1617 1918
1919 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1618 public void moveToTarget(Vector3 target, float tau) 1920 public void moveToTarget(Vector3 target, float tau)
1619 { 1921 {
1620 SceneObjectPart rootpart = m_rootPart; 1922 SceneObjectPart rootpart = m_rootPart;
@@ -1654,20 +1956,55 @@ namespace OpenSim.Region.Framework.Scenes
1654 SceneObjectPart rootpart = m_rootPart; 1956 SceneObjectPart rootpart = m_rootPart;
1655 if (rootpart != null) 1957 if (rootpart != null)
1656 { 1958 {
1657 if (rootpart.PhysActor != null) 1959 if (IsAttachment)
1960 {
1961 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1962 if (avatar != null) avatar.StopMoveToPosition();
1963 }
1964 else
1658 { 1965 {
1659 rootpart.PhysActor.PIDActive = false; 1966 if (rootpart.PhysActor != null)
1967 {
1968 rootpart.PhysActor.PIDActive = false;
1969 }
1660 } 1970 }
1661 } 1971 }
1662 } 1972 }
1663 1973
1974 public void rotLookAt(Quaternion target, float strength, float damping)
1975 {
1976 SceneObjectPart rootpart = m_rootPart;
1977 if (rootpart != null)
1978 {
1979 if (IsAttachment)
1980 {
1981 /*
1982 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1983 if (avatar != null)
1984 {
1985 Rotate the Av?
1986 } */
1987 }
1988 else
1989 {
1990 if (rootpart.PhysActor != null)
1991 { // APID must be implemented in your physics system for this to function.
1992 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1993 rootpart.PhysActor.APIDStrength = strength;
1994 rootpart.PhysActor.APIDDamping = damping;
1995 rootpart.PhysActor.APIDActive = true;
1996 }
1997 }
1998 }
1999 }
2000
1664 public void stopLookAt() 2001 public void stopLookAt()
1665 { 2002 {
1666 SceneObjectPart rootpart = m_rootPart; 2003 SceneObjectPart rootpart = m_rootPart;
1667 if (rootpart != null) 2004 if (rootpart != null)
1668 { 2005 {
1669 if (rootpart.PhysActor != null) 2006 if (rootpart.PhysActor != null)
1670 { 2007 { // APID must be implemented in your physics system for this to function.
1671 rootpart.PhysActor.APIDActive = false; 2008 rootpart.PhysActor.APIDActive = false;
1672 } 2009 }
1673 } 2010 }
@@ -1733,6 +2070,8 @@ namespace OpenSim.Region.Framework.Scenes
1733 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2070 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1734 { 2071 {
1735 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2072 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2073 newPart.SetParent(this);
2074
1736 AddPart(newPart); 2075 AddPart(newPart);
1737 2076
1738 SetPartAsNonRoot(newPart); 2077 SetPartAsNonRoot(newPart);
@@ -1879,11 +2218,11 @@ namespace OpenSim.Region.Framework.Scenes
1879 /// Immediately send a full update for this scene object. 2218 /// Immediately send a full update for this scene object.
1880 /// </summary> 2219 /// </summary>
1881 public void SendGroupFullUpdate() 2220 public void SendGroupFullUpdate()
1882 { 2221 {
1883 if (IsDeleted) 2222 if (IsDeleted)
1884 return; 2223 return;
1885 2224
1886// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2225// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1887 2226
1888 RootPart.SendFullUpdateToAllClients(); 2227 RootPart.SendFullUpdateToAllClients();
1889 2228
@@ -2072,12 +2411,15 @@ namespace OpenSim.Region.Framework.Scenes
2072 part.LinkNum += objectGroup.PrimCount; 2411 part.LinkNum += objectGroup.PrimCount;
2073 } 2412 }
2074 } 2413 }
2414 }
2075 2415
2076 linkPart.LinkNum = 2; 2416 linkPart.LinkNum = 2;
2077 2417
2078 linkPart.SetParent(this); 2418 linkPart.SetParent(this);
2079 linkPart.CreateSelected = true; 2419 linkPart.CreateSelected = true;
2080 2420
2421 lock (m_parts.SyncRoot)
2422 {
2081 //if (linkPart.PhysActor != null) 2423 //if (linkPart.PhysActor != null)
2082 //{ 2424 //{
2083 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2425 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
@@ -2235,6 +2577,8 @@ namespace OpenSim.Region.Framework.Scenes
2235 /// <param name="objectGroup"></param> 2577 /// <param name="objectGroup"></param>
2236 public virtual void DetachFromBackup() 2578 public virtual void DetachFromBackup()
2237 { 2579 {
2580 m_scene.SceneGraph.FireDetachFromBackup(this);
2581
2238 if (m_isBackedUp) 2582 if (m_isBackedUp)
2239 m_scene.EventManager.OnBackup -= ProcessBackup; 2583 m_scene.EventManager.OnBackup -= ProcessBackup;
2240 2584
@@ -2253,7 +2597,8 @@ namespace OpenSim.Region.Framework.Scenes
2253 2597
2254 axPos *= parentRot; 2598 axPos *= parentRot;
2255 part.OffsetPosition = axPos; 2599 part.OffsetPosition = axPos;
2256 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2600 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2601 part.GroupPosition = newPos;
2257 part.OffsetPosition = Vector3.Zero; 2602 part.OffsetPosition = Vector3.Zero;
2258 part.RotationOffset = worldRot; 2603 part.RotationOffset = worldRot;
2259 2604
@@ -2264,7 +2609,7 @@ namespace OpenSim.Region.Framework.Scenes
2264 2609
2265 part.LinkNum = linkNum; 2610 part.LinkNum = linkNum;
2266 2611
2267 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2612 part.OffsetPosition = newPos - AbsolutePosition;
2268 2613
2269 Quaternion rootRotation = m_rootPart.RotationOffset; 2614 Quaternion rootRotation = m_rootPart.RotationOffset;
2270 2615
@@ -2274,7 +2619,7 @@ namespace OpenSim.Region.Framework.Scenes
2274 2619
2275 parentRot = m_rootPart.RotationOffset; 2620 parentRot = m_rootPart.RotationOffset;
2276 oldRot = part.RotationOffset; 2621 oldRot = part.RotationOffset;
2277 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2622 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2278 part.RotationOffset = newRot; 2623 part.RotationOffset = newRot;
2279 } 2624 }
2280 2625
@@ -2525,8 +2870,12 @@ namespace OpenSim.Region.Framework.Scenes
2525 } 2870 }
2526 } 2871 }
2527 2872
2873 RootPart.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2528 for (int i = 0; i < parts.Length; i++) 2874 for (int i = 0; i < parts.Length; i++)
2529 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2875 {
2876 if (parts[i] != RootPart)
2877 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2878 }
2530 } 2879 }
2531 } 2880 }
2532 2881
@@ -2539,6 +2888,17 @@ namespace OpenSim.Region.Framework.Scenes
2539 } 2888 }
2540 } 2889 }
2541 2890
2891
2892
2893 /// <summary>
2894 /// Gets the number of parts
2895 /// </summary>
2896 /// <returns></returns>
2897 public int GetPartCount()
2898 {
2899 return Parts.Count();
2900 }
2901
2542 /// <summary> 2902 /// <summary>
2543 /// Update the texture entry for this part 2903 /// Update the texture entry for this part
2544 /// </summary> 2904 /// </summary>
@@ -2600,11 +2960,9 @@ namespace OpenSim.Region.Framework.Scenes
2600 scale.Y = m_scene.m_maxNonphys; 2960 scale.Y = m_scene.m_maxNonphys;
2601 if (scale.Z > m_scene.m_maxNonphys) 2961 if (scale.Z > m_scene.m_maxNonphys)
2602 scale.Z = m_scene.m_maxNonphys; 2962 scale.Z = m_scene.m_maxNonphys;
2603
2604 SceneObjectPart part = GetChildPart(localID); 2963 SceneObjectPart part = GetChildPart(localID);
2605 if (part != null) 2964 if (part != null)
2606 { 2965 {
2607 part.Resize(scale);
2608 if (part.PhysActor != null) 2966 if (part.PhysActor != null)
2609 { 2967 {
2610 if (part.PhysActor.IsPhysical) 2968 if (part.PhysActor.IsPhysical)
@@ -2619,7 +2977,7 @@ namespace OpenSim.Region.Framework.Scenes
2619 part.PhysActor.Size = scale; 2977 part.PhysActor.Size = scale;
2620 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2978 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2621 } 2979 }
2622 //if (part.UUID != m_rootPart.UUID) 2980 part.Resize(scale);
2623 2981
2624 HasGroupChanged = true; 2982 HasGroupChanged = true;
2625 part.TriggerScriptChangedEvent(Changed.SCALE); 2983 part.TriggerScriptChangedEvent(Changed.SCALE);
@@ -2642,7 +3000,6 @@ namespace OpenSim.Region.Framework.Scenes
2642 SceneObjectPart part = GetChildPart(localID); 3000 SceneObjectPart part = GetChildPart(localID);
2643 if (part != null) 3001 if (part != null)
2644 { 3002 {
2645 part.IgnoreUndoUpdate = true;
2646 if (scale.X > m_scene.m_maxNonphys) 3003 if (scale.X > m_scene.m_maxNonphys)
2647 scale.X = m_scene.m_maxNonphys; 3004 scale.X = m_scene.m_maxNonphys;
2648 if (scale.Y > m_scene.m_maxNonphys) 3005 if (scale.Y > m_scene.m_maxNonphys)
@@ -2679,7 +3036,7 @@ namespace OpenSim.Region.Framework.Scenes
2679 3036
2680 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3037 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2681 { 3038 {
2682 if (oldSize.X * x > m_scene.m_maxPhys) 3039 if (oldSize.X*x > m_scene.m_maxPhys)
2683 { 3040 {
2684 f = m_scene.m_maxPhys / oldSize.X; 3041 f = m_scene.m_maxPhys / oldSize.X;
2685 a = f / x; 3042 a = f / x;
@@ -2687,7 +3044,7 @@ namespace OpenSim.Region.Framework.Scenes
2687 y *= a; 3044 y *= a;
2688 z *= a; 3045 z *= a;
2689 } 3046 }
2690 if (oldSize.Y * y > m_scene.m_maxPhys) 3047 if (oldSize.Y*y > m_scene.m_maxPhys)
2691 { 3048 {
2692 f = m_scene.m_maxPhys / oldSize.Y; 3049 f = m_scene.m_maxPhys / oldSize.Y;
2693 a = f / y; 3050 a = f / y;
@@ -2695,7 +3052,7 @@ namespace OpenSim.Region.Framework.Scenes
2695 y *= a; 3052 y *= a;
2696 z *= a; 3053 z *= a;
2697 } 3054 }
2698 if (oldSize.Z * z > m_scene.m_maxPhys) 3055 if (oldSize.Z*z > m_scene.m_maxPhys)
2699 { 3056 {
2700 f = m_scene.m_maxPhys / oldSize.Z; 3057 f = m_scene.m_maxPhys / oldSize.Z;
2701 a = f / z; 3058 a = f / z;
@@ -2706,7 +3063,7 @@ namespace OpenSim.Region.Framework.Scenes
2706 } 3063 }
2707 else 3064 else
2708 { 3065 {
2709 if (oldSize.X * x > m_scene.m_maxNonphys) 3066 if (oldSize.X*x > m_scene.m_maxNonphys)
2710 { 3067 {
2711 f = m_scene.m_maxNonphys / oldSize.X; 3068 f = m_scene.m_maxNonphys / oldSize.X;
2712 a = f / x; 3069 a = f / x;
@@ -2714,7 +3071,7 @@ namespace OpenSim.Region.Framework.Scenes
2714 y *= a; 3071 y *= a;
2715 z *= a; 3072 z *= a;
2716 } 3073 }
2717 if (oldSize.Y * y > m_scene.m_maxNonphys) 3074 if (oldSize.Y*y > m_scene.m_maxNonphys)
2718 { 3075 {
2719 f = m_scene.m_maxNonphys / oldSize.Y; 3076 f = m_scene.m_maxNonphys / oldSize.Y;
2720 a = f / y; 3077 a = f / y;
@@ -2722,7 +3079,7 @@ namespace OpenSim.Region.Framework.Scenes
2722 y *= a; 3079 y *= a;
2723 z *= a; 3080 z *= a;
2724 } 3081 }
2725 if (oldSize.Z * z > m_scene.m_maxNonphys) 3082 if (oldSize.Z*z > m_scene.m_maxNonphys)
2726 { 3083 {
2727 f = m_scene.m_maxNonphys / oldSize.Z; 3084 f = m_scene.m_maxNonphys / oldSize.Z;
2728 a = f / z; 3085 a = f / z;
@@ -2732,7 +3089,6 @@ namespace OpenSim.Region.Framework.Scenes
2732 } 3089 }
2733 } 3090 }
2734 obPart.IgnoreUndoUpdate = false; 3091 obPart.IgnoreUndoUpdate = false;
2735 obPart.StoreUndoState();
2736 } 3092 }
2737 } 3093 }
2738 } 3094 }
@@ -2740,8 +3096,13 @@ namespace OpenSim.Region.Framework.Scenes
2740 Vector3 prevScale = part.Scale; 3096 Vector3 prevScale = part.Scale;
2741 prevScale.X *= x; 3097 prevScale.X *= x;
2742 prevScale.Y *= y; 3098 prevScale.Y *= y;
2743 prevScale.Z *= z; 3099 prevScale.Z *= z;;
3100
3101 part.IgnoreUndoUpdate = false;
3102 part.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3103 part.IgnoreUndoUpdate = true;
2744 part.Resize(prevScale); 3104 part.Resize(prevScale);
3105 part.IgnoreUndoUpdate = false;
2745 3106
2746 parts = m_parts.GetArray(); 3107 parts = m_parts.GetArray();
2747 for (int i = 0; i < parts.Length; i++) 3108 for (int i = 0; i < parts.Length; i++)
@@ -2750,19 +3111,26 @@ namespace OpenSim.Region.Framework.Scenes
2750 obPart.IgnoreUndoUpdate = true; 3111 obPart.IgnoreUndoUpdate = true;
2751 if (obPart.UUID != m_rootPart.UUID) 3112 if (obPart.UUID != m_rootPart.UUID)
2752 { 3113 {
2753 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3114 if (obPart.UUID != m_rootPart.UUID)
2754 currentpos.X *= x; 3115 {
2755 currentpos.Y *= y; 3116 obPart.IgnoreUndoUpdate = false;
2756 currentpos.Z *= z; 3117 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
2757 Vector3 newSize = new Vector3(obPart.Scale); 3118 obPart.IgnoreUndoUpdate = true;
2758 newSize.X *= x; 3119
2759 newSize.Y *= y; 3120 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2760 newSize.Z *= z; 3121 currentpos.X *= x;
2761 obPart.Resize(newSize); 3122 currentpos.Y *= y;
2762 obPart.UpdateOffSet(currentpos); 3123 currentpos.Z *= z;
3124 Vector3 newSize = new Vector3(obPart.Scale);
3125 newSize.X *= x;
3126 newSize.Y *= y;
3127 newSize.Z *= z;
3128 obPart.Resize(newSize);
3129 obPart.UpdateOffSet(currentpos);
3130 }
3131 obPart.IgnoreUndoUpdate = false;
2763 } 3132 }
2764 obPart.IgnoreUndoUpdate = false; 3133 obPart.IgnoreUndoUpdate = false;
2765 obPart.StoreUndoState();
2766 } 3134 }
2767 3135
2768 if (part.PhysActor != null) 3136 if (part.PhysActor != null)
@@ -2772,7 +3140,6 @@ namespace OpenSim.Region.Framework.Scenes
2772 } 3140 }
2773 3141
2774 part.IgnoreUndoUpdate = false; 3142 part.IgnoreUndoUpdate = false;
2775 part.StoreUndoState();
2776 HasGroupChanged = true; 3143 HasGroupChanged = true;
2777 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE); 3144 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
2778 ScheduleGroupForTerseUpdate(); 3145 ScheduleGroupForTerseUpdate();
@@ -2789,14 +3156,11 @@ namespace OpenSim.Region.Framework.Scenes
2789 /// <param name="pos"></param> 3156 /// <param name="pos"></param>
2790 public void UpdateGroupPosition(Vector3 pos) 3157 public void UpdateGroupPosition(Vector3 pos)
2791 { 3158 {
2792 SceneObjectPart[] parts = m_parts.GetArray();
2793 for (int i = 0; i < parts.Length; i++)
2794 parts[i].StoreUndoState();
2795
2796 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3159 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2797 { 3160 {
2798 if (IsAttachment) 3161 if (IsAttachment)
2799 { 3162 {
3163 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
2800 m_rootPart.AttachedPos = pos; 3164 m_rootPart.AttachedPos = pos;
2801 } 3165 }
2802 if (RootPart.GetStatusSandbox()) 3166 if (RootPart.GetStatusSandbox())
@@ -2830,7 +3194,7 @@ namespace OpenSim.Region.Framework.Scenes
2830 3194
2831 SceneObjectPart[] parts = m_parts.GetArray(); 3195 SceneObjectPart[] parts = m_parts.GetArray();
2832 for (int i = 0; i < parts.Length; i++) 3196 for (int i = 0; i < parts.Length; i++)
2833 parts[i].StoreUndoState(); 3197 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2834 3198
2835 if (part != null) 3199 if (part != null)
2836 { 3200 {
@@ -2855,7 +3219,7 @@ namespace OpenSim.Region.Framework.Scenes
2855 { 3219 {
2856 SceneObjectPart[] parts = m_parts.GetArray(); 3220 SceneObjectPart[] parts = m_parts.GetArray();
2857 for (int i = 0; i < parts.Length; i++) 3221 for (int i = 0; i < parts.Length; i++)
2858 parts[i].StoreUndoState(); 3222 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2859 3223
2860 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3224 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2861 Vector3 oldPos = 3225 Vector3 oldPos =
@@ -2876,10 +3240,27 @@ namespace OpenSim.Region.Framework.Scenes
2876 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3240 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2877 } 3241 }
2878 3242
2879 AbsolutePosition = newPos; 3243 //We have to set undoing here because otherwise an undo state will be saved
3244 if (!m_rootPart.Undoing)
3245 {
3246 m_rootPart.Undoing = true;
3247 AbsolutePosition = newPos;
3248 m_rootPart.Undoing = false;
3249 }
3250 else
3251 {
3252 AbsolutePosition = newPos;
3253 }
2880 3254
2881 HasGroupChanged = true; 3255 HasGroupChanged = true;
2882 ScheduleGroupForTerseUpdate(); 3256 if (m_rootPart.Undoing)
3257 {
3258 ScheduleGroupForFullUpdate();
3259 }
3260 else
3261 {
3262 ScheduleGroupForTerseUpdate();
3263 }
2883 } 3264 }
2884 3265
2885 public void OffsetForNewRegion(Vector3 offset) 3266 public void OffsetForNewRegion(Vector3 offset)
@@ -2899,7 +3280,7 @@ namespace OpenSim.Region.Framework.Scenes
2899 { 3280 {
2900 SceneObjectPart[] parts = m_parts.GetArray(); 3281 SceneObjectPart[] parts = m_parts.GetArray();
2901 for (int i = 0; i < parts.Length; i++) 3282 for (int i = 0; i < parts.Length; i++)
2902 parts[i].StoreUndoState(); 3283 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2903 3284
2904 m_rootPart.UpdateRotation(rot); 3285 m_rootPart.UpdateRotation(rot);
2905 3286
@@ -2923,7 +3304,7 @@ namespace OpenSim.Region.Framework.Scenes
2923 { 3304 {
2924 SceneObjectPart[] parts = m_parts.GetArray(); 3305 SceneObjectPart[] parts = m_parts.GetArray();
2925 for (int i = 0; i < parts.Length; i++) 3306 for (int i = 0; i < parts.Length; i++)
2926 parts[i].StoreUndoState(); 3307 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2927 3308
2928 m_rootPart.UpdateRotation(rot); 3309 m_rootPart.UpdateRotation(rot);
2929 3310
@@ -2948,10 +3329,9 @@ namespace OpenSim.Region.Framework.Scenes
2948 public void UpdateSingleRotation(Quaternion rot, uint localID) 3329 public void UpdateSingleRotation(Quaternion rot, uint localID)
2949 { 3330 {
2950 SceneObjectPart part = GetChildPart(localID); 3331 SceneObjectPart part = GetChildPart(localID);
2951
2952 SceneObjectPart[] parts = m_parts.GetArray(); 3332 SceneObjectPart[] parts = m_parts.GetArray();
2953 for (int i = 0; i < parts.Length; i++) 3333 for (int i = 0; i < parts.Length; i++)
2954 parts[i].StoreUndoState(); 3334 parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2955 3335
2956 if (part != null) 3336 if (part != null)
2957 { 3337 {
@@ -2979,15 +3359,24 @@ namespace OpenSim.Region.Framework.Scenes
2979 if (part.UUID == m_rootPart.UUID) 3359 if (part.UUID == m_rootPart.UUID)
2980 { 3360 {
2981 UpdateRootRotation(rot); 3361 UpdateRootRotation(rot);
2982 AbsolutePosition = pos; 3362 if (!m_rootPart.Undoing)
3363 {
3364 m_rootPart.Undoing = true;
3365 AbsolutePosition = pos;
3366 m_rootPart.Undoing = false;
3367 }
3368 else
3369 {
3370 AbsolutePosition = pos;
3371 }
2983 } 3372 }
2984 else 3373 else
2985 { 3374 {
3375 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2986 part.IgnoreUndoUpdate = true; 3376 part.IgnoreUndoUpdate = true;
2987 part.UpdateRotation(rot); 3377 part.UpdateRotation(rot);
2988 part.OffsetPosition = pos; 3378 part.OffsetPosition = pos;
2989 part.IgnoreUndoUpdate = false; 3379 part.IgnoreUndoUpdate = false;
2990 part.StoreUndoState();
2991 } 3380 }
2992 } 3381 }
2993 } 3382 }
@@ -3001,8 +3390,16 @@ namespace OpenSim.Region.Framework.Scenes
3001 Quaternion axRot = rot; 3390 Quaternion axRot = rot;
3002 Quaternion oldParentRot = m_rootPart.RotationOffset; 3391 Quaternion oldParentRot = m_rootPart.RotationOffset;
3003 3392
3004 m_rootPart.StoreUndoState(); 3393 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3005 m_rootPart.UpdateRotation(rot); 3394 bool cancelUndo = false;
3395 if (!m_rootPart.Undoing)
3396 {
3397 m_rootPart.Undoing = true;
3398 cancelUndo = true;
3399 }
3400
3401 //Don't use UpdateRotation because it schedules an update prematurely
3402 m_rootPart.RotationOffset = rot;
3006 if (m_rootPart.PhysActor != null) 3403 if (m_rootPart.PhysActor != null)
3007 { 3404 {
3008 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3405 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -3017,28 +3414,22 @@ namespace OpenSim.Region.Framework.Scenes
3017 { 3414 {
3018 prim.IgnoreUndoUpdate = true; 3415 prim.IgnoreUndoUpdate = true;
3019 Vector3 axPos = prim.OffsetPosition; 3416 Vector3 axPos = prim.OffsetPosition;
3417
3020 axPos *= oldParentRot; 3418 axPos *= oldParentRot;
3021 axPos *= Quaternion.Inverse(axRot); 3419 axPos *= Quaternion.Inverse(axRot);
3022 prim.OffsetPosition = axPos; 3420 prim.OffsetPosition = axPos;
3023 Quaternion primsRot = prim.RotationOffset; 3421
3024 Quaternion newRot = primsRot * oldParentRot; 3422 prim.RotationOffset *= Quaternion.Inverse(prim.GetWorldRotation()) * (oldParentRot * prim.RotationOffset);
3025 newRot *= Quaternion.Inverse(axRot); 3423
3026 prim.RotationOffset = newRot; 3424 prim.IgnoreUndoUpdate = false;
3027 prim.ScheduleTerseUpdate();
3028 } 3425 }
3029 } 3426 }
3030 3427 if (cancelUndo == true)
3031 for (int i = 0; i < parts.Length; i++)
3032 { 3428 {
3033 SceneObjectPart childpart = parts[i]; 3429 m_rootPart.Undoing = false;
3034 if (childpart != m_rootPart)
3035 {
3036 childpart.IgnoreUndoUpdate = false;
3037 childpart.StoreUndoState();
3038 }
3039 } 3430 }
3040 3431 HasGroupChanged = true;
3041 m_rootPart.ScheduleTerseUpdate(); 3432 ScheduleGroupForFullUpdate();
3042 } 3433 }
3043 3434
3044 #endregion 3435 #endregion
@@ -3261,7 +3652,6 @@ namespace OpenSim.Region.Framework.Scenes
3261 public float GetMass() 3652 public float GetMass()
3262 { 3653 {
3263 float retmass = 0f; 3654 float retmass = 0f;
3264
3265 SceneObjectPart[] parts = m_parts.GetArray(); 3655 SceneObjectPart[] parts = m_parts.GetArray();
3266 for (int i = 0; i < parts.Length; i++) 3656 for (int i = 0; i < parts.Length; i++)
3267 retmass += parts[i].GetMass(); 3657 retmass += parts[i].GetMass();
@@ -3377,6 +3767,14 @@ namespace OpenSim.Region.Framework.Scenes
3377 SetFromItemID(uuid); 3767 SetFromItemID(uuid);
3378 } 3768 }
3379 3769
3770 public void ResetOwnerChangeFlag()
3771 {
3772 ForEachPart(delegate(SceneObjectPart part)
3773 {
3774 part.ResetOwnerChangeFlag();
3775 });
3776 }
3777
3380 #endregion 3778 #endregion
3381 } 3779 }
3382} 3780}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 4d5eedf..9b9f280 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; }
@@ -718,9 +730,11 @@ namespace OpenSim.Region.Framework.Scenes
718 { 730 {
719 // If this is a linkset, we don't want the physics engine mucking up our group position here. 731 // If this is a linkset, we don't want the physics engine mucking up our group position here.
720 PhysicsActor actor = PhysActor; 732 PhysicsActor actor = PhysActor;
721 if (actor != null && _parentID == 0) 733 if (_parentID == 0)
722 { 734 {
723 m_groupPosition = actor.Position; 735 if (actor != null)
736 m_groupPosition = actor.Position;
737 return m_groupPosition;
724 } 738 }
725 739
726 if (IsAttachment) 740 if (IsAttachment)
@@ -730,12 +744,14 @@ namespace OpenSim.Region.Framework.Scenes
730 return sp.AbsolutePosition; 744 return sp.AbsolutePosition;
731 } 745 }
732 746
747 // use root prim's group position. Physics may have updated it
748 if (ParentGroup.RootPart != this)
749 m_groupPosition = ParentGroup.RootPart.GroupPosition;
733 return m_groupPosition; 750 return m_groupPosition;
734 } 751 }
735 set 752 set
736 { 753 {
737 m_groupPosition = value; 754 m_groupPosition = value;
738
739 PhysicsActor actor = PhysActor; 755 PhysicsActor actor = PhysActor;
740 if (actor != null) 756 if (actor != null)
741 { 757 {
@@ -755,25 +771,13 @@ namespace OpenSim.Region.Framework.Scenes
755 771
756 // Tell the physics engines that this prim changed. 772 // Tell the physics engines that this prim changed.
757 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 773 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
774
758 } 775 }
759 catch (Exception e) 776 catch (Exception e)
760 { 777 {
761 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 778 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
762 } 779 }
763 } 780 }
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 } 781 }
778 } 782 }
779 783
@@ -782,7 +786,8 @@ namespace OpenSim.Region.Framework.Scenes
782 get { return m_offsetPosition; } 786 get { return m_offsetPosition; }
783 set 787 set
784 { 788 {
785 StoreUndoState(); 789 Vector3 oldpos = m_offsetPosition;
790 StoreUndoState(UndoType.STATE_PRIM_POSITION);
786 m_offsetPosition = value; 791 m_offsetPosition = value;
787 792
788 if (ParentGroup != null && !ParentGroup.IsDeleted) 793 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -796,7 +801,22 @@ namespace OpenSim.Region.Framework.Scenes
796 // Tell the physics engines that this prim changed. 801 // Tell the physics engines that this prim changed.
797 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 802 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
798 } 803 }
804
805 if (!m_parentGroup.m_dupeInProgress)
806 {
807 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
808 foreach (ScenePresence av in avs)
809 {
810 if (av.LinkedPrim == m_uuid)
811 {
812 Vector3 offset = (m_offsetPosition - oldpos);
813 av.OffsetPosition += offset;
814 av.SendAvatarDataToAllAgents();
815 }
816 }
817 }
799 } 818 }
819 TriggerScriptChangedEvent(Changed.POSITION);
800 } 820 }
801 } 821 }
802 822
@@ -838,7 +858,7 @@ namespace OpenSim.Region.Framework.Scenes
838 858
839 set 859 set
840 { 860 {
841 StoreUndoState(); 861 StoreUndoState(UndoType.STATE_PRIM_ROTATION);
842 m_rotationOffset = value; 862 m_rotationOffset = value;
843 863
844 PhysicsActor actor = PhysActor; 864 PhysicsActor actor = PhysActor;
@@ -922,7 +942,16 @@ namespace OpenSim.Region.Framework.Scenes
922 /// <summary></summary> 942 /// <summary></summary>
923 public Vector3 Acceleration 943 public Vector3 Acceleration
924 { 944 {
925 get { return m_acceleration; } 945 get
946 {
947 PhysicsActor actor = PhysActor;
948 if (actor != null)
949 {
950 m_acceleration = actor.Acceleration;
951 }
952 return m_acceleration;
953 }
954
926 set { m_acceleration = value; } 955 set { m_acceleration = value; }
927 } 956 }
928 957
@@ -1013,7 +1042,7 @@ namespace OpenSim.Region.Framework.Scenes
1013 get { return m_shape.Scale; } 1042 get { return m_shape.Scale; }
1014 set 1043 set
1015 { 1044 {
1016 StoreUndoState(); 1045 StoreUndoState(UndoType.STATE_PRIM_SCALE);
1017 if (m_shape != null) 1046 if (m_shape != null)
1018 { 1047 {
1019 m_shape.Scale = value; 1048 m_shape.Scale = value;
@@ -1079,11 +1108,10 @@ namespace OpenSim.Region.Framework.Scenes
1079 1108
1080 public Vector3 AbsolutePosition 1109 public Vector3 AbsolutePosition
1081 { 1110 {
1082 get { 1111 get
1083 if (IsAttachment) 1112 {
1084 return GroupPosition; 1113 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1085 1114 }
1086 return m_offsetPosition + m_groupPosition; }
1087 } 1115 }
1088 1116
1089 public SceneObjectGroup ParentGroup 1117 public SceneObjectGroup ParentGroup
@@ -1242,6 +1270,13 @@ namespace OpenSim.Region.Framework.Scenes
1242 _flags = value; 1270 _flags = value;
1243 } 1271 }
1244 } 1272 }
1273
1274 [XmlIgnore]
1275 public bool IsOccupied // KF If an av is sittingon this prim
1276 {
1277 get { return m_occupied; }
1278 set { m_occupied = value; }
1279 }
1245 1280
1246 1281
1247 public UUID SitTargetAvatar 1282 public UUID SitTargetAvatar
@@ -1317,14 +1352,6 @@ namespace OpenSim.Region.Framework.Scenes
1317 } 1352 }
1318 } 1353 }
1319 1354
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) 1355 private void SendObjectPropertiesToClient(UUID AgentID)
1329 { 1356 {
1330 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1357 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1575,14 +1602,22 @@ namespace OpenSim.Region.Framework.Scenes
1575 // or flexible 1602 // or flexible
1576 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible)) 1603 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible))
1577 { 1604 {
1578 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( 1605 try
1579 string.Format("{0}/{1}", Name, UUID), 1606 {
1580 Shape, 1607 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
1581 AbsolutePosition, 1608 string.Format("{0}/{1}", Name, UUID),
1582 Scale, 1609 Shape,
1583 RotationOffset, 1610 AbsolutePosition,
1584 RigidBody); 1611 Scale,
1585 1612 RotationOffset,
1613 RigidBody);
1614 PhysActor.SetMaterial(Material);
1615 }
1616 catch
1617 {
1618 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid);
1619 PhysActor = null;
1620 }
1586 // Basic Physics returns null.. joy joy joy. 1621 // Basic Physics returns null.. joy joy joy.
1587 if (PhysActor != null) 1622 if (PhysActor != null)
1588 { 1623 {
@@ -1610,7 +1645,7 @@ namespace OpenSim.Region.Framework.Scenes
1610 { 1645 {
1611 m_redo.Clear(); 1646 m_redo.Clear();
1612 } 1647 }
1613 StoreUndoState(); 1648 StoreUndoState(UndoType.STATE_ALL);
1614 } 1649 }
1615 1650
1616 public byte ConvertScriptUintToByte(uint indata) 1651 public byte ConvertScriptUintToByte(uint indata)
@@ -1679,6 +1714,9 @@ namespace OpenSim.Region.Framework.Scenes
1679 1714
1680 // Move afterwards ResetIDs as it clears the localID 1715 // Move afterwards ResetIDs as it clears the localID
1681 dupe.LocalId = localID; 1716 dupe.LocalId = localID;
1717 if(dupe.PhysActor != null)
1718 dupe.PhysActor.LocalID = localID;
1719
1682 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1720 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1683 dupe._lastOwnerID = OwnerID; 1721 dupe._lastOwnerID = OwnerID;
1684 1722
@@ -1722,7 +1760,7 @@ namespace OpenSim.Region.Framework.Scenes
1722 PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); 1760 PrimitiveBaseShape shape = PrimitiveBaseShape.Create();
1723 part.Shape = shape; 1761 part.Shape = shape;
1724 1762
1725 part.Name = "Primitive"; 1763 part.Name = "Object";
1726 part._ownerID = UUID.Random(); 1764 part._ownerID = UUID.Random();
1727 1765
1728 return part; 1766 return part;
@@ -2083,12 +2121,17 @@ namespace OpenSim.Region.Framework.Scenes
2083 public Vector3 GetWorldPosition() 2121 public Vector3 GetWorldPosition()
2084 { 2122 {
2085 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2123 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
2086
2087 Vector3 axPos = OffsetPosition; 2124 Vector3 axPos = OffsetPosition;
2088
2089 axPos *= parentRot; 2125 axPos *= parentRot;
2090 Vector3 translationOffsetPosition = axPos; 2126 Vector3 translationOffsetPosition = axPos;
2091 return GroupPosition + translationOffsetPosition; 2127 if(_parentID == 0)
2128 {
2129 return GroupPosition;
2130 }
2131 else
2132 {
2133 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
2134 }
2092 } 2135 }
2093 2136
2094 /// <summary> 2137 /// <summary>
@@ -2745,17 +2788,18 @@ namespace OpenSim.Region.Framework.Scenes
2745 //Trys to fetch sound id from prim's inventory. 2788 //Trys to fetch sound id from prim's inventory.
2746 //Prim's inventory doesn't support non script items yet 2789 //Prim's inventory doesn't support non script items yet
2747 2790
2748 lock (TaskInventory) 2791 TaskInventory.LockItemsForRead(true);
2792
2793 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2749 { 2794 {
2750 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2795 if (item.Value.Name == sound)
2751 { 2796 {
2752 if (item.Value.Name == sound) 2797 soundID = item.Value.ItemID;
2753 { 2798 break;
2754 soundID = item.Value.ItemID;
2755 break;
2756 }
2757 } 2799 }
2758 } 2800 }
2801
2802 TaskInventory.LockItemsForRead(false);
2759 } 2803 }
2760 2804
2761 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2805 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2815,7 +2859,7 @@ namespace OpenSim.Region.Framework.Scenes
2815 /// <param name="scale"></param> 2859 /// <param name="scale"></param>
2816 public void Resize(Vector3 scale) 2860 public void Resize(Vector3 scale)
2817 { 2861 {
2818 StoreUndoState(); 2862 StoreUndoState(UndoType.STATE_PRIM_SCALE);
2819 m_shape.Scale = scale; 2863 m_shape.Scale = scale;
2820 2864
2821 ParentGroup.HasGroupChanged = true; 2865 ParentGroup.HasGroupChanged = true;
@@ -2824,38 +2868,7 @@ namespace OpenSim.Region.Framework.Scenes
2824 2868
2825 public void RotLookAt(Quaternion target, float strength, float damping) 2869 public void RotLookAt(Quaternion target, float strength, float damping)
2826 { 2870 {
2827 rotLookAt(target, strength, damping); 2871 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2828 }
2829
2830 public void rotLookAt(Quaternion target, float strength, float damping)
2831 {
2832 if (IsAttachment)
2833 {
2834 /*
2835 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2836 if (avatar != null)
2837 {
2838 Rotate the Av?
2839 } */
2840 }
2841 else
2842 {
2843 APIDDamp = damping;
2844 APIDStrength = strength;
2845 APIDTarget = target;
2846 }
2847 }
2848
2849 public void startLookAt(Quaternion rot, float damp, float strength)
2850 {
2851 APIDDamp = damp;
2852 APIDStrength = strength;
2853 APIDTarget = rot;
2854 }
2855
2856 public void stopLookAt()
2857 {
2858 APIDTarget = Quaternion.Identity;
2859 } 2872 }
2860 2873
2861 /// <summary> 2874 /// <summary>
@@ -2867,7 +2880,10 @@ namespace OpenSim.Region.Framework.Scenes
2867 2880
2868 if (m_parentGroup != null) 2881 if (m_parentGroup != null)
2869 { 2882 {
2870 m_parentGroup.QueueForUpdateCheck(); 2883 if (!m_parentGroup.areUpdatesSuspended)
2884 {
2885 m_parentGroup.QueueForUpdateCheck();
2886 }
2871 } 2887 }
2872 2888
2873 int timeNow = Util.UnixTimeSinceEpoch(); 2889 int timeNow = Util.UnixTimeSinceEpoch();
@@ -3084,8 +3100,8 @@ namespace OpenSim.Region.Framework.Scenes
3084 { 3100 {
3085 const float ROTATION_TOLERANCE = 0.01f; 3101 const float ROTATION_TOLERANCE = 0.01f;
3086 const float VELOCITY_TOLERANCE = 0.001f; 3102 const float VELOCITY_TOLERANCE = 0.001f;
3087 const float POSITION_TOLERANCE = 0.05f; 3103 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
3088 const int TIME_MS_TOLERANCE = 3000; 3104 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
3089 3105
3090 if (m_updateFlag == 1) 3106 if (m_updateFlag == 1)
3091 { 3107 {
@@ -3099,7 +3115,7 @@ namespace OpenSim.Region.Framework.Scenes
3099 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3115 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
3100 { 3116 {
3101 AddTerseUpdateToAllAvatars(); 3117 AddTerseUpdateToAllAvatars();
3102 ClearUpdateSchedule(); 3118
3103 3119
3104 // This causes the Scene to 'poll' physical objects every couple of frames 3120 // This causes the Scene to 'poll' physical objects every couple of frames
3105 // bad, so it's been replaced by an event driven method. 3121 // bad, so it's been replaced by an event driven method.
@@ -3117,16 +3133,18 @@ namespace OpenSim.Region.Framework.Scenes
3117 m_lastAngularVelocity = AngularVelocity; 3133 m_lastAngularVelocity = AngularVelocity;
3118 m_lastTerseSent = Environment.TickCount; 3134 m_lastTerseSent = Environment.TickCount;
3119 } 3135 }
3136 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
3137 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
3120 } 3138 }
3121 else 3139 else
3122 { 3140 {
3123 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 3141 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3124 { 3142 {
3125 AddFullUpdateToAllAvatars(); 3143 AddFullUpdateToAllAvatars();
3126 ClearUpdateSchedule(); 3144 m_updateFlag = 0; //Same here
3127 } 3145 }
3128 } 3146 }
3129 ClearUpdateSchedule(); 3147 m_updateFlag = 0;
3130 } 3148 }
3131 3149
3132 /// <summary> 3150 /// <summary>
@@ -3154,17 +3172,16 @@ namespace OpenSim.Region.Framework.Scenes
3154 if (!UUID.TryParse(sound, out soundID)) 3172 if (!UUID.TryParse(sound, out soundID))
3155 { 3173 {
3156 // search sound file from inventory 3174 // search sound file from inventory
3157 lock (TaskInventory) 3175 TaskInventory.LockItemsForRead(true);
3176 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3158 { 3177 {
3159 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3178 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3160 { 3179 {
3161 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3180 soundID = item.Value.ItemID;
3162 { 3181 break;
3163 soundID = item.Value.ItemID;
3164 break;
3165 }
3166 } 3182 }
3167 } 3183 }
3184 TaskInventory.LockItemsForRead(false);
3168 } 3185 }
3169 3186
3170 if (soundID == UUID.Zero) 3187 if (soundID == UUID.Zero)
@@ -3594,7 +3611,7 @@ namespace OpenSim.Region.Framework.Scenes
3594 3611
3595 public void StopLookAt() 3612 public void StopLookAt()
3596 { 3613 {
3597 m_parentGroup.stopLookAt(); 3614 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3598 3615
3599 m_parentGroup.ScheduleGroupForTerseUpdate(); 3616 m_parentGroup.ScheduleGroupForTerseUpdate();
3600 } 3617 }
@@ -3621,10 +3638,9 @@ namespace OpenSim.Region.Framework.Scenes
3621 m_parentGroup.ScheduleGroupForTerseUpdate(); 3638 m_parentGroup.ScheduleGroupForTerseUpdate();
3622 //m_parentGroup.ScheduleGroupForFullUpdate(); 3639 //m_parentGroup.ScheduleGroupForFullUpdate();
3623 } 3640 }
3624 3641 public void StoreUndoState(UndoType type)
3625 public void StoreUndoState()
3626 { 3642 {
3627 if (!Undoing) 3643 if (!Undoing && (m_parentGroup == null || m_parentGroup.RootPart == null || !m_parentGroup.RootPart.Undoing))
3628 { 3644 {
3629 if (!IgnoreUndoUpdate) 3645 if (!IgnoreUndoUpdate)
3630 { 3646 {
@@ -3635,17 +3651,25 @@ namespace OpenSim.Region.Framework.Scenes
3635 if (m_undo.Count > 0) 3651 if (m_undo.Count > 0)
3636 { 3652 {
3637 UndoState last = m_undo.Peek(); 3653 UndoState last = m_undo.Peek();
3638 if (last != null) 3654
3639 {
3640 if (last.Compare(this))
3641 return;
3642 }
3643 } 3655 }
3644 3656
3645 if (m_parentGroup.GetSceneMaxUndo() > 0) 3657 if (m_parentGroup.GetSceneMaxUndo() > 0)
3646 { 3658 {
3647 UndoState nUndo = new UndoState(this); 3659 UndoState lastUndo = m_undo.Peek();
3648 3660
3661 UndoState nUndo = new UndoState(this, type);
3662
3663 if (lastUndo != null)
3664 {
3665 TimeSpan ts = DateTime.Now.Subtract(lastUndo.LastUpdated);
3666 if (ts.TotalMilliseconds < 500)
3667 {
3668 //Delete the last entry since it was less than 500 milliseconds ago
3669 nUndo.Merge(lastUndo);
3670 m_undo.Pop();
3671 }
3672 }
3649 m_undo.Push(nUndo); 3673 m_undo.Push(nUndo);
3650 } 3674 }
3651 3675
@@ -4122,11 +4146,13 @@ namespace OpenSim.Region.Framework.Scenes
4122 if (m_undo.Count > 0) 4146 if (m_undo.Count > 0)
4123 { 4147 {
4124 UndoState nUndo = null; 4148 UndoState nUndo = null;
4149 UndoState goback = m_undo.Pop();
4125 if (m_parentGroup.GetSceneMaxUndo() > 0) 4150 if (m_parentGroup.GetSceneMaxUndo() > 0)
4126 { 4151 {
4127 nUndo = new UndoState(this); 4152 nUndo = new UndoState(this, goback.Type);
4128 } 4153 }
4129 UndoState goback = m_undo.Pop(); 4154
4155
4130 if (goback != null) 4156 if (goback != null)
4131 { 4157 {
4132 goback.PlaybackState(this); 4158 goback.PlaybackState(this);
@@ -4141,13 +4167,13 @@ namespace OpenSim.Region.Framework.Scenes
4141 { 4167 {
4142 lock (m_redo) 4168 lock (m_redo)
4143 { 4169 {
4170 UndoState gofwd = m_redo.Pop();
4144 if (m_parentGroup.GetSceneMaxUndo() > 0) 4171 if (m_parentGroup.GetSceneMaxUndo() > 0)
4145 { 4172 {
4146 UndoState nUndo = new UndoState(this); 4173 UndoState nUndo = new UndoState(this, gofwd.Type);
4147 4174
4148 m_undo.Push(nUndo); 4175 m_undo.Push(nUndo);
4149 } 4176 }
4150 UndoState gofwd = m_redo.Pop();
4151 if (gofwd != null) 4177 if (gofwd != null)
4152 gofwd.PlayfwdState(this); 4178 gofwd.PlayfwdState(this);
4153 } 4179 }
@@ -4411,6 +4437,7 @@ namespace OpenSim.Region.Framework.Scenes
4411 Scale, 4437 Scale,
4412 RotationOffset, 4438 RotationOffset,
4413 UsePhysics); 4439 UsePhysics);
4440 PhysActor.SetMaterial(Material);
4414 4441
4415 pa = PhysActor; 4442 pa = PhysActor;
4416 if (pa != null) 4443 if (pa != null)
@@ -4596,8 +4623,9 @@ namespace OpenSim.Region.Framework.Scenes
4596 { 4623 {
4597 m_shape.TextureEntry = textureEntry; 4624 m_shape.TextureEntry = textureEntry;
4598 TriggerScriptChangedEvent(Changed.TEXTURE); 4625 TriggerScriptChangedEvent(Changed.TEXTURE);
4599 4626 m_updateFlag = 1;
4600 ParentGroup.HasGroupChanged = true; 4627 ParentGroup.HasGroupChanged = true;
4628
4601 //This is madness.. 4629 //This is madness..
4602 //ParentGroup.ScheduleGroupForFullUpdate(); 4630 //ParentGroup.ScheduleGroupForFullUpdate();
4603 //This is sparta 4631 //This is sparta
@@ -4830,5 +4858,17 @@ namespace OpenSim.Region.Framework.Scenes
4830 Color color = Color; 4858 Color color = Color;
4831 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4859 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4832 } 4860 }
4861
4862 public void ResetOwnerChangeFlag()
4863 {
4864 List<UUID> inv = Inventory.GetInventoryList();
4865
4866 foreach (UUID itemID in inv)
4867 {
4868 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4869 item.OwnerChanged = false;
4870 Inventory.UpdateInventoryItem(item, false, false);
4871 }
4872 }
4833 } 4873 }
4834} 4874}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 3281eab..1992956 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -48,6 +48,9 @@ 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 private bool m_inventoryPrivileged = false;
52
53 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
51 54
52 /// <value> 55 /// <value>
53 /// The part to which the inventory belongs. 56 /// The part to which the inventory belongs.
@@ -84,11 +87,14 @@ namespace OpenSim.Region.Framework.Scenes
84 /// </value> 87 /// </value>
85 protected internal TaskInventoryDictionary Items 88 protected internal TaskInventoryDictionary Items
86 { 89 {
87 get { return m_items; } 90 get {
91 return m_items;
92 }
88 set 93 set
89 { 94 {
90 m_items = value; 95 m_items = value;
91 m_inventorySerial++; 96 m_inventorySerial++;
97 QueryScriptStates();
92 } 98 }
93 } 99 }
94 100
@@ -120,39 +126,45 @@ namespace OpenSim.Region.Framework.Scenes
120 /// <param name="linkNum">Link number for the part</param> 126 /// <param name="linkNum">Link number for the part</param>
121 public void ResetInventoryIDs() 127 public void ResetInventoryIDs()
122 { 128 {
123 if (null == m_part || null == m_part.ParentGroup) 129 m_items.LockItemsForWrite(true);
124 return; 130
125 131 if (Items.Count == 0)
126 lock (m_items)
127 { 132 {
128 if (0 == m_items.Count) 133 m_items.LockItemsForWrite(false);
129 return; 134 return;
135 }
130 136
131 IList<TaskInventoryItem> items = GetInventoryItems(); 137 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
132 m_items.Clear(); 138 Items.Clear();
133 139
134 foreach (TaskInventoryItem item in items) 140 foreach (TaskInventoryItem item in items)
135 { 141 {
136 item.ResetIDs(m_part.UUID); 142 item.ResetIDs(m_part.UUID);
137 m_items.Add(item.ItemID, item); 143 Items.Add(item.ItemID, item);
138 }
139 } 144 }
145 m_items.LockItemsForWrite(false);
140 } 146 }
141 147
142 public void ResetObjectID() 148 public void ResetObjectID()
143 { 149 {
144 lock (Items) 150 m_items.LockItemsForWrite(true);
151
152 if (Items.Count == 0)
145 { 153 {
146 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 154 m_items.LockItemsForWrite(false);
147 Items.Clear(); 155 return;
148
149 foreach (TaskInventoryItem item in items)
150 {
151 item.ParentPartID = m_part.UUID;
152 item.ParentID = m_part.UUID;
153 Items.Add(item.ItemID, item);
154 }
155 } 156 }
157
158 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
159 Items.Clear();
160
161 foreach (TaskInventoryItem item in items)
162 {
163 item.ParentPartID = m_part.UUID;
164 item.ParentID = m_part.UUID;
165 Items.Add(item.ItemID, item);
166 }
167 m_items.LockItemsForWrite(false);
156 } 168 }
157 169
158 /// <summary> 170 /// <summary>
@@ -161,12 +173,11 @@ namespace OpenSim.Region.Framework.Scenes
161 /// <param name="ownerId"></param> 173 /// <param name="ownerId"></param>
162 public void ChangeInventoryOwner(UUID ownerId) 174 public void ChangeInventoryOwner(UUID ownerId)
163 { 175 {
164 lock (Items) 176 m_items.LockItemsForWrite(true);
177 if (0 == Items.Count)
165 { 178 {
166 if (0 == Items.Count) 179 m_items.LockItemsForWrite(false);
167 { 180 return;
168 return;
169 }
170 } 181 }
171 182
172 HasInventoryChanged = true; 183 HasInventoryChanged = true;
@@ -182,6 +193,7 @@ namespace OpenSim.Region.Framework.Scenes
182 item.PermsGranter = UUID.Zero; 193 item.PermsGranter = UUID.Zero;
183 item.OwnerChanged = true; 194 item.OwnerChanged = true;
184 } 195 }
196 m_items.LockItemsForWrite(false);
185 } 197 }
186 198
187 /// <summary> 199 /// <summary>
@@ -190,12 +202,11 @@ namespace OpenSim.Region.Framework.Scenes
190 /// <param name="groupID"></param> 202 /// <param name="groupID"></param>
191 public void ChangeInventoryGroup(UUID groupID) 203 public void ChangeInventoryGroup(UUID groupID)
192 { 204 {
193 lock (Items) 205 m_items.LockItemsForWrite(true);
206 if (0 == Items.Count)
194 { 207 {
195 if (0 == Items.Count) 208 m_items.LockItemsForWrite(false);
196 { 209 return;
197 return;
198 }
199 } 210 }
200 211
201 // Don't let this set the HasGroupChanged flag for attachments 212 // Don't let this set the HasGroupChanged flag for attachments
@@ -207,12 +218,45 @@ namespace OpenSim.Region.Framework.Scenes
207 m_part.ParentGroup.HasGroupChanged = true; 218 m_part.ParentGroup.HasGroupChanged = true;
208 } 219 }
209 220
210 List<TaskInventoryItem> items = GetInventoryItems(); 221 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
211 foreach (TaskInventoryItem item in items) 222 foreach (TaskInventoryItem item in items)
212 { 223 {
213 if (groupID != item.GroupID) 224 if (groupID != item.GroupID)
225 {
214 item.GroupID = groupID; 226 item.GroupID = groupID;
227 }
215 } 228 }
229 m_items.LockItemsForWrite(false);
230 }
231
232 private void QueryScriptStates()
233 {
234 if (m_part == null || m_part.ParentGroup == null)
235 return;
236
237 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
238 if (engines == null) // No engine at all
239 return;
240
241 Items.LockItemsForRead(true);
242 foreach (TaskInventoryItem item in Items.Values)
243 {
244 if (item.InvType == (int)InventoryType.LSL)
245 {
246 foreach (IScriptModule e in engines)
247 {
248 bool running;
249
250 if (e.HasScript(item.ItemID, out running))
251 {
252 item.ScriptRunning = running;
253 break;
254 }
255 }
256 }
257 }
258
259 Items.LockItemsForRead(false);
216 } 260 }
217 261
218 /// <summary> 262 /// <summary>
@@ -220,9 +264,14 @@ namespace OpenSim.Region.Framework.Scenes
220 /// </summary> 264 /// </summary>
221 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 265 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
222 { 266 {
223 List<TaskInventoryItem> scripts = GetInventoryScripts(); 267 Items.LockItemsForRead(true);
224 foreach (TaskInventoryItem item in scripts) 268 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
225 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 269 Items.LockItemsForRead(false);
270 foreach (TaskInventoryItem item in items)
271 {
272 if ((int)InventoryType.LSL == item.InvType)
273 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
274 }
226 } 275 }
227 276
228 public ArrayList GetScriptErrors(UUID itemID) 277 public ArrayList GetScriptErrors(UUID itemID)
@@ -255,9 +304,18 @@ namespace OpenSim.Region.Framework.Scenes
255 /// </param> 304 /// </param>
256 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 305 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
257 { 306 {
258 List<TaskInventoryItem> scripts = GetInventoryScripts(); 307 Items.LockItemsForRead(true);
259 foreach (TaskInventoryItem item in scripts) 308 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
260 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 309 Items.LockItemsForRead(false);
310
311 foreach (TaskInventoryItem item in items)
312 {
313 if ((int)InventoryType.LSL == item.InvType)
314 {
315 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
316 m_part.RemoveScriptEvents(item.ItemID);
317 }
318 }
261 } 319 }
262 320
263 /// <summary> 321 /// <summary>
@@ -273,7 +331,10 @@ namespace OpenSim.Region.Framework.Scenes
273 // item.Name, item.ItemID, Name, UUID); 331 // item.Name, item.ItemID, Name, UUID);
274 332
275 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 333 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
334 {
335 StoreScriptError(item.ItemID, "no permission");
276 return; 336 return;
337 }
277 338
278 m_part.AddFlag(PrimFlags.Scripted); 339 m_part.AddFlag(PrimFlags.Scripted);
279 340
@@ -282,14 +343,13 @@ namespace OpenSim.Region.Framework.Scenes
282 if (stateSource == 2 && // Prim crossing 343 if (stateSource == 2 && // Prim crossing
283 m_part.ParentGroup.Scene.m_trustBinaries) 344 m_part.ParentGroup.Scene.m_trustBinaries)
284 { 345 {
285 lock (m_items) 346 m_items.LockItemsForWrite(true);
286 { 347 m_items[item.ItemID].PermsMask = 0;
287 m_items[item.ItemID].PermsMask = 0; 348 m_items[item.ItemID].PermsGranter = UUID.Zero;
288 m_items[item.ItemID].PermsGranter = UUID.Zero; 349 m_items.LockItemsForWrite(false);
289 }
290
291 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 350 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
292 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 351 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
352 StoreScriptErrors(item.ItemID, null);
293 m_part.ParentGroup.AddActiveScriptCount(1); 353 m_part.ParentGroup.AddActiveScriptCount(1);
294 m_part.ScheduleFullUpdate(); 354 m_part.ScheduleFullUpdate();
295 return; 355 return;
@@ -298,6 +358,8 @@ namespace OpenSim.Region.Framework.Scenes
298 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 358 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
299 if (null == asset) 359 if (null == asset)
300 { 360 {
361 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
362 StoreScriptError(item.ItemID, msg);
301 m_log.ErrorFormat( 363 m_log.ErrorFormat(
302 "[PRIM INVENTORY]: " + 364 "[PRIM INVENTORY]: " +
303 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 365 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -309,15 +371,20 @@ namespace OpenSim.Region.Framework.Scenes
309 if (m_part.ParentGroup.m_savedScriptState != null) 371 if (m_part.ParentGroup.m_savedScriptState != null)
310 RestoreSavedScriptState(item.OldItemID, item.ItemID); 372 RestoreSavedScriptState(item.OldItemID, item.ItemID);
311 373
312 lock (m_items) 374 m_items.LockItemsForWrite(true);
313 { 375
314 m_items[item.ItemID].PermsMask = 0; 376 m_items[item.ItemID].PermsMask = 0;
315 m_items[item.ItemID].PermsGranter = UUID.Zero; 377 m_items[item.ItemID].PermsGranter = UUID.Zero;
316 } 378
379 m_items.LockItemsForWrite(false);
317 380
318 string script = Utils.BytesToString(asset.Data); 381 string script = Utils.BytesToString(asset.Data);
319 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 382 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
320 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 383 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
384 StoreScriptErrors(item.ItemID, null);
385 if (!item.ScriptRunning)
386 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
387 m_part.LocalId, item.ItemID);
321 m_part.ParentGroup.AddActiveScriptCount(1); 388 m_part.ParentGroup.AddActiveScriptCount(1);
322 m_part.ScheduleFullUpdate(); 389 m_part.ScheduleFullUpdate();
323 } 390 }
@@ -381,21 +448,145 @@ namespace OpenSim.Region.Framework.Scenes
381 448
382 /// <summary> 449 /// <summary>
383 /// Start a script which is in this prim's inventory. 450 /// Start a script which is in this prim's inventory.
451 /// Some processing may occur in the background, but this routine returns asap.
384 /// </summary> 452 /// </summary>
385 /// <param name="itemId"> 453 /// <param name="itemId">
386 /// A <see cref="UUID"/> 454 /// A <see cref="UUID"/>
387 /// </param> 455 /// </param>
388 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 456 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
389 { 457 {
390 TaskInventoryItem item = GetInventoryItem(itemId); 458 lock (m_scriptErrors)
391 if (item != null) 459 {
392 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 460 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
461 m_scriptErrors.Remove(itemId);
462 }
463 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
464 }
465
466 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
467 {
468 m_items.LockItemsForRead(true);
469 if (m_items.ContainsKey(itemId))
470 {
471 if (m_items.ContainsKey(itemId))
472 {
473 m_items.LockItemsForRead(false);
474 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
475 }
476 else
477 {
478 m_items.LockItemsForRead(false);
479 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
480 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
481 StoreScriptError(itemId, msg);
482 m_log.ErrorFormat(
483 "[PRIM INVENTORY]: " +
484 "Couldn't start script with ID {0} since it {1}", itemId, msg);
485 }
486 }
393 else 487 else
488 {
489 m_items.LockItemsForRead(false);
490 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
491 StoreScriptError(itemId, msg);
394 m_log.ErrorFormat( 492 m_log.ErrorFormat(
395 "[PRIM INVENTORY]: " + 493 "[PRIM INVENTORY]: " +
396 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 494 "Couldn't start script with ID {0} since it {1}", itemId, msg);
397 itemId, m_part.Name, m_part.UUID, 495 }
398 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 496
497 }
498
499 /// <summary>
500 /// Start a script which is in this prim's inventory and return any compilation error messages.
501 /// </summary>
502 /// <param name="itemId">
503 /// A <see cref="UUID"/>
504 /// </param>
505 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
506 {
507 ArrayList errors;
508
509 // Indicate to CreateScriptInstanceInternal() we want it to
510 // post any compilation/loading error messages
511 lock (m_scriptErrors)
512 {
513 m_scriptErrors[itemId] = null;
514 }
515
516 // Perform compilation/loading
517 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
518
519 // Wait for and retrieve any errors
520 lock (m_scriptErrors)
521 {
522 while ((errors = m_scriptErrors[itemId]) == null)
523 {
524 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
525 {
526 m_log.ErrorFormat(
527 "[PRIM INVENTORY]: " +
528 "timedout waiting for script {0} errors", itemId);
529 errors = m_scriptErrors[itemId];
530 if (errors == null)
531 {
532 errors = new ArrayList(1);
533 errors.Add("timedout waiting for errors");
534 }
535 break;
536 }
537 }
538 m_scriptErrors.Remove(itemId);
539 }
540 return errors;
541 }
542
543 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
544 private void StoreScriptErrors(UUID itemId, ArrayList errors)
545 {
546 lock (m_scriptErrors)
547 {
548 // If compilation/loading initiated via CreateScriptInstance(),
549 // it does not want the errors, so just get out
550 if (!m_scriptErrors.ContainsKey(itemId))
551 {
552 return;
553 }
554
555 // Initiated via CreateScriptInstanceEr(), if we know what the
556 // errors are, save them and wake CreateScriptInstanceEr().
557 if (errors != null)
558 {
559 m_scriptErrors[itemId] = errors;
560 System.Threading.Monitor.PulseAll(m_scriptErrors);
561 return;
562 }
563 }
564
565 // Initiated via CreateScriptInstanceEr() but we don't know what
566 // the errors are yet, so retrieve them from the script engine.
567 // This may involve some waiting internal to GetScriptErrors().
568 errors = GetScriptErrors(itemId);
569
570 // Get a default non-null value to indicate success.
571 if (errors == null)
572 {
573 errors = new ArrayList();
574 }
575
576 // Post to CreateScriptInstanceEr() and wake it up
577 lock (m_scriptErrors)
578 {
579 m_scriptErrors[itemId] = errors;
580 System.Threading.Monitor.PulseAll(m_scriptErrors);
581 }
582 }
583
584 // Like StoreScriptErrors(), but just posts a single string message
585 private void StoreScriptError(UUID itemId, string message)
586 {
587 ArrayList errors = new ArrayList(1);
588 errors.Add(message);
589 StoreScriptErrors(itemId, errors);
399 } 590 }
400 591
401 /// <summary> 592 /// <summary>
@@ -408,15 +599,7 @@ namespace OpenSim.Region.Framework.Scenes
408 /// </param> 599 /// </param>
409 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 600 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
410 { 601 {
411 bool scriptPresent = false; 602 if (m_items.ContainsKey(itemId))
412
413 lock (m_items)
414 {
415 if (m_items.ContainsKey(itemId))
416 scriptPresent = true;
417 }
418
419 if (scriptPresent)
420 { 603 {
421 if (!sceneObjectBeingDeleted) 604 if (!sceneObjectBeingDeleted)
422 m_part.RemoveScriptEvents(itemId); 605 m_part.RemoveScriptEvents(itemId);
@@ -441,14 +624,16 @@ namespace OpenSim.Region.Framework.Scenes
441 /// <returns></returns> 624 /// <returns></returns>
442 private bool InventoryContainsName(string name) 625 private bool InventoryContainsName(string name)
443 { 626 {
444 lock (m_items) 627 m_items.LockItemsForRead(true);
628 foreach (TaskInventoryItem item in m_items.Values)
445 { 629 {
446 foreach (TaskInventoryItem item in m_items.Values) 630 if (item.Name == name)
447 { 631 {
448 if (item.Name == name) 632 m_items.LockItemsForRead(false);
449 return true; 633 return true;
450 } 634 }
451 } 635 }
636 m_items.LockItemsForRead(false);
452 return false; 637 return false;
453 } 638 }
454 639
@@ -490,8 +675,9 @@ namespace OpenSim.Region.Framework.Scenes
490 /// <param name="item"></param> 675 /// <param name="item"></param>
491 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 676 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
492 { 677 {
493 List<TaskInventoryItem> il = GetInventoryItems(); 678 m_items.LockItemsForRead(true);
494 679 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
680 m_items.LockItemsForRead(false);
495 foreach (TaskInventoryItem i in il) 681 foreach (TaskInventoryItem i in il)
496 { 682 {
497 if (i.Name == item.Name) 683 if (i.Name == item.Name)
@@ -529,14 +715,14 @@ namespace OpenSim.Region.Framework.Scenes
529 item.Name = name; 715 item.Name = name;
530 item.GroupID = m_part.GroupID; 716 item.GroupID = m_part.GroupID;
531 717
532 lock (m_items) 718 m_items.LockItemsForWrite(true);
533 m_items.Add(item.ItemID, item); 719 m_items.Add(item.ItemID, item);
534 720 m_items.LockItemsForWrite(false);
535 if (allowedDrop) 721 if (allowedDrop)
536 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 722 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
537 else 723 else
538 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 724 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
539 725
540 m_inventorySerial++; 726 m_inventorySerial++;
541 //m_inventorySerial += 2; 727 //m_inventorySerial += 2;
542 HasInventoryChanged = true; 728 HasInventoryChanged = true;
@@ -552,15 +738,15 @@ namespace OpenSim.Region.Framework.Scenes
552 /// <param name="items"></param> 738 /// <param name="items"></param>
553 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 739 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
554 { 740 {
555 lock (m_items) 741 m_items.LockItemsForWrite(true);
742 foreach (TaskInventoryItem item in items)
556 { 743 {
557 foreach (TaskInventoryItem item in items) 744 m_items.Add(item.ItemID, item);
558 { 745// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
559 m_items.Add(item.ItemID, item);
560// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
561 }
562 m_inventorySerial++;
563 } 746 }
747 m_items.LockItemsForWrite(false);
748
749 m_inventorySerial++;
564 } 750 }
565 751
566 /// <summary> 752 /// <summary>
@@ -571,10 +757,9 @@ namespace OpenSim.Region.Framework.Scenes
571 public TaskInventoryItem GetInventoryItem(UUID itemId) 757 public TaskInventoryItem GetInventoryItem(UUID itemId)
572 { 758 {
573 TaskInventoryItem item; 759 TaskInventoryItem item;
574 760 m_items.LockItemsForRead(true);
575 lock (m_items) 761 m_items.TryGetValue(itemId, out item);
576 m_items.TryGetValue(itemId, out item); 762 m_items.LockItemsForRead(false);
577
578 return item; 763 return item;
579 } 764 }
580 765
@@ -590,15 +775,16 @@ namespace OpenSim.Region.Framework.Scenes
590 { 775 {
591 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 776 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
592 777
593 lock (m_items) 778 m_items.LockItemsForRead(true);
779
780 foreach (TaskInventoryItem item in m_items.Values)
594 { 781 {
595 foreach (TaskInventoryItem item in m_items.Values) 782 if (item.Name == name)
596 { 783 items.Add(item);
597 if (item.Name == name)
598 items.Add(item);
599 }
600 } 784 }
601 785
786 m_items.LockItemsForRead(false);
787
602 return items; 788 return items;
603 } 789 }
604 790
@@ -691,9 +877,9 @@ namespace OpenSim.Region.Framework.Scenes
691 877
692 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 878 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
693 { 879 {
694 TaskInventoryItem it = GetInventoryItem(item.ItemID); 880 m_items.LockItemsForWrite(true);
695 if (it != null)
696 881
882 if (m_items.ContainsKey(item.ItemID))
697 { 883 {
698 item.ParentID = m_part.UUID; 884 item.ParentID = m_part.UUID;
699 item.ParentPartID = m_part.UUID; 885 item.ParentPartID = m_part.UUID;
@@ -704,14 +890,10 @@ namespace OpenSim.Region.Framework.Scenes
704 item.GroupID = m_part.GroupID; 890 item.GroupID = m_part.GroupID;
705 891
706 if (item.AssetID == UUID.Zero) 892 if (item.AssetID == UUID.Zero)
707 item.AssetID = it.AssetID; 893 item.AssetID = m_items[item.ItemID].AssetID;
708
709 lock (m_items)
710 {
711 m_items[item.ItemID] = item;
712 m_inventorySerial++;
713 }
714 894
895 m_items[item.ItemID] = item;
896 m_inventorySerial++;
715 if (fireScriptEvents) 897 if (fireScriptEvents)
716 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 898 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
717 if (considerChanged) 899 if (considerChanged)
@@ -719,6 +901,7 @@ namespace OpenSim.Region.Framework.Scenes
719 HasInventoryChanged = true; 901 HasInventoryChanged = true;
720 m_part.ParentGroup.HasGroupChanged = true; 902 m_part.ParentGroup.HasGroupChanged = true;
721 } 903 }
904 m_items.LockItemsForWrite(false);
722 return true; 905 return true;
723 } 906 }
724 else 907 else
@@ -729,8 +912,9 @@ namespace OpenSim.Region.Framework.Scenes
729 item.ItemID, m_part.Name, m_part.UUID, 912 item.ItemID, m_part.Name, m_part.UUID,
730 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 913 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
731 } 914 }
732 return false; 915 m_items.LockItemsForWrite(false);
733 916
917 return false;
734 } 918 }
735 919
736 /// <summary> 920 /// <summary>
@@ -741,107 +925,68 @@ namespace OpenSim.Region.Framework.Scenes
741 /// in this prim's inventory.</returns> 925 /// in this prim's inventory.</returns>
742 public int RemoveInventoryItem(UUID itemID) 926 public int RemoveInventoryItem(UUID itemID)
743 { 927 {
744 TaskInventoryItem item = GetInventoryItem(itemID); 928 m_items.LockItemsForRead(true);
745 if (item != null) 929
930 if (m_items.ContainsKey(itemID))
746 { 931 {
747 int type = m_items[itemID].InvType; 932 int type = m_items[itemID].InvType;
933 m_items.LockItemsForRead(false);
748 if (type == 10) // Script 934 if (type == 10) // Script
749 { 935 {
750 m_part.RemoveScriptEvents(itemID);
751 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 936 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
752 } 937 }
938 m_items.LockItemsForWrite(true);
753 m_items.Remove(itemID); 939 m_items.Remove(itemID);
940 m_items.LockItemsForWrite(false);
754 m_inventorySerial++; 941 m_inventorySerial++;
755 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 942 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
756 943
757 HasInventoryChanged = true; 944 HasInventoryChanged = true;
758 m_part.ParentGroup.HasGroupChanged = true; 945 m_part.ParentGroup.HasGroupChanged = true;
759 946
760 if (!ContainsScripts()) 947 int scriptcount = 0;
948 m_items.LockItemsForRead(true);
949 foreach (TaskInventoryItem item in m_items.Values)
950 {
951 if (item.Type == 10)
952 {
953 scriptcount++;
954 }
955 }
956 m_items.LockItemsForRead(false);
957
958
959 if (scriptcount <= 0)
960 {
761 m_part.RemFlag(PrimFlags.Scripted); 961 m_part.RemFlag(PrimFlags.Scripted);
962 }
762 963
763 m_part.ScheduleFullUpdate(); 964 m_part.ScheduleFullUpdate();
764 965
765 return type; 966 return type;
766
767 } 967 }
768 else 968 else
769 { 969 {
970 m_items.LockItemsForRead(false);
770 m_log.ErrorFormat( 971 m_log.ErrorFormat(
771 "[PRIM INVENTORY]: " + 972 "[PRIM INVENTORY]: " +
772 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 973 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
773 itemID, m_part.Name, m_part.UUID, 974 itemID, m_part.Name, m_part.UUID);
774 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
775 } 975 }
776 976
777 return -1; 977 return -1;
778 } 978 }
779 979
780 private bool CreateInventoryFile() 980 private bool CreateInventoryFileName()
781 { 981 {
782 if (m_inventoryFileName == String.Empty || 982 if (m_inventoryFileName == String.Empty ||
783 m_inventoryFileNameSerial < m_inventorySerial) 983 m_inventoryFileNameSerial < m_inventorySerial)
784 { 984 {
785 // Something changed, we need to create a new file
786 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 985 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
787 m_inventoryFileNameSerial = m_inventorySerial; 986 m_inventoryFileNameSerial = m_inventorySerial;
788
789 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
790
791 lock (m_items)
792 {
793 foreach (TaskInventoryItem item in m_items.Values)
794 {
795 UUID ownerID = item.OwnerID;
796 uint everyoneMask = 0;
797 uint baseMask = item.BasePermissions;
798 uint ownerMask = item.CurrentPermissions;
799 uint groupMask = item.GroupPermissions;
800
801 invString.AddItemStart();
802 invString.AddNameValueLine("item_id", item.ItemID.ToString());
803 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
804
805 invString.AddPermissionsStart();
806
807 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
808 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
809 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
810 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
811 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
812
813 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
814 invString.AddNameValueLine("owner_id", ownerID.ToString());
815
816 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
817
818 invString.AddNameValueLine("group_id", item.GroupID.ToString());
819 invString.AddSectionEnd();
820
821 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
822 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
823 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
824 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
825
826 invString.AddSaleStart();
827 invString.AddNameValueLine("sale_type", "not");
828 invString.AddNameValueLine("sale_price", "0");
829 invString.AddSectionEnd();
830
831 invString.AddNameValueLine("name", item.Name + "|");
832 invString.AddNameValueLine("desc", item.Description + "|");
833
834 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
835 invString.AddSectionEnd();
836 }
837 }
838
839 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
840
841 return true; 987 return true;
842 } 988 }
843 989
844 // No need to recreate, the existing file is fine
845 return false; 990 return false;
846 } 991 }
847 992
@@ -851,26 +996,99 @@ namespace OpenSim.Region.Framework.Scenes
851 /// <param name="xferManager"></param> 996 /// <param name="xferManager"></param>
852 public void RequestInventoryFile(IClientAPI client, IXfer xferManager) 997 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
853 { 998 {
854 CreateInventoryFile(); 999 bool changed = CreateInventoryFileName();
1000
1001 bool includeAssets = false;
1002 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1003 includeAssets = true;
1004
1005 if (m_inventoryPrivileged != includeAssets)
1006 changed = true;
1007
1008 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1009
1010 Items.LockItemsForRead(true);
855 1011
856 if (m_inventorySerial == 0) // No inventory 1012 if (m_inventorySerial == 0) // No inventory
857 { 1013 {
858 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1014 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1015 Items.LockItemsForRead(false);
859 return; 1016 return;
860 } 1017 }
861 1018
862 // In principle, we should only do the rest if the inventory changed; 1019 if (!changed)
863 // by sending m_inventorySerial to the client, it ought to know 1020 {
864 // that nothing changed and that it doesn't need to request the file. 1021 if (m_inventoryFileData.Length > 2)
865 // Unfortunately, it doesn't look like the client optimizes this; 1022 {
866 // the client seems to always come back and request the Xfer, 1023 xferManager.AddNewFile(m_inventoryFileName,
867 // no matter what value m_inventorySerial has. 1024 m_inventoryFileData);
1025 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
1026 Util.StringToBytes256(m_inventoryFileName));
1027
1028 Items.LockItemsForRead(false);
1029 return;
1030 }
1031 }
1032
1033 m_inventoryPrivileged = includeAssets;
1034
1035 foreach (TaskInventoryItem item in m_items.Values)
1036 {
1037 UUID ownerID = item.OwnerID;
1038 uint everyoneMask = 0;
1039 uint baseMask = item.BasePermissions;
1040 uint ownerMask = item.CurrentPermissions;
1041 uint groupMask = item.GroupPermissions;
1042
1043 invString.AddItemStart();
1044 invString.AddNameValueLine("item_id", item.ItemID.ToString());
1045 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
1046
1047 invString.AddPermissionsStart();
1048
1049 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1050 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1051 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1052 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1053 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
1054
1055 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
1056 invString.AddNameValueLine("owner_id", ownerID.ToString());
1057
1058 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
1059
1060 invString.AddNameValueLine("group_id", item.GroupID.ToString());
1061 invString.AddSectionEnd();
1062
1063 if (includeAssets)
1064 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1065 else
1066 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1067 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
1068 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
1069 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
1070
1071 invString.AddSaleStart();
1072 invString.AddNameValueLine("sale_type", "not");
1073 invString.AddNameValueLine("sale_price", "0");
1074 invString.AddSectionEnd();
1075
1076 invString.AddNameValueLine("name", item.Name + "|");
1077 invString.AddNameValueLine("desc", item.Description + "|");
1078
1079 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1080 invString.AddSectionEnd();
1081 }
1082
1083 Items.LockItemsForRead(false);
1084
1085 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
868 1086
869 if (m_inventoryFileData.Length > 2) 1087 if (m_inventoryFileData.Length > 2)
870 // Add the file for Xfer 1088 {
871 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); 1089 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
1090 }
872 1091
873 // Tell the client we're ready to Xfer the file
874 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, 1092 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
875 Util.StringToBytes256(m_inventoryFileName)); 1093 Util.StringToBytes256(m_inventoryFileName));
876 } 1094 }
@@ -883,10 +1101,11 @@ namespace OpenSim.Region.Framework.Scenes
883 { 1101 {
884 if (HasInventoryChanged) 1102 if (HasInventoryChanged)
885 { 1103 {
886 HasInventoryChanged = false; 1104 Items.LockItemsForRead(true);
887 List<TaskInventoryItem> items = GetInventoryItems(); 1105 datastore.StorePrimInventory(m_part.UUID, Items.Values);
888 datastore.StorePrimInventory(m_part.UUID, items); 1106 Items.LockItemsForRead(false);
889 1107
1108 HasInventoryChanged = false;
890 } 1109 }
891 } 1110 }
892 1111
@@ -953,82 +1172,63 @@ namespace OpenSim.Region.Framework.Scenes
953 { 1172 {
954 uint mask=0x7fffffff; 1173 uint mask=0x7fffffff;
955 1174
956 lock (m_items) 1175 foreach (TaskInventoryItem item in m_items.Values)
957 { 1176 {
958 foreach (TaskInventoryItem item in m_items.Values) 1177 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1178 mask &= ~((uint)PermissionMask.Copy >> 13);
1179 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1180 mask &= ~((uint)PermissionMask.Transfer >> 13);
1181 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1182 mask &= ~((uint)PermissionMask.Modify >> 13);
1183
1184 if (item.InvType == (int)InventoryType.Object)
959 { 1185 {
960 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1186 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
961 mask &= ~((uint)PermissionMask.Copy >> 13); 1187 mask &= ~((uint)PermissionMask.Copy >> 13);
962 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1188 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
963 mask &= ~((uint)PermissionMask.Transfer >> 13); 1189 mask &= ~((uint)PermissionMask.Transfer >> 13);
964 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1190 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
965 mask &= ~((uint)PermissionMask.Modify >> 13); 1191 mask &= ~((uint)PermissionMask.Modify >> 13);
966
967 if (item.InvType != (int)InventoryType.Object)
968 {
969 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
970 mask &= ~((uint)PermissionMask.Copy >> 13);
971 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
972 mask &= ~((uint)PermissionMask.Transfer >> 13);
973 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
974 mask &= ~((uint)PermissionMask.Modify >> 13);
975 }
976 else
977 {
978 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
979 mask &= ~((uint)PermissionMask.Copy >> 13);
980 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
981 mask &= ~((uint)PermissionMask.Transfer >> 13);
982 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
983 mask &= ~((uint)PermissionMask.Modify >> 13);
984 }
985
986 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
987 mask &= ~(uint)PermissionMask.Copy;
988 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
989 mask &= ~(uint)PermissionMask.Transfer;
990 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
991 mask &= ~(uint)PermissionMask.Modify;
992 } 1192 }
1193
1194 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1195 mask &= ~(uint)PermissionMask.Copy;
1196 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1197 mask &= ~(uint)PermissionMask.Transfer;
1198 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1199 mask &= ~(uint)PermissionMask.Modify;
993 } 1200 }
994
995 return mask; 1201 return mask;
996 } 1202 }
997 1203
998 public void ApplyNextOwnerPermissions() 1204 public void ApplyNextOwnerPermissions()
999 { 1205 {
1000 lock (m_items) 1206 foreach (TaskInventoryItem item in m_items.Values)
1001 { 1207 {
1002 foreach (TaskInventoryItem item in m_items.Values) 1208 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1003 { 1209 {
1004 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1210 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1005 { 1211 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1006 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1212 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1007 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1213 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1008 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1214 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1009 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1215 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1010 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1011 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1012 }
1013 item.CurrentPermissions &= item.NextPermissions;
1014 item.BasePermissions &= item.NextPermissions;
1015 item.EveryonePermissions &= item.NextPermissions;
1016 item.OwnerChanged = true;
1017 item.PermsMask = 0;
1018 item.PermsGranter = UUID.Zero;
1019 } 1216 }
1217 item.OwnerChanged = true;
1218 item.CurrentPermissions &= item.NextPermissions;
1219 item.BasePermissions &= item.NextPermissions;
1220 item.EveryonePermissions &= item.NextPermissions;
1221 item.PermsMask = 0;
1222 item.PermsGranter = UUID.Zero;
1020 } 1223 }
1021 } 1224 }
1022 1225
1023 public void ApplyGodPermissions(uint perms) 1226 public void ApplyGodPermissions(uint perms)
1024 { 1227 {
1025 lock (m_items) 1228 foreach (TaskInventoryItem item in m_items.Values)
1026 { 1229 {
1027 foreach (TaskInventoryItem item in m_items.Values) 1230 item.CurrentPermissions = perms;
1028 { 1231 item.BasePermissions = perms;
1029 item.CurrentPermissions = perms;
1030 item.BasePermissions = perms;
1031 }
1032 } 1232 }
1033 m_inventorySerial++; 1233 m_inventorySerial++;
1034 HasInventoryChanged = true; 1234 HasInventoryChanged = true;
@@ -1036,17 +1236,13 @@ namespace OpenSim.Region.Framework.Scenes
1036 1236
1037 public bool ContainsScripts() 1237 public bool ContainsScripts()
1038 { 1238 {
1039 lock (m_items) 1239 foreach (TaskInventoryItem item in m_items.Values)
1040 { 1240 {
1041 foreach (TaskInventoryItem item in m_items.Values) 1241 if (item.InvType == (int)InventoryType.LSL)
1042 { 1242 {
1043 if (item.InvType == (int)InventoryType.LSL) 1243 return true;
1044 {
1045 return true;
1046 }
1047 } 1244 }
1048 } 1245 }
1049
1050 return false; 1246 return false;
1051 } 1247 }
1052 1248
@@ -1054,11 +1250,8 @@ namespace OpenSim.Region.Framework.Scenes
1054 { 1250 {
1055 List<UUID> ret = new List<UUID>(); 1251 List<UUID> ret = new List<UUID>();
1056 1252
1057 lock (m_items) 1253 foreach (TaskInventoryItem item in m_items.Values)
1058 { 1254 ret.Add(item.ItemID);
1059 foreach (TaskInventoryItem item in m_items.Values)
1060 ret.Add(item.ItemID);
1061 }
1062 1255
1063 return ret; 1256 return ret;
1064 } 1257 }
@@ -1089,6 +1282,11 @@ namespace OpenSim.Region.Framework.Scenes
1089 1282
1090 public Dictionary<UUID, string> GetScriptStates() 1283 public Dictionary<UUID, string> GetScriptStates()
1091 { 1284 {
1285 return GetScriptStates(false);
1286 }
1287
1288 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1289 {
1092 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1290 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1093 1291
1094 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1292 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1099,25 +1297,35 @@ namespace OpenSim.Region.Framework.Scenes
1099 if (engines == null) // No engine at all 1297 if (engines == null) // No engine at all
1100 return ret; 1298 return ret;
1101 1299
1102 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1300 Items.LockItemsForRead(true);
1103 1301 foreach (TaskInventoryItem item in m_items.Values)
1104 foreach (TaskInventoryItem item in scripts)
1105 { 1302 {
1106 foreach (IScriptModule e in engines) 1303 if (item.InvType == (int)InventoryType.LSL)
1107 { 1304 {
1108 if (e != null) 1305 foreach (IScriptModule e in engines)
1109 { 1306 {
1110 string n = e.GetXMLState(item.ItemID); 1307 if (e != null)
1111 if (n != String.Empty)
1112 { 1308 {
1113 if (!ret.ContainsKey(item.ItemID)) 1309 string n = e.GetXMLState(item.ItemID);
1114 ret[item.ItemID] = n; 1310 if (n != String.Empty)
1115 break; 1311 {
1312 if (oldIDs)
1313 {
1314 if (!ret.ContainsKey(item.OldItemID))
1315 ret[item.OldItemID] = n;
1316 }
1317 else
1318 {
1319 if (!ret.ContainsKey(item.ItemID))
1320 ret[item.ItemID] = n;
1321 }
1322 break;
1323 }
1116 } 1324 }
1117 } 1325 }
1118 } 1326 }
1119 } 1327 }
1120 1328 Items.LockItemsForRead(false);
1121 return ret; 1329 return ret;
1122 } 1330 }
1123 1331
@@ -1127,21 +1335,27 @@ namespace OpenSim.Region.Framework.Scenes
1127 if (engines == null) 1335 if (engines == null)
1128 return; 1336 return;
1129 1337
1130 List<TaskInventoryItem> scripts = GetInventoryScripts();
1131 1338
1132 foreach (TaskInventoryItem item in scripts) 1339 Items.LockItemsForRead(true);
1340
1341 foreach (TaskInventoryItem item in m_items.Values)
1133 { 1342 {
1134 foreach (IScriptModule engine in engines) 1343 if (item.InvType == (int)InventoryType.LSL)
1135 { 1344 {
1136 if (engine != null) 1345 foreach (IScriptModule engine in engines)
1137 { 1346 {
1138 if (item.OwnerChanged) 1347 if (engine != null)
1139 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1348 {
1140 item.OwnerChanged = false; 1349 if (item.OwnerChanged)
1141 engine.ResumeScript(item.ItemID); 1350 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1351 item.OwnerChanged = false;
1352 engine.ResumeScript(item.ItemID);
1353 }
1142 } 1354 }
1143 } 1355 }
1144 } 1356 }
1357
1358 Items.LockItemsForRead(false);
1145 } 1359 }
1146 } 1360 }
1147} 1361}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 00a1487..3a5b05d 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
@@ -110,6 +113,7 @@ namespace OpenSim.Region.Framework.Scenes
110 { 113 {
111 get { return m_attachments; } 114 get { return m_attachments; }
112 } 115 }
116
113 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>(); 117 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
114 118
115 private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>(); 119 private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
@@ -119,10 +123,12 @@ namespace OpenSim.Region.Framework.Scenes
119 private SceneObjectGroup proxyObjectGroup; 123 private SceneObjectGroup proxyObjectGroup;
120 //private SceneObjectPart proxyObjectPart = null; 124 //private SceneObjectPart proxyObjectPart = null;
121 public Vector3 lastKnownAllowedPosition; 125 public Vector3 lastKnownAllowedPosition;
122 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;
@@ -130,6 +136,11 @@ namespace OpenSim.Region.Framework.Scenes
130 private bool m_updateflag; 136 private bool m_updateflag;
131 private byte m_movementflag; 137 private byte m_movementflag;
132 private Vector3? m_forceToApply; 138 private Vector3? m_forceToApply;
139 private int m_userFlags;
140 public int UserFlags
141 {
142 get { return m_userFlags; }
143 }
133 private TeleportFlags m_teleportFlags; 144 private TeleportFlags m_teleportFlags;
134 public TeleportFlags TeleportFlags 145 public TeleportFlags TeleportFlags
135 { 146 {
@@ -160,9 +171,10 @@ namespace OpenSim.Region.Framework.Scenes
160 private int m_perfMonMS; 171 private int m_perfMonMS;
161 172
162 private bool m_setAlwaysRun; 173 private bool m_setAlwaysRun;
163
164 private bool m_forceFly; 174 private bool m_forceFly;
165 private bool m_flyDisabled; 175 private bool m_flyDisabled;
176 private bool m_flyingOld; // add for fly velocity control
177 public bool m_wasFlying; // add for fly velocity control
166 178
167 private float m_speedModifier = 1.0f; 179 private float m_speedModifier = 1.0f;
168 180
@@ -181,7 +193,8 @@ namespace OpenSim.Region.Framework.Scenes
181 protected RegionInfo m_regionInfo; 193 protected RegionInfo m_regionInfo;
182 protected ulong crossingFromRegion; 194 protected ulong crossingFromRegion;
183 195
184 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 196 private readonly Vector3[] Dir_Vectors = new Vector3[11];
197 private bool m_isNudging = false;
185 198
186 // Position of agent's camera in world (region cordinates) 199 // Position of agent's camera in world (region cordinates)
187 protected Vector3 m_CameraCenter; 200 protected Vector3 m_CameraCenter;
@@ -206,17 +219,25 @@ namespace OpenSim.Region.Framework.Scenes
206 private bool m_autopilotMoving; 219 private bool m_autopilotMoving;
207 private Vector3 m_autoPilotTarget; 220 private Vector3 m_autoPilotTarget;
208 private bool m_sitAtAutoTarget; 221 private bool m_sitAtAutoTarget;
222 private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
209 223
210 private string m_nextSitAnimation = String.Empty; 224 private string m_nextSitAnimation = String.Empty;
211 225
212 //PauPaw:Proper PID Controler for autopilot************ 226 //PauPaw:Proper PID Controler for autopilot************
213 private bool m_moveToPositionInProgress; 227 private bool m_moveToPositionInProgress;
214 private Vector3 m_moveToPositionTarget; 228 private Vector3 m_moveToPositionTarget;
229 private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
215 230
216 private bool m_followCamAuto; 231 private bool m_followCamAuto;
217 232
218 private int m_movementUpdateCount; 233 private int m_movementUpdateCount;
234 private int m_lastColCount = -1; //KF: Look for Collision chnages
235 private int m_updateCount = 0; //KF: Update Anims for a while
236 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
219 private const int NumMovementsBetweenRayCast = 5; 237 private const int NumMovementsBetweenRayCast = 5;
238 private List<uint> m_lastColliders = new List<uint>();
239
240 private object m_syncRoot = new Object();
220 241
221 private bool CameraConstraintActive; 242 private bool CameraConstraintActive;
222 //private int m_moveToPositionStateStatus; 243 //private int m_moveToPositionStateStatus;
@@ -243,7 +264,9 @@ namespace OpenSim.Region.Framework.Scenes
243 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 264 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
244 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 265 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
245 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 266 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
246 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 267 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
268 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
269 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
247 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 270 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
248 } 271 }
249 272
@@ -450,7 +473,8 @@ namespace OpenSim.Region.Framework.Scenes
450 get 473 get
451 { 474 {
452 PhysicsActor actor = m_physicsActor; 475 PhysicsActor actor = m_physicsActor;
453 if (actor != null) 476// if (actor != null)
477 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
454 m_pos = actor.Position; 478 m_pos = actor.Position;
455 else 479 else
456 { 480 {
@@ -472,7 +496,7 @@ namespace OpenSim.Region.Framework.Scenes
472 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 496 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
473 if (part != null) 497 if (part != null)
474 { 498 {
475 return m_parentPosition + (m_pos * part.GetWorldRotation()); 499 return part.AbsolutePosition + (m_pos * part.GetWorldRotation());
476 } 500 }
477 else 501 else
478 { 502 {
@@ -499,7 +523,8 @@ namespace OpenSim.Region.Framework.Scenes
499 } 523 }
500 } 524 }
501 525
502 m_pos = value; 526 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
527 m_pos = value;
503 m_parentPosition = Vector3.Zero; 528 m_parentPosition = Vector3.Zero;
504 } 529 }
505 } 530 }
@@ -543,10 +568,39 @@ namespace OpenSim.Region.Framework.Scenes
543 } 568 }
544 } 569 }
545 570
571 public Quaternion OffsetRotation
572 {
573 get { return m_offsetRotation; }
574 set { m_offsetRotation = value; }
575 }
576
546 public Quaternion Rotation 577 public Quaternion Rotation
547 { 578 {
548 get { return m_bodyRot; } 579 get {
549 set { m_bodyRot = value; } 580 if (m_parentID != 0)
581 {
582 if (m_offsetRotation != null)
583 {
584 return m_offsetRotation;
585 }
586 else
587 {
588 return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
589 }
590
591 }
592 else
593 {
594 return m_bodyRot;
595 }
596 }
597 set {
598 m_bodyRot = value;
599 if (m_parentID != 0)
600 {
601 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
602 }
603 }
550 } 604 }
551 605
552 public Quaternion PreviousRotation 606 public Quaternion PreviousRotation
@@ -571,11 +625,21 @@ namespace OpenSim.Region.Framework.Scenes
571 625
572 private uint m_parentID; 626 private uint m_parentID;
573 627
628
629 private UUID m_linkedPrim;
630
574 public uint ParentID 631 public uint ParentID
575 { 632 {
576 get { return m_parentID; } 633 get { return m_parentID; }
577 set { m_parentID = value; } 634 set { m_parentID = value; }
578 } 635 }
636
637 public UUID LinkedPrim
638 {
639 get { return m_linkedPrim; }
640 set { m_linkedPrim = value; }
641 }
642
579 public float Health 643 public float Health
580 { 644 {
581 get { return m_health; } 645 get { return m_health; }
@@ -697,7 +761,7 @@ namespace OpenSim.Region.Framework.Scenes
697 CreateSceneViewer(); 761 CreateSceneViewer();
698 m_animator = new ScenePresenceAnimator(this); 762 m_animator = new ScenePresenceAnimator(this);
699 } 763 }
700 764
701 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() 765 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
702 { 766 {
703 m_DrawDistance = world.DefaultDrawDistance; 767 m_DrawDistance = world.DefaultDrawDistance;
@@ -712,6 +776,7 @@ namespace OpenSim.Region.Framework.Scenes
712 m_localId = m_scene.AllocateLocalId(); 776 m_localId = m_scene.AllocateLocalId();
713 777
714 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); 778 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
779 m_userFlags = account.UserFlags;
715 780
716 if (account != null) 781 if (account != null)
717 m_userLevel = account.UserLevel; 782 m_userLevel = account.UserLevel;
@@ -730,10 +795,7 @@ namespace OpenSim.Region.Framework.Scenes
730 m_reprioritization_timer.AutoReset = false; 795 m_reprioritization_timer.AutoReset = false;
731 796
732 AdjustKnownSeeds(); 797 AdjustKnownSeeds();
733
734 // TODO: I think, this won't send anything, as we are still a child here...
735 Animator.TrySetMovementAnimation("STAND"); 798 Animator.TrySetMovementAnimation("STAND");
736
737 // we created a new ScenePresence (a new child agent) in a fresh region. 799 // we created a new ScenePresence (a new child agent) in a fresh region.
738 // Request info about all the (root) agents in this region 800 // Request info about all the (root) agents in this region
739 // Note: This won't send data *to* other clients in that region (children don't send) 801 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -784,25 +846,47 @@ namespace OpenSim.Region.Framework.Scenes
784 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 846 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
785 Dir_Vectors[4] = Vector3.UnitZ; //UP 847 Dir_Vectors[4] = Vector3.UnitZ; //UP
786 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 848 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
787 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 849 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
788 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 850 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
789 Dir_Vectors[7] = -Vector3.UnitX; //BACK 851 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
852 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
853 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
790 } 854 }
791 855
792 private Vector3[] GetWalkDirectionVectors() 856 private Vector3[] GetWalkDirectionVectors()
793 { 857 {
794 Vector3[] vector = new Vector3[9]; 858 Vector3[] vector = new Vector3[11];
795 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 859 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
796 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 860 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
797 vector[2] = Vector3.UnitY; //LEFT 861 vector[2] = Vector3.UnitY; //LEFT
798 vector[3] = -Vector3.UnitY; //RIGHT 862 vector[3] = -Vector3.UnitY; //RIGHT
799 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 863 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
800 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 864 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
801 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 865 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
802 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 866 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
803 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 867 vector[8] = Vector3.UnitY; //LEFT_NUDGE
868 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
869 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
804 return vector; 870 return vector;
805 } 871 }
872
873 private bool[] GetDirectionIsNudge()
874 {
875 bool[] isNudge = new bool[11];
876 isNudge[0] = false; //FORWARD
877 isNudge[1] = false; //BACK
878 isNudge[2] = false; //LEFT
879 isNudge[3] = false; //RIGHT
880 isNudge[4] = false; //UP
881 isNudge[5] = false; //DOWN
882 isNudge[6] = true; //FORWARD_NUDGE
883 isNudge[7] = true; //BACK_NUDGE
884 isNudge[8] = true; //LEFT_NUDGE
885 isNudge[9] = true; //RIGHT_NUDGE
886 isNudge[10] = true; //DOWN_Nudge
887 return isNudge;
888 }
889
806 890
807 #endregion 891 #endregion
808 892
@@ -864,6 +948,62 @@ namespace OpenSim.Region.Framework.Scenes
864 pos.Y = crossedBorder.BorderLine.Z - 1; 948 pos.Y = crossedBorder.BorderLine.Z - 1;
865 } 949 }
866 950
951 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
952 if (land != null)
953 {
954 // If we come in via login, landmark or map, we want to
955 // honor landing points. If we come in via Lure, we want
956 // to ignore them.
957 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) ||
958 (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 ||
959 (m_teleportFlags & TeleportFlags.ViaLocation) != 0)
960 {
961 // Don't restrict gods, estate managers, or land owners to
962 // the TP point. This behaviour mimics agni.
963 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
964 land.LandData.UserLocation != Vector3.Zero &&
965 GodLevel < 200 &&
966 ((land.LandData.OwnerID != m_uuid &&
967 (!m_scene.Permissions.IsGod(m_uuid)) &&
968 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid))) || (m_teleportFlags & TeleportFlags.ViaLocation) != 0))
969 {
970 pos = land.LandData.UserLocation;
971 }
972 }
973
974 land.SendLandUpdateToClient(ControllingClient);
975 }
976
977 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
978 {
979 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
980
981 if (pos.X < 0)
982 {
983 emergencyPos.X = (int)Constants.RegionSize + pos.X;
984 if (!(pos.Y < 0))
985 emergencyPos.Y = pos.Y;
986 if (!(pos.Z < 0))
987 emergencyPos.Z = pos.Z;
988 }
989 if (pos.Y < 0)
990 {
991 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
992 if (!(pos.X < 0))
993 emergencyPos.X = pos.X;
994 if (!(pos.Z < 0))
995 emergencyPos.Z = pos.Z;
996 }
997 if (pos.Z < 0)
998 {
999 emergencyPos.Z = 128;
1000 if (!(pos.Y < 0))
1001 emergencyPos.Y = pos.Y;
1002 if (!(pos.X < 0))
1003 emergencyPos.X = pos.X;
1004 }
1005 }
1006
867 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 1007 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
868 { 1008 {
869 m_log.WarnFormat( 1009 m_log.WarnFormat(
@@ -988,16 +1128,21 @@ namespace OpenSim.Region.Framework.Scenes
988 /// <summary> 1128 /// <summary>
989 /// Removes physics plugin scene representation of this agent if it exists. 1129 /// Removes physics plugin scene representation of this agent if it exists.
990 /// </summary> 1130 /// </summary>
991 private void RemoveFromPhysicalScene() 1131 public void RemoveFromPhysicalScene()
992 { 1132 {
993 if (PhysicsActor != null) 1133 if (PhysicsActor != null)
994 { 1134 {
995 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1135 try
996 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; 1136 {
997 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1137 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
998 m_physicsActor.UnSubscribeEvents(); 1138 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
999 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1139 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1000 PhysicsActor = null; 1140 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1141 m_physicsActor.UnSubscribeEvents();
1142 PhysicsActor = null;
1143 }
1144 catch
1145 { }
1001 } 1146 }
1002 } 1147 }
1003 1148
@@ -1008,11 +1153,13 @@ namespace OpenSim.Region.Framework.Scenes
1008 public void Teleport(Vector3 pos) 1153 public void Teleport(Vector3 pos)
1009 { 1154 {
1010 bool isFlying = false; 1155 bool isFlying = false;
1156
1011 if (m_physicsActor != null) 1157 if (m_physicsActor != null)
1012 isFlying = m_physicsActor.Flying; 1158 isFlying = m_physicsActor.Flying;
1013 1159
1014 RemoveFromPhysicalScene(); 1160 RemoveFromPhysicalScene();
1015 Velocity = Vector3.Zero; 1161 Velocity = Vector3.Zero;
1162 CheckLandingPoint(ref pos);
1016 AbsolutePosition = pos; 1163 AbsolutePosition = pos;
1017 AddToPhysicalScene(isFlying); 1164 AddToPhysicalScene(isFlying);
1018 if (m_appearance != null) 1165 if (m_appearance != null)
@@ -1022,6 +1169,7 @@ namespace OpenSim.Region.Framework.Scenes
1022 } 1169 }
1023 1170
1024 SendTerseUpdateToAllClients(); 1171 SendTerseUpdateToAllClients();
1172
1025 } 1173 }
1026 1174
1027 public void TeleportWithMomentum(Vector3 pos) 1175 public void TeleportWithMomentum(Vector3 pos)
@@ -1031,6 +1179,7 @@ namespace OpenSim.Region.Framework.Scenes
1031 isFlying = m_physicsActor.Flying; 1179 isFlying = m_physicsActor.Flying;
1032 1180
1033 RemoveFromPhysicalScene(); 1181 RemoveFromPhysicalScene();
1182 CheckLandingPoint(ref pos);
1034 AbsolutePosition = pos; 1183 AbsolutePosition = pos;
1035 AddToPhysicalScene(isFlying); 1184 AddToPhysicalScene(isFlying);
1036 if (m_appearance != null) 1185 if (m_appearance != null)
@@ -1242,6 +1391,7 @@ namespace OpenSim.Region.Framework.Scenes
1242 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1391 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1243 1392
1244 m_pos = m_LastFinitePos; 1393 m_pos = m_LastFinitePos;
1394
1245 if (!m_pos.IsFinite()) 1395 if (!m_pos.IsFinite())
1246 { 1396 {
1247 m_pos.X = 127f; 1397 m_pos.X = 127f;
@@ -1312,7 +1462,6 @@ namespace OpenSim.Region.Framework.Scenes
1312 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1462 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1313 } 1463 }
1314 } 1464 }
1315
1316 lock (scriptedcontrols) 1465 lock (scriptedcontrols)
1317 { 1466 {
1318 if (scriptedcontrols.Count > 0) 1467 if (scriptedcontrols.Count > 0)
@@ -1327,6 +1476,9 @@ namespace OpenSim.Region.Framework.Scenes
1327 1476
1328 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1477 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1329 { 1478 {
1479 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1480 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1481
1330 // TODO: This doesn't prevent the user from walking yet. 1482 // TODO: This doesn't prevent the user from walking yet.
1331 // Setting parent ID would fix this, if we knew what value 1483 // Setting parent ID would fix this, if we knew what value
1332 // to use. Or we could add a m_isSitting variable. 1484 // to use. Or we could add a m_isSitting variable.
@@ -1375,12 +1527,20 @@ namespace OpenSim.Region.Framework.Scenes
1375 if (actor.Flying != oldflying) 1527 if (actor.Flying != oldflying)
1376 update_movementflag = true; 1528 update_movementflag = true;
1377 1529
1530 if (m_animator.m_jumping) // add for jumping
1531 update_movementflag = true;
1532
1378 if (q != m_bodyRot) 1533 if (q != m_bodyRot)
1379 { 1534 {
1380 m_bodyRot = q; 1535 m_bodyRot = q;
1381 update_rotation = true; 1536 update_rotation = true;
1382 } 1537 }
1383 1538
1539 //guilty until proven innocent..
1540 bool Nudging = true;
1541 //Basically, if there is at least one non-nudge control then we don't need
1542 //to worry about stopping the avatar
1543
1384 if (m_parentID == 0) 1544 if (m_parentID == 0)
1385 { 1545 {
1386 bool bAllowUpdateMoveToPosition = false; 1546 bool bAllowUpdateMoveToPosition = false;
@@ -1395,9 +1555,12 @@ namespace OpenSim.Region.Framework.Scenes
1395 else 1555 else
1396 dirVectors = Dir_Vectors; 1556 dirVectors = Dir_Vectors;
1397 1557
1398 // The fact that m_movementflag is a byte needs to be fixed 1558 bool[] isNudge = GetDirectionIsNudge();
1399 // it really should be a uint 1559
1400 uint nudgehack = 250; 1560
1561
1562
1563
1401 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1564 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1402 { 1565 {
1403 if (((uint)flags & (uint)DCF) != 0) 1566 if (((uint)flags & (uint)DCF) != 0)
@@ -1407,40 +1570,28 @@ namespace OpenSim.Region.Framework.Scenes
1407 try 1570 try
1408 { 1571 {
1409 agent_control_v3 += dirVectors[i]; 1572 agent_control_v3 += dirVectors[i];
1410 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1573 if (isNudge[i] == false)
1574 {
1575 Nudging = false;
1576 }
1411 } 1577 }
1412 catch (IndexOutOfRangeException) 1578 catch (IndexOutOfRangeException)
1413 { 1579 {
1414 // Why did I get this? 1580 // Why did I get this?
1415 } 1581 }
1416 1582
1417 if ((m_movementflag & (byte)(uint)DCF) == 0) 1583 if ((m_movementflag & (uint)DCF) == 0)
1418 { 1584 {
1419 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1420 {
1421 m_movementflag |= (byte)nudgehack;
1422 }
1423 m_movementflag += (byte)(uint)DCF; 1585 m_movementflag += (byte)(uint)DCF;
1424 update_movementflag = true; 1586 update_movementflag = true;
1425 } 1587 }
1426 } 1588 }
1427 else 1589 else
1428 { 1590 {
1429 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1591 if ((m_movementflag & (uint)DCF) != 0)
1430 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1431 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1432 ) // This or is for Nudge forward
1433 { 1592 {
1434 m_movementflag -= ((byte)(uint)DCF); 1593 m_movementflag -= (byte)(uint)DCF;
1435
1436 update_movementflag = true; 1594 update_movementflag = true;
1437 /*
1438 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1439 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1440 {
1441 m_log.Debug("Removed Hack flag");
1442 }
1443 */
1444 } 1595 }
1445 else 1596 else
1446 { 1597 {
@@ -1449,7 +1600,6 @@ namespace OpenSim.Region.Framework.Scenes
1449 } 1600 }
1450 i++; 1601 i++;
1451 } 1602 }
1452
1453 //Paupaw:Do Proper PID for Autopilot here 1603 //Paupaw:Do Proper PID for Autopilot here
1454 if (bResetMoveToPosition) 1604 if (bResetMoveToPosition)
1455 { 1605 {
@@ -1461,8 +1611,41 @@ namespace OpenSim.Region.Framework.Scenes
1461 1611
1462 if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving)) 1612 if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
1463 { 1613 {
1614/*
1615 bool twoD = false;
1616 bool there = false;
1617 if (Animator != null)
1618 {
1619 switch (Animator.CurrentMovementAnimation)
1620 {
1621 case "STAND":
1622 case "WALK":
1623 case "RUN":
1624 case "CROUCH":
1625 case "CROUCHWALK":
1626 {
1627 twoD = true;
1628 }
1629 break;
1630 }
1631 }
1632
1633 if (twoD)
1634 {
1635*/
1636 Vector3 abspos = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, 0.0f);
1637 Vector3 tgt = new Vector3(m_moveToPositionTarget.X, m_moveToPositionTarget.Y, 0.0f);
1638/* if (Util.GetDistanceTo(abspos, tgt) <= 0.5f) there = true;
1639 }
1640 else
1641 {
1642 if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) there = true;
1643 }
1644*/
1464 //Check the error term of the current position in relation to the target position 1645 //Check the error term of the current position in relation to the target position
1465 if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) 1646// if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f)
1647// if (there)
1648 if (Util.GetDistanceTo(abspos, tgt) <= 0.5f)
1466 { 1649 {
1467 // we are close enough to the target 1650 // we are close enough to the target
1468 m_moveToPositionTarget = Vector3.Zero; 1651 m_moveToPositionTarget = Vector3.Zero;
@@ -1479,11 +1662,15 @@ namespace OpenSim.Region.Framework.Scenes
1479 // unknown forces are acting on the avatar and we need to adaptively respond 1662 // unknown forces are acting on the avatar and we need to adaptively respond
1480 // to such forces, but the following simple approach seems to works fine. 1663 // to such forces, but the following simple approach seems to works fine.
1481 Vector3 LocalVectorToTarget3D = 1664 Vector3 LocalVectorToTarget3D =
1482 (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords 1665// (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
1666 (tgt - abspos)
1483 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords 1667 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
1484 // Ignore z component of vector 1668 // Ignore z component of vector
1485 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1669 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1486 LocalVectorToTarget2D.Normalize(); 1670 LocalVectorToTarget2D.Normalize();
1671
1672 //We're not nudging
1673 Nudging = false;
1487 agent_control_v3 += LocalVectorToTarget2D; 1674 agent_control_v3 += LocalVectorToTarget2D;
1488 1675
1489 // update avatar movement flags. the avatar coordinate system is as follows: 1676 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1574,13 +1761,13 @@ namespace OpenSim.Region.Framework.Scenes
1574 // m_log.DebugFormat( 1761 // m_log.DebugFormat(
1575 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1762 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1576 1763
1577 AddNewMovement(agent_control_v3, q); 1764 AddNewMovement(agent_control_v3, q, Nudging);
1578 1765
1579 1766
1580 } 1767 }
1581 } 1768 }
1582 1769
1583 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1770 if (update_movementflag && !SitGround)
1584 Animator.UpdateMovementAnimations(); 1771 Animator.UpdateMovementAnimations();
1585 1772
1586 m_scene.EventManager.TriggerOnClientMovement(this); 1773 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1595,7 +1782,6 @@ namespace OpenSim.Region.Framework.Scenes
1595 m_sitAtAutoTarget = false; 1782 m_sitAtAutoTarget = false;
1596 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1783 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1597 //proxy.PCode = (byte)PCode.ParticleSystem; 1784 //proxy.PCode = (byte)PCode.ParticleSystem;
1598
1599 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1785 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1600 proxyObjectGroup.AttachToScene(m_scene); 1786 proxyObjectGroup.AttachToScene(m_scene);
1601 1787
@@ -1614,8 +1800,15 @@ namespace OpenSim.Region.Framework.Scenes
1614// } 1800// }
1615 } 1801 }
1616 1802
1803 public void StopMoveToPosition()
1804 {
1805 m_moveToPositionTarget = Vector3.Zero;
1806 m_moveToPositionInProgress = false;
1807 }
1808
1617 public void DoMoveToPosition(Object sender, string method, List<String> args) 1809 public void DoMoveToPosition(Object sender, string method, List<String> args)
1618 { 1810 {
1811//Console.WriteLine("SP:DoMoveToPosition");
1619 try 1812 try
1620 { 1813 {
1621 float locx = 0f; 1814 float locx = 0f;
@@ -1637,7 +1830,7 @@ namespace OpenSim.Region.Framework.Scenes
1637 } 1830 }
1638 m_moveToPositionInProgress = true; 1831 m_moveToPositionInProgress = true;
1639 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1832 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1640 } 1833 }
1641 catch (Exception ex) 1834 catch (Exception ex)
1642 { 1835 {
1643 //Why did I get this error? 1836 //Why did I get this error?
@@ -1659,7 +1852,7 @@ namespace OpenSim.Region.Framework.Scenes
1659 Velocity = Vector3.Zero; 1852 Velocity = Vector3.Zero;
1660 SendAvatarDataToAllAgents(); 1853 SendAvatarDataToAllAgents();
1661 1854
1662 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1855 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1663 } 1856 }
1664 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1857 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1665 m_requestedSitTargetUUID = UUID.Zero; 1858 m_requestedSitTargetUUID = UUID.Zero;
@@ -1696,25 +1889,22 @@ namespace OpenSim.Region.Framework.Scenes
1696 1889
1697 if (m_parentID != 0) 1890 if (m_parentID != 0)
1698 { 1891 {
1699 m_log.Debug("StandupCode Executed"); 1892 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1700 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1701 if (part != null) 1893 if (part != null)
1702 { 1894 {
1895 part.TaskInventory.LockItemsForRead(true);
1703 TaskInventoryDictionary taskIDict = part.TaskInventory; 1896 TaskInventoryDictionary taskIDict = part.TaskInventory;
1704 if (taskIDict != null) 1897 if (taskIDict != null)
1705 { 1898 {
1706 lock (taskIDict) 1899 foreach (UUID taskID in taskIDict.Keys)
1707 { 1900 {
1708 foreach (UUID taskID in taskIDict.Keys) 1901 UnRegisterControlEventsToScript(LocalId, taskID);
1709 { 1902 taskIDict[taskID].PermsMask &= ~(
1710 UnRegisterControlEventsToScript(LocalId, taskID); 1903 2048 | //PERMISSION_CONTROL_CAMERA
1711 taskIDict[taskID].PermsMask &= ~( 1904 4); // PERMISSION_TAKE_CONTROLS
1712 2048 | //PERMISSION_CONTROL_CAMERA
1713 4); // PERMISSION_TAKE_CONTROLS
1714 }
1715 } 1905 }
1716
1717 } 1906 }
1907 part.TaskInventory.LockItemsForRead(false);
1718 // Reset sit target. 1908 // Reset sit target.
1719 if (part.GetAvatarOnSitTarget() == UUID) 1909 if (part.GetAvatarOnSitTarget() == UUID)
1720 part.SitTargetAvatar = UUID.Zero; 1910 part.SitTargetAvatar = UUID.Zero;
@@ -1723,16 +1913,55 @@ namespace OpenSim.Region.Framework.Scenes
1723 m_parentPosition = part.GetWorldPosition(); 1913 m_parentPosition = part.GetWorldPosition();
1724 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1914 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1725 } 1915 }
1916 // part.GetWorldRotation() is the rotation of the object being sat on
1917 // Rotation is the sittiing Av's rotation
1918
1919 Quaternion partRot;
1920// if (part.LinkNum == 1)
1921// { // Root prim of linkset
1922// partRot = part.ParentGroup.RootPart.RotationOffset;
1923// }
1924// else
1925// { // single or child prim
1926
1927// }
1928 if (part == null) //CW: Part may be gone. llDie() for example.
1929 {
1930 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1931 }
1932 else
1933 {
1934 partRot = part.GetWorldRotation();
1935 }
1936
1937 Quaternion partIRot = Quaternion.Inverse(partRot);
1726 1938
1939 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1940 Vector3 avStandUp = new Vector3(0.3f, 0f, 0f) * avatarRot; // 0.3M infront of av
1941
1942
1727 if (m_physicsActor == null) 1943 if (m_physicsActor == null)
1728 { 1944 {
1729 AddToPhysicalScene(false); 1945 AddToPhysicalScene(false);
1730 } 1946 }
1731 1947 //CW: If the part isn't null then we can set the current position
1732 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1948 if (part != null)
1733 m_parentPosition = Vector3.Zero; 1949 {
1734 1950 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
1735 m_parentID = 0; 1951 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1952 part.IsOccupied = false;
1953 part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
1954 }
1955 else
1956 {
1957 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1958 AbsolutePosition = m_lastWorldPosition;
1959 }
1960
1961 m_parentPosition = Vector3.Zero;
1962 m_parentID = 0;
1963 m_linkedPrim = UUID.Zero;
1964 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1736 SendAvatarDataToAllAgents(); 1965 SendAvatarDataToAllAgents();
1737 m_requestedSitTargetID = 0; 1966 m_requestedSitTargetID = 0;
1738 if (m_physicsActor != null && m_appearance != null) 1967 if (m_physicsActor != null && m_appearance != null)
@@ -1741,7 +1970,6 @@ namespace OpenSim.Region.Framework.Scenes
1741 SetHeight(m_appearance.AvatarHeight); 1970 SetHeight(m_appearance.AvatarHeight);
1742 } 1971 }
1743 } 1972 }
1744
1745 Animator.TrySetMovementAnimation("STAND"); 1973 Animator.TrySetMovementAnimation("STAND");
1746 } 1974 }
1747 1975
@@ -1772,13 +2000,9 @@ namespace OpenSim.Region.Framework.Scenes
1772 Vector3 avSitOffSet = part.SitTargetPosition; 2000 Vector3 avSitOffSet = part.SitTargetPosition;
1773 Quaternion avSitOrientation = part.SitTargetOrientation; 2001 Quaternion avSitOrientation = part.SitTargetOrientation;
1774 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 2002 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1775 2003 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1776 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 2004 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1777 bool SitTargetisSet = 2005 if (SitTargetisSet && !SitTargetOccupied)
1778 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1779 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1780
1781 if (SitTargetisSet && SitTargetUnOccupied)
1782 { 2006 {
1783 //switch the target to this prim 2007 //switch the target to this prim
1784 return part; 2008 return part;
@@ -1792,85 +2016,168 @@ namespace OpenSim.Region.Framework.Scenes
1792 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 2016 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1793 { 2017 {
1794 bool autopilot = true; 2018 bool autopilot = true;
2019 Vector3 autopilotTarget = new Vector3();
2020 Quaternion sitOrientation = Quaternion.Identity;
1795 Vector3 pos = new Vector3(); 2021 Vector3 pos = new Vector3();
1796 Quaternion sitOrientation = pSitOrientation;
1797 Vector3 cameraEyeOffset = Vector3.Zero; 2022 Vector3 cameraEyeOffset = Vector3.Zero;
1798 Vector3 cameraAtOffset = Vector3.Zero; 2023 Vector3 cameraAtOffset = Vector3.Zero;
1799 bool forceMouselook = false; 2024 bool forceMouselook = false;
1800 2025
1801 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 2026 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1802 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 2027 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1803 if (part != null) 2028 if (part == null) return;
1804 { 2029
1805 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 2030 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1806 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 2031 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1807 2032
1808 // Is a sit target available? 2033 // part is the prim to sit on
1809 Vector3 avSitOffSet = part.SitTargetPosition; 2034 // offset is the world-ref vector distance from that prim center to the click-spot
1810 Quaternion avSitOrientation = part.SitTargetOrientation; 2035 // UUID is the UUID of the Avatar doing the clicking
1811 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 2036
1812 2037 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1813 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 2038
1814 bool SitTargetisSet = 2039 // Is a sit target available?
1815 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 2040 Vector3 avSitOffSet = part.SitTargetPosition;
1816 ( 2041 Quaternion avSitOrientation = part.SitTargetOrientation;
1817 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 2042
1818 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 2043 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1819 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 2044 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1820 ) 2045 Quaternion partRot;
1821 )); 2046// if (part.LinkNum == 1)
1822 2047// { // Root prim of linkset
1823 if (SitTargetisSet && SitTargetUnOccupied) 2048// partRot = part.ParentGroup.RootPart.RotationOffset;
1824 { 2049// }
1825 part.SitTargetAvatar = UUID; 2050// else
1826 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 2051// { // single or child prim
1827 sitOrientation = avSitOrientation; 2052 partRot = part.GetWorldRotation();
1828 autopilot = false; 2053// }
1829 } 2054 Quaternion partIRot = Quaternion.Inverse(partRot);
1830 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 2055//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1831 2056 // Sit analysis rewritten by KF 091125
1832 pos = part.AbsolutePosition + offset; 2057 if (SitTargetisSet) // scipted sit
1833 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 2058 {
1834 //{ 2059 if (!part.IsOccupied)
1835 // offset = pos; 2060 {
1836 //autopilot = false; 2061//Console.WriteLine("Scripted, unoccupied");
1837 //} 2062 part.SitTargetAvatar = UUID; // set that Av will be on it
1838 if (m_physicsActor != null) 2063 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1839 { 2064
1840 // If we're not using the client autopilot, we're immediately warping the avatar to the location 2065 Quaternion nrot = avSitOrientation;
1841 // We can remove the physicsActor until they stand up. 2066 if (!part.IsRoot)
1842 m_sitAvatarHeight = m_physicsActor.Size.Z;
1843
1844 if (autopilot)
1845 { 2067 {
1846 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 2068 nrot = part.RotationOffset * avSitOrientation;
1847 {
1848 autopilot = false;
1849
1850 RemoveFromPhysicalScene();
1851 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1852 }
1853 } 2069 }
1854 else 2070 sitOrientation = nrot; // Change rotatione to the scripted one
2071 OffsetRotation = nrot;
2072 autopilot = false; // Jump direct to scripted llSitPos()
2073 }
2074 else
2075 {
2076//Console.WriteLine("Scripted, occupied");
2077 return;
2078 }
2079 }
2080 else // Not Scripted
2081 {
2082 if ( (Math.Abs(offset.X) > 0.1f) || (Math.Abs(offset.Y) > 0.1f) ) // Changed 0.5M to 0.1M as they want to be able to sit close together
2083 {
2084 // large prim & offset, ignore if other Avs sitting
2085// offset.Z -= 0.05f;
2086 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
2087 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
2088
2089//Console.WriteLine(" offset ={0}", offset);
2090//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
2091//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
2092
2093 }
2094 else // small offset
2095 {
2096//Console.WriteLine("Small offset");
2097 if (!part.IsOccupied)
2098 {
2099 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
2100 autopilotTarget = part.AbsolutePosition;
2101//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
2102 }
2103 else return; // occupied small
2104 } // end large/small
2105 } // end Scripted/not
2106
2107 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2108
2109 cameraAtOffset = part.GetCameraAtOffset();
2110 cameraEyeOffset = part.GetCameraEyeOffset();
2111 forceMouselook = part.GetForceMouselook();
2112 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
2113 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
2114
2115 if (m_physicsActor != null)
2116 {
2117 // If we're not using the client autopilot, we're immediately warping the avatar to the location
2118 // We can remove the physicsActor until they stand up.
2119 m_sitAvatarHeight = m_physicsActor.Size.Z;
2120 if (autopilot)
2121 { // its not a scripted sit
2122// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
2123 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
1855 { 2124 {
2125 autopilot = false; // close enough
2126 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2127 Not using the part's position because returning the AV to the last known standing
2128 position is likely to be more friendly, isn't it? */
1856 RemoveFromPhysicalScene(); 2129 RemoveFromPhysicalScene();
1857 } 2130 Velocity = Vector3.Zero;
2131 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
2132 } // else the autopilot will get us close
2133 }
2134 else
2135 { // its a scripted sit
2136 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2137 I *am* using the part's position this time because we have no real idea how far away
2138 the avatar is from the sit target. */
2139 RemoveFromPhysicalScene();
2140 Velocity = Vector3.Zero;
1858 } 2141 }
1859
1860 cameraAtOffset = part.GetCameraAtOffset();
1861 cameraEyeOffset = part.GetCameraEyeOffset();
1862 forceMouselook = part.GetForceMouselook();
1863 } 2142 }
1864 2143 else return; // physactor is null!
1865 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 2144
1866 m_requestedSitTargetUUID = targetID; 2145 Vector3 offsetr; // = offset * partIRot;
2146 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
2147 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
2148 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
2149 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
2150 //offsetr = offset * partIRot;
2151//
2152 // }
2153 // else
2154 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
2155 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
2156 // (offset * partRot);
2157 // }
2158
2159//Console.WriteLine(" ");
2160//Console.WriteLine("link number ={0}", part.LinkNum);
2161//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2162//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2163//Console.WriteLine("Click offst ={0}", offset);
2164//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2165//Console.WriteLine("offsetr ={0}", offsetr);
2166//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2167//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2168
2169 //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
2170 ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2171
2172 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1867 // This calls HandleAgentSit twice, once from here, and the client calls 2173 // This calls HandleAgentSit twice, once from here, and the client calls
1868 // HandleAgentSit itself after it gets to the location 2174 // HandleAgentSit itself after it gets to the location
1869 // It doesn't get to the location until we've moved them there though 2175 // It doesn't get to the location until we've moved them there though
1870 // which happens in HandleAgentSit :P 2176 // which happens in HandleAgentSit :P
1871 m_autopilotMoving = autopilot; 2177 m_autopilotMoving = autopilot;
1872 m_autoPilotTarget = pos; 2178 m_autoPilotTarget = autopilotTarget;
1873 m_sitAtAutoTarget = autopilot; 2179 m_sitAtAutoTarget = autopilot;
2180 m_initialSitTarget = autopilotTarget;
1874 if (!autopilot) 2181 if (!autopilot)
1875 HandleAgentSit(remoteClient, UUID); 2182 HandleAgentSit(remoteClient, UUID);
1876 } 2183 }
@@ -2165,47 +2472,130 @@ namespace OpenSim.Region.Framework.Scenes
2165 { 2472 {
2166 if (part != null) 2473 if (part != null)
2167 { 2474 {
2475//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2168 if (part.GetAvatarOnSitTarget() == UUID) 2476 if (part.GetAvatarOnSitTarget() == UUID)
2169 { 2477 {
2478//Console.WriteLine("Scripted Sit");
2479 // Scripted sit
2170 Vector3 sitTargetPos = part.SitTargetPosition; 2480 Vector3 sitTargetPos = part.SitTargetPosition;
2171 Quaternion sitTargetOrient = part.SitTargetOrientation; 2481 Quaternion sitTargetOrient = part.SitTargetOrientation;
2172
2173 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2174 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2175
2176 //Quaternion result = (sitTargetOrient * vq) * nq;
2177
2178 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2482 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2179 m_pos += SIT_TARGET_ADJUSTMENT; 2483 m_pos += SIT_TARGET_ADJUSTMENT;
2484 if (!part.IsRoot)
2485 {
2486 m_pos *= part.RotationOffset;
2487 }
2180 m_bodyRot = sitTargetOrient; 2488 m_bodyRot = sitTargetOrient;
2181 //Rotation = sitTargetOrient;
2182 m_parentPosition = part.AbsolutePosition; 2489 m_parentPosition = part.AbsolutePosition;
2183 2490 part.IsOccupied = true;
2184 //SendTerseUpdateToAllClients(); 2491 part.ParentGroup.AddAvatar(agentID);
2185 } 2492 }
2186 else 2493 else
2187 { 2494 {
2188 m_pos -= part.AbsolutePosition; 2495 // if m_avUnscriptedSitPos is zero then Av sits above center
2496 // Else Av sits at m_avUnscriptedSitPos
2497
2498 // Non-scripted sit by Kitto Flora 21Nov09
2499 // Calculate angle of line from prim to Av
2500 Quaternion partIRot;
2501// if (part.LinkNum == 1)
2502// { // Root prim of linkset
2503// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2504// }
2505// else
2506// { // single or child prim
2507 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2508// }
2509 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2510 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2511 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2512 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2513 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2514 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2515 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2516 // Av sits at world euler <0,0, z>, translated by part rotation
2517 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2518
2189 m_parentPosition = part.AbsolutePosition; 2519 m_parentPosition = part.AbsolutePosition;
2190 } 2520 part.IsOccupied = true;
2521 part.ParentGroup.AddAvatar(agentID);
2522 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2523 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2524 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2525 m_avUnscriptedSitPos; // adds click offset, if any
2526 //Set up raytrace to find top surface of prim
2527 Vector3 size = part.Scale;
2528 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2529 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2530 Vector3 down = new Vector3(0f, 0f, -1f);
2531//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2532 m_scene.PhysicsScene.RaycastWorld(
2533 start, // Vector3 position,
2534 down, // Vector3 direction,
2535 mag, // float length,
2536 SitAltitudeCallback); // retMethod
2537 } // end scripted/not
2191 } 2538 }
2192 else 2539 else // no Av
2193 { 2540 {
2194 return; 2541 return;
2195 } 2542 }
2196 } 2543 }
2197 m_parentID = m_requestedSitTargetID;
2198 2544
2545 //We want our offsets to reference the root prim, not the child we may have sat on
2546 if (!part.IsRoot)
2547 {
2548 m_parentID = part.ParentGroup.RootPart.LocalId;
2549 m_pos += part.OffsetPosition;
2550 }
2551 else
2552 {
2553 m_parentID = m_requestedSitTargetID;
2554 }
2555
2556 m_linkedPrim = part.UUID;
2557 if (part.GetAvatarOnSitTarget() != UUID)
2558 {
2559 m_offsetRotation = m_offsetRotation / part.RotationOffset;
2560 }
2199 Velocity = Vector3.Zero; 2561 Velocity = Vector3.Zero;
2200 RemoveFromPhysicalScene(); 2562 RemoveFromPhysicalScene();
2201
2202 Animator.TrySetMovementAnimation(sitAnimation); 2563 Animator.TrySetMovementAnimation(sitAnimation);
2203 SendAvatarDataToAllAgents(); 2564 SendAvatarDataToAllAgents();
2204 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2205 // So we're also sending a terse update (which has avatar rotation)
2206 // [Update] We do now.
2207 //SendTerseUpdateToAllClients(); 2565 //SendTerseUpdateToAllClients();
2208 } 2566 }
2567
2568 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2569 {
2570 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2571 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2572 if(hitYN)
2573 {
2574 // m_pos = Av offset from prim center to make look like on center
2575 // m_parentPosition = Actual center pos of prim
2576 // collisionPoint = spot on prim where we want to sit
2577 // collisionPoint.Z = global sit surface height
2578 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2579 Quaternion partIRot;
2580// if (part.LinkNum == 1)
2581/// { // Root prim of linkset
2582// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2583// }
2584// else
2585// { // single or child prim
2586 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2587// }
2588 if (m_initialSitTarget != null)
2589 {
2590 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2591 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2592 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2593 m_pos += offset;
2594 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2595 }
2596
2597 }
2598 } // End SitAltitudeCallback KF.
2209 2599
2210 /// <summary> 2600 /// <summary>
2211 /// Event handler for the 'Always run' setting on the client 2601 /// Event handler for the 'Always run' setting on the client
@@ -2235,12 +2625,13 @@ namespace OpenSim.Region.Framework.Scenes
2235 /// </summary> 2625 /// </summary>
2236 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2626 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2237 /// <param name="rotation">The direction in which this avatar should now face. 2627 /// <param name="rotation">The direction in which this avatar should now face.
2238 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2628 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2239 { 2629 {
2240 if (m_isChildAgent) 2630 if (m_isChildAgent)
2241 { 2631 {
2242 // WHAT??? 2632 // WHAT???
2243 m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!"); 2633 m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent");
2634
2244 return; 2635 return;
2245 } 2636 }
2246 2637
@@ -2249,15 +2640,26 @@ namespace OpenSim.Region.Framework.Scenes
2249 Rotation = rotation; 2640 Rotation = rotation;
2250 Vector3 direc = vec * rotation; 2641 Vector3 direc = vec * rotation;
2251 direc.Normalize(); 2642 direc.Normalize();
2643 PhysicsActor actor = m_physicsActor;
2644
2645 if (actor.Flying != m_flyingOld) // add for fly velocity control
2646 {
2647 m_flyingOld = actor.Flying; // add for fly velocity control
2648 if (!actor.Flying) m_wasFlying = true; // add for fly velocity control
2649 }
2650
2651 if (m_physicsActor.IsColliding == true) m_wasFlying = false; // add for fly velocity control
2652
2653 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2252 2654
2253 direc *= 0.03f * 128f * m_speedModifier; 2655 direc *= 0.03f * 128f * m_speedModifier;
2254 2656
2255 PhysicsActor actor = m_physicsActor;
2256 if (actor != null) 2657 if (actor != null)
2257 { 2658 {
2258 if (actor.Flying) 2659 if (actor.Flying)
2259 { 2660 {
2260 direc *= 4.0f; 2661// rm speed mod direc *= 4.0f;
2662 direc *= 5.2f; // for speed mod
2261 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2663 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
2262 //bool colliding = (m_physicsActor.IsColliding==true); 2664 //bool colliding = (m_physicsActor.IsColliding==true);
2263 //if (controlland) 2665 //if (controlland)
@@ -2270,22 +2672,34 @@ namespace OpenSim.Region.Framework.Scenes
2270 // m_log.Info("[AGENT]: Stop FLying"); 2672 // m_log.Info("[AGENT]: Stop FLying");
2271 //} 2673 //}
2272 } 2674 }
2675 if (Animator.m_falling && m_wasFlying) // if falling from flying, disable motion add
2676 {
2677 direc *= 0.0f;
2678 }
2679 /* This jumping section removed to SPA
2273 else if (!actor.Flying && actor.IsColliding) 2680 else if (!actor.Flying && actor.IsColliding)
2274 { 2681 {
2275 if (direc.Z > 2.0f) 2682 if (direc.Z > 2.0f)
2276 { 2683 {
2277 direc.Z *= 3.0f; 2684 if(m_animator.m_animTickJump == -1)
2278 2685 {
2279 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2686 direc.Z *= 3.0f; // jump
2280 Animator.TrySetMovementAnimation("PREJUMP"); 2687 }
2281 Animator.TrySetMovementAnimation("JUMP"); 2688 else
2689 {
2690 direc.Z *= 0.1f; // prejump
2691 }
2692 / * Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
2693 Animator.TrySetMovementAnimation("PREJUMP");
2694 Animator.TrySetMovementAnimation("JUMP");
2695 * /
2282 } 2696 }
2283 } 2697 } */
2284 } 2698 }
2285 2699
2286 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2700 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2287 m_forceToApply = direc; 2701 m_forceToApply = direc;
2288 2702 m_isNudging = Nudging;
2289 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2703 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2290 } 2704 }
2291 2705
@@ -2334,6 +2748,9 @@ namespace OpenSim.Region.Framework.Scenes
2334 2748
2335 CheckForSignificantMovement(); // sends update to the modules. 2749 CheckForSignificantMovement(); // sends update to the modules.
2336 } 2750 }
2751
2752 //Sending prim updates AFTER the avatar terse updates are sent
2753 SendPrimUpdates();
2337 } 2754 }
2338 2755
2339 #endregion 2756 #endregion
@@ -3143,6 +3560,7 @@ namespace OpenSim.Region.Framework.Scenes
3143 m_callbackURI = cAgent.CallbackURI; 3560 m_callbackURI = cAgent.CallbackURI;
3144 3561
3145 m_pos = cAgent.Position; 3562 m_pos = cAgent.Position;
3563
3146 m_velocity = cAgent.Velocity; 3564 m_velocity = cAgent.Velocity;
3147 m_CameraCenter = cAgent.Center; 3565 m_CameraCenter = cAgent.Center;
3148 m_CameraAtAxis = cAgent.AtAxis; 3566 m_CameraAtAxis = cAgent.AtAxis;
@@ -3265,20 +3683,45 @@ namespace OpenSim.Region.Framework.Scenes
3265 /// </summary> 3683 /// </summary>
3266 public override void UpdateMovement() 3684 public override void UpdateMovement()
3267 { 3685 {
3268 if (m_forceToApply.HasValue) 3686 if (Animator!=null) // add for jumping
3269 { 3687 { // add for jumping
3270 Vector3 force = m_forceToApply.Value; 3688 // if (!m_animator.m_jumping) // add for jumping
3689 // { // add for jumping
3271 3690
3272 m_updateflag = true; 3691 if (m_forceToApply.HasValue) // this section realigned
3273 3692 {
3274 // The magic constant 0.95f seems to make walking feel less jerky,
3275 // probably because it hackishly accounts for the overall latency of
3276 // these Velocity updates -- Diva
3277 Velocity = force * .95F;
3278 3693
3279 m_forceToApply = null; 3694 Vector3 force = m_forceToApply.Value;
3280 } 3695 m_updateflag = true;
3281 } 3696if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3697 Velocity = force;
3698//Console.WriteLine("UM1 {0}", Velocity);
3699 m_forceToApply = null;
3700 }
3701 else
3702 {
3703 if (m_isNudging)
3704 {
3705 Vector3 force = Vector3.Zero;
3706
3707 m_updateflag = true;
3708if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3709 Velocity = force;
3710//Console.WriteLine("UM2 {0}", Velocity);
3711 m_isNudging = false;
3712 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3713 }
3714 else // add for jumping
3715 { // add for jumping
3716 Vector3 force = Vector3.Zero; // add for jumping
3717if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3718//Console.WriteLine("UM3 {0}", Velocity);
3719 Velocity = force; // add for jumping
3720 }
3721 }
3722 // } // end realign
3723 } // add for jumping
3724 } // add for jumping
3282 3725
3283 /// <summary> 3726 /// <summary>
3284 /// Adds a physical representation of the avatar to the Physics plugin 3727 /// Adds a physical representation of the avatar to the Physics plugin
@@ -3292,10 +3735,8 @@ namespace OpenSim.Region.Framework.Scenes
3292 3735
3293 Vector3 pVec = AbsolutePosition; 3736 Vector3 pVec = AbsolutePosition;
3294 3737
3295 // Old bug where the height was in centimeters instead of meters
3296 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, 3738 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
3297 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying); 3739 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
3298
3299 scene.AddPhysicsActorTaint(m_physicsActor); 3740 scene.AddPhysicsActorTaint(m_physicsActor);
3300 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3741 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3301 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3742 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
@@ -3319,18 +3760,29 @@ namespace OpenSim.Region.Framework.Scenes
3319 { 3760 {
3320 if (e == null) 3761 if (e == null)
3321 return; 3762 return;
3322 3763
3323 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3764 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3324 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3325 // as of this comment the interval is set in AddToPhysicalScene 3765 // as of this comment the interval is set in AddToPhysicalScene
3326 if (Animator!=null) 3766 if (Animator!=null)
3327 Animator.UpdateMovementAnimations(); 3767 {
3768 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3769 { // else its will lock out other animation changes, like ground sit.
3770 Animator.UpdateMovementAnimations();
3771 m_updateCount--;
3772 }
3773 }
3328 3774
3329 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3775 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3330 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3776 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3331 3777
3332 CollisionPlane = Vector4.UnitW; 3778 CollisionPlane = Vector4.UnitW;
3333 3779
3780 if (m_lastColCount != coldata.Count)
3781 {
3782 m_updateCount = UPDATE_COUNT;
3783 m_lastColCount = coldata.Count;
3784 }
3785
3334 if (coldata.Count != 0 && Animator != null) 3786 if (coldata.Count != 0 && Animator != null)
3335 { 3787 {
3336 switch (Animator.CurrentMovementAnimation) 3788 switch (Animator.CurrentMovementAnimation)
@@ -3360,6 +3812,148 @@ namespace OpenSim.Region.Framework.Scenes
3360 } 3812 }
3361 } 3813 }
3362 3814
3815 List<uint> thisHitColliders = new List<uint>();
3816 List<uint> endedColliders = new List<uint>();
3817 List<uint> startedColliders = new List<uint>();
3818
3819 foreach (uint localid in coldata.Keys)
3820 {
3821 thisHitColliders.Add(localid);
3822 if (!m_lastColliders.Contains(localid))
3823 {
3824 startedColliders.Add(localid);
3825 }
3826 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3827 }
3828
3829 // calculate things that ended colliding
3830 foreach (uint localID in m_lastColliders)
3831 {
3832 if (!thisHitColliders.Contains(localID))
3833 {
3834 endedColliders.Add(localID);
3835 }
3836 }
3837 //add the items that started colliding this time to the last colliders list.
3838 foreach (uint localID in startedColliders)
3839 {
3840 m_lastColliders.Add(localID);
3841 }
3842 // remove things that ended colliding from the last colliders list
3843 foreach (uint localID in endedColliders)
3844 {
3845 m_lastColliders.Remove(localID);
3846 }
3847
3848 // do event notification
3849 if (startedColliders.Count > 0)
3850 {
3851 ColliderArgs StartCollidingMessage = new ColliderArgs();
3852 List<DetectedObject> colliding = new List<DetectedObject>();
3853 foreach (uint localId in startedColliders)
3854 {
3855 if (localId == 0)
3856 continue;
3857
3858 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3859 string data = "";
3860 if (obj != null)
3861 {
3862 DetectedObject detobj = new DetectedObject();
3863 detobj.keyUUID = obj.UUID;
3864 detobj.nameStr = obj.Name;
3865 detobj.ownerUUID = obj.OwnerID;
3866 detobj.posVector = obj.AbsolutePosition;
3867 detobj.rotQuat = obj.GetWorldRotation();
3868 detobj.velVector = obj.Velocity;
3869 detobj.colliderType = 0;
3870 detobj.groupUUID = obj.GroupID;
3871 colliding.Add(detobj);
3872 }
3873 }
3874
3875 if (colliding.Count > 0)
3876 {
3877 StartCollidingMessage.Colliders = colliding;
3878
3879 foreach (SceneObjectGroup att in Attachments)
3880 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3881 }
3882 }
3883
3884 if (endedColliders.Count > 0)
3885 {
3886 ColliderArgs EndCollidingMessage = new ColliderArgs();
3887 List<DetectedObject> colliding = new List<DetectedObject>();
3888 foreach (uint localId in endedColliders)
3889 {
3890 if (localId == 0)
3891 continue;
3892
3893 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3894 string data = "";
3895 if (obj != null)
3896 {
3897 DetectedObject detobj = new DetectedObject();
3898 detobj.keyUUID = obj.UUID;
3899 detobj.nameStr = obj.Name;
3900 detobj.ownerUUID = obj.OwnerID;
3901 detobj.posVector = obj.AbsolutePosition;
3902 detobj.rotQuat = obj.GetWorldRotation();
3903 detobj.velVector = obj.Velocity;
3904 detobj.colliderType = 0;
3905 detobj.groupUUID = obj.GroupID;
3906 colliding.Add(detobj);
3907 }
3908 }
3909
3910 if (colliding.Count > 0)
3911 {
3912 EndCollidingMessage.Colliders = colliding;
3913
3914 foreach (SceneObjectGroup att in Attachments)
3915 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
3916 }
3917 }
3918
3919 if (thisHitColliders.Count > 0)
3920 {
3921 ColliderArgs CollidingMessage = new ColliderArgs();
3922 List<DetectedObject> colliding = new List<DetectedObject>();
3923 foreach (uint localId in thisHitColliders)
3924 {
3925 if (localId == 0)
3926 continue;
3927
3928 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3929 string data = "";
3930 if (obj != null)
3931 {
3932 DetectedObject detobj = new DetectedObject();
3933 detobj.keyUUID = obj.UUID;
3934 detobj.nameStr = obj.Name;
3935 detobj.ownerUUID = obj.OwnerID;
3936 detobj.posVector = obj.AbsolutePosition;
3937 detobj.rotQuat = obj.GetWorldRotation();
3938 detobj.velVector = obj.Velocity;
3939 detobj.colliderType = 0;
3940 detobj.groupUUID = obj.GroupID;
3941 colliding.Add(detobj);
3942 }
3943 }
3944
3945 if (colliding.Count > 0)
3946 {
3947 CollidingMessage.Colliders = colliding;
3948
3949 lock (m_attachments)
3950 {
3951 foreach (SceneObjectGroup att in m_attachments)
3952 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
3953 }
3954 }
3955 }
3956
3363 if (m_invulnerable) 3957 if (m_invulnerable)
3364 return; 3958 return;
3365 3959
@@ -3785,6 +4379,39 @@ namespace OpenSim.Region.Framework.Scenes
3785 return; 4379 return;
3786 } 4380 }
3787 4381
4382 XmlDocument doc = new XmlDocument();
4383 string stateData = String.Empty;
4384
4385 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
4386 if (attServ != null)
4387 {
4388 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
4389 stateData = attServ.Get(ControllingClient.AgentId.ToString());
4390 if (stateData != String.Empty)
4391 {
4392 try
4393 {
4394 doc.LoadXml(stateData);
4395 }
4396 catch { }
4397 }
4398 }
4399
4400 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
4401
4402 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
4403 if (nodes.Count > 0)
4404 {
4405 foreach (XmlNode n in nodes)
4406 {
4407 XmlElement elem = (XmlElement)n;
4408 string itemID = elem.GetAttribute("ItemID");
4409 string xml = elem.InnerXml;
4410
4411 itemData[new UUID(itemID)] = xml;
4412 }
4413 }
4414
3788 List<AvatarAttachment> attachments = m_appearance.GetAttachments(); 4415 List<AvatarAttachment> attachments = m_appearance.GetAttachments();
3789 foreach (AvatarAttachment attach in attachments) 4416 foreach (AvatarAttachment attach in attachments)
3790 { 4417 {
@@ -3805,7 +4432,30 @@ namespace OpenSim.Region.Framework.Scenes
3805 4432
3806 try 4433 try
3807 { 4434 {
3808 m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); 4435 string xmlData;
4436 XmlDocument d = new XmlDocument();
4437 UUID asset;
4438 if (itemData.TryGetValue(itemID, out xmlData))
4439 {
4440 d.LoadXml(xmlData);
4441 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
4442
4443 // Rez from inventory
4444 asset
4445 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
4446
4447 }
4448 else
4449 {
4450 // Rez from inventory (with a null doc to let
4451 // CHANGED_OWNER happen)
4452 asset
4453 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
4454 }
4455
4456 m_log.InfoFormat(
4457 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2}",
4458 p, itemID, asset);
3809 } 4459 }
3810 catch (Exception e) 4460 catch (Exception e)
3811 { 4461 {
@@ -3838,6 +4488,15 @@ namespace OpenSim.Region.Framework.Scenes
3838 m_reprioritization_called = false; 4488 m_reprioritization_called = false;
3839 } 4489 }
3840 } 4490 }
4491
4492 private Vector3 Quat2Euler(Quaternion rot){
4493 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4494 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4495 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4496 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4497 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4498 return(new Vector3(x,y,z));
4499 }
3841 4500
3842 public void SaveChangedAttachments() 4501 public void SaveChangedAttachments()
3843 { 4502 {
@@ -3861,5 +4520,30 @@ namespace OpenSim.Region.Framework.Scenes
3861 } 4520 }
3862 } 4521 }
3863 } 4522 }
4523
4524 private void CheckLandingPoint(ref Vector3 pos)
4525 {
4526 // Never constrain lures
4527 if ((TeleportFlags & TeleportFlags.ViaLure) != 0)
4528 return;
4529
4530 if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
4531 return;
4532
4533 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
4534
4535 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
4536 land.LandData.UserLocation != Vector3.Zero &&
4537 land.LandData.OwnerID != m_uuid &&
4538 (!m_scene.Permissions.IsGod(m_uuid)) &&
4539 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)))
4540 {
4541 float curr = Vector3.Distance(AbsolutePosition, pos);
4542 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr)
4543 pos = land.LandData.UserLocation;
4544 else
4545 ControllingClient.SendAlertMessage("Can't teleport closer to destination");
4546 }
4547 }
3864 } 4548 }
3865} 4549}
diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
index 7c067ca..1f4ec96 100644
--- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
@@ -106,7 +106,7 @@ namespace OpenSim.Region.Framework.Scenes
106 g.ScheduleFullUpdateToAvatar(m_presence); 106 g.ScheduleFullUpdateToAvatar(m_presence);
107 } 107 }
108 108
109 while (m_partsUpdateQueue.Count > 0) 109 while (m_partsUpdateQueue.Count != null && m_partsUpdateQueue.Count > 0)
110 { 110 {
111 SceneObjectPart part = m_partsUpdateQueue.Dequeue(); 111 SceneObjectPart part = m_partsUpdateQueue.Dequeue();
112 112
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 57ae4fd..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 }
@@ -1441,12 +1441,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1441 { 1441 {
1442 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1442 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1443 1443
1444 if (reader.IsEmptyElement)
1445 {
1446 reader.Read();
1447 return tinv;
1448 }
1449
1450 reader.ReadStartElement(name, String.Empty); 1444 reader.ReadStartElement(name, String.Empty);
1451 1445
1452 while (reader.Name == "TaskInventoryItem") 1446 while (reader.Name == "TaskInventoryItem")
@@ -1480,12 +1474,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1480 { 1474 {
1481 PrimitiveBaseShape shape = new PrimitiveBaseShape(); 1475 PrimitiveBaseShape shape = new PrimitiveBaseShape();
1482 1476
1483 if (reader.IsEmptyElement)
1484 {
1485 reader.Read();
1486 return shape;
1487 }
1488
1489 reader.ReadStartElement(name, String.Empty); // Shape 1477 reader.ReadStartElement(name, String.Empty); // Shape
1490 1478
1491 string nodeName = string.Empty; 1479 string nodeName = string.Empty;
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
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 83906d7..3978a7d 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -86,10 +86,6 @@ namespace OpenSim.Region.Framework.Scenes
86 /// <param name="assetUuids">The assets gathered</param> 86 /// <param name="assetUuids">The assets gathered</param>
87 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 87 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids)
88 { 88 {
89 // avoid infinite loops
90 if (assetUuids.ContainsKey(assetUuid))
91 return;
92
93 try 89 try
94 { 90 {
95 assetUuids[assetUuid] = assetType; 91 assetUuids[assetUuid] = assetType;