aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/ScenePresence.cs
diff options
context:
space:
mode:
authorDavid Walter Seikel2016-11-03 21:44:39 +1000
committerDavid Walter Seikel2016-11-03 21:44:39 +1000
commit134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch)
tree216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Region/Framework/Scenes/ScenePresence.cs
parentMore changing to production grid. Double oops. (diff)
downloadopensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs2577
1 files changed, 1813 insertions, 764 deletions
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index a90872e..1fddd91 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -29,16 +29,19 @@ using System;
29using System.Xml; 29using System.Xml;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using System.Threading;
32using System.Timers; 33using System.Timers;
34using Timer = System.Timers.Timer;
33using OpenMetaverse; 35using OpenMetaverse;
34using log4net; 36using log4net;
35using Nini.Config; 37using Nini.Config;
36using OpenSim.Framework; 38using OpenSim.Framework;
37using OpenSim.Framework.Client; 39using OpenSim.Framework.Client;
40using OpenSim.Framework.Monitoring;
38using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes.Animation; 42using OpenSim.Region.Framework.Scenes.Animation;
40using OpenSim.Region.Framework.Scenes.Types; 43using OpenSim.Region.Framework.Scenes.Types;
41using OpenSim.Region.Physics.Manager; 44using OpenSim.Region.PhysicsModules.SharedBase;
42using GridRegion = OpenSim.Services.Interfaces.GridRegion; 45using GridRegion = OpenSim.Services.Interfaces.GridRegion;
43using OpenSim.Services.Interfaces; 46using OpenSim.Services.Interfaces;
44using TeleportFlags = OpenSim.Framework.Constants.TeleportFlags; 47using TeleportFlags = OpenSim.Framework.Constants.TeleportFlags;
@@ -63,6 +66,7 @@ namespace OpenSim.Region.Framework.Scenes
63 66
64 struct ScriptControllers 67 struct ScriptControllers
65 { 68 {
69 public UUID objectID;
66 public UUID itemID; 70 public UUID itemID;
67 public ScriptControlled ignoreControls; 71 public ScriptControlled ignoreControls;
68 public ScriptControlled eventControls; 72 public ScriptControlled eventControls;
@@ -72,21 +76,51 @@ namespace OpenSim.Region.Framework.Scenes
72 76
73 public class ScenePresence : EntityBase, IScenePresence 77 public class ScenePresence : EntityBase, IScenePresence
74 { 78 {
79 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
80 private static readonly String LogHeader = "[SCENE PRESENCE]";
81
75// ~ScenePresence() 82// ~ScenePresence()
76// { 83// {
77// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); 84// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
78// } 85// }
79 86
80 private void TriggerScenePresenceUpdated() 87 public void TriggerScenePresenceUpdated()
81 { 88 {
82 if (m_scene != null) 89 if (m_scene != null)
83 m_scene.EventManager.TriggerScenePresenceUpdated(this); 90 m_scene.EventManager.TriggerScenePresenceUpdated(this);
84 } 91 }
85 92
86 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
87
88 public PresenceType PresenceType { get; private set; } 93 public PresenceType PresenceType { get; private set; }
89 94
95 private ScenePresenceStateMachine m_stateMachine;
96
97 /// <summary>
98 /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine
99 /// for more details.
100 /// </summary>
101 public ScenePresenceState LifecycleState
102 {
103 get
104 {
105 return m_stateMachine.GetState();
106 }
107
108 set
109 {
110 m_stateMachine.SetState(value);
111 }
112 }
113
114 /// <summary>
115 /// This exists to prevent race conditions between two CompleteMovement threads if the simulator is slow and
116 /// the viewer fires these in quick succession.
117 /// </summary>
118 /// <remarks>
119 /// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement
120 /// regulation done there.
121 /// </remarks>
122 private object m_completeMovementLock = new object();
123
90// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 124// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
91 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); 125 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
92 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); 126 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
@@ -99,7 +133,7 @@ namespace OpenSim.Region.Framework.Scenes
99 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 133 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
100 /// issue #1716 134 /// issue #1716
101 /// </summary> 135 /// </summary>
102 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); 136 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f);
103 137
104 /// <summary> 138 /// <summary>
105 /// Movement updates for agents in neighboring regions are sent directly to clients. 139 /// Movement updates for agents in neighboring regions are sent directly to clients.
@@ -139,6 +173,10 @@ namespace OpenSim.Region.Framework.Scenes
139 private Vector3 m_lastPosition; 173 private Vector3 m_lastPosition;
140 private Quaternion m_lastRotation; 174 private Quaternion m_lastRotation;
141 private Vector3 m_lastVelocity; 175 private Vector3 m_lastVelocity;
176 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f);
177
178 private bool m_followCamAuto = false;
179
142 180
143 private Vector3? m_forceToApply; 181 private Vector3? m_forceToApply;
144 private int m_userFlags; 182 private int m_userFlags;
@@ -196,10 +234,15 @@ namespace OpenSim.Region.Framework.Scenes
196 private float m_sitAvatarHeight = 2.0f; 234 private float m_sitAvatarHeight = 2.0f;
197 235
198 private Vector3 m_lastChildAgentUpdatePosition; 236 private Vector3 m_lastChildAgentUpdatePosition;
199 private Vector3 m_lastChildAgentUpdateCamPosition; 237// private Vector3 m_lastChildAgentUpdateCamPosition;
200 238
201 private const int LAND_VELOCITYMAG_MAX = 12; 239 private const int LAND_VELOCITYMAG_MAX = 12;
202 240
241 private const float FLY_ROLL_MAX_RADIANS = 1.1f;
242
243 private const float FLY_ROLL_RADIANS_PER_UPDATE = 0.06f;
244 private const float FLY_ROLL_RESET_RADIANS_PER_UPDATE = 0.02f;
245
203 private float m_health = 100f; 246 private float m_health = 100f;
204 247
205 protected ulong crossingFromRegion; 248 protected ulong crossingFromRegion;
@@ -221,8 +264,6 @@ namespace OpenSim.Region.Framework.Scenes
221 /// </summary> 264 /// </summary>
222 public bool LandAtTarget { get; private set; } 265 public bool LandAtTarget { get; private set; }
223 266
224 private bool m_followCamAuto;
225
226 private int m_movementUpdateCount; 267 private int m_movementUpdateCount;
227 private const int NumMovementsBetweenRayCast = 5; 268 private const int NumMovementsBetweenRayCast = 5;
228 269
@@ -230,6 +271,10 @@ namespace OpenSim.Region.Framework.Scenes
230 //private int m_moveToPositionStateStatus; 271 //private int m_moveToPositionStateStatus;
231 //***************************************************** 272 //*****************************************************
232 273
274 private int m_movementAnimationUpdateCounter = 0;
275
276 public Vector3 PrevSitOffset { get; set; }
277
233 protected AvatarAppearance m_appearance; 278 protected AvatarAppearance m_appearance;
234 279
235 public AvatarAppearance Appearance 280 public AvatarAppearance Appearance
@@ -242,6 +287,8 @@ namespace OpenSim.Region.Framework.Scenes
242 } 287 }
243 } 288 }
244 289
290 public bool SentInitialDataToClient { get; private set; }
291
245 /// <summary> 292 /// <summary>
246 /// Copy of the script states while the agent is in transit. This state may 293 /// Copy of the script states while the agent is in transit. This state may
247 /// need to be placed back in case of transfer fail. 294 /// need to be placed back in case of transfer fail.
@@ -276,9 +323,43 @@ namespace OpenSim.Region.Framework.Scenes
276 /// </summary> 323 /// </summary>
277 private Vector3 posLastSignificantMove; 324 private Vector3 posLastSignificantMove;
278 325
279 // For teleports and crossings callbacks 326 #region For teleports and crossings callbacks
280 string m_callbackURI; 327
281 UUID m_originRegionID; 328 /// <summary>
329 /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address.
330 /// </summary>
331 private string m_callbackURI;
332
333 /// <summary>
334 /// Records the region from which this presence originated, if not from login.
335 /// </summary>
336 /// <remarks>
337 /// Also acts as a signal in the teleport V2 process to release UpdateAgent after a viewer has triggered
338 /// CompleteMovement and made the previous child agent a root agent.
339 /// </remarks>
340 private UUID m_originRegionID;
341
342 /// <summary>
343 /// This object is used as a lock before accessing m_originRegionID to make sure that every thread is seeing
344 /// the very latest value and not using some cached version. Cannot make m_originRegionID itself volatite as
345 /// it is a value type.
346 /// </summary>
347 private object m_originRegionIDAccessLock = new object();
348
349 /// <summary>
350 /// Triggered on entity transfer after to allow CompleteMovement() to proceed after we have received an
351 /// UpdateAgent from the originating region.ddkjjkj
352 /// </summary>
353 private AutoResetEvent m_updateAgentReceivedAfterTransferEvent = new AutoResetEvent(false);
354
355 /// <summary>
356 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
357 /// teleport is reusing the connection.
358 /// </summary>
359 /// <remarks>May be refactored or move somewhere else soon.</remarks>
360 public bool DoNotCloseAfterTeleport { get; set; }
361
362 #endregion
282 363
283 /// <value> 364 /// <value>
284 /// Script engines present in the scene 365 /// Script engines present in the scene
@@ -295,15 +376,17 @@ namespace OpenSim.Region.Framework.Scenes
295 /// <summary> 376 /// <summary>
296 /// Record user movement inputs. 377 /// Record user movement inputs.
297 /// </summary> 378 /// </summary>
298 public byte MovementFlag { get; private set; } 379 public uint MovementFlag { get; private set; }
299 380
300 private bool m_updateflag; 381 /// <summary>
382 /// Set this if we need to force a movement update on the next received AgentUpdate from the viewer.
383 /// </summary>
384 private const uint ForceUpdateMovementFlagValue = uint.MaxValue;
301 385
302 public bool Updated 386 /// <summary>
303 { 387 /// Is the agent stop control flag currently active?
304 set { m_updateflag = value; } 388 /// </summary>
305 get { return m_updateflag; } 389 public bool AgentControlStopActive { get; private set; }
306 }
307 390
308 private bool m_invulnerable = true; 391 private bool m_invulnerable = true;
309 392
@@ -344,6 +427,9 @@ namespace OpenSim.Region.Framework.Scenes
344 /// </summary> 427 /// </summary>
345 protected Vector3 m_lastCameraPosition; 428 protected Vector3 m_lastCameraPosition;
346 429
430 private Vector4 m_lastCameraCollisionPlane = new Vector4(0f, 0f, 0f, 1);
431 private bool m_doingCamRayCast = false;
432
347 public Vector3 CameraPosition { get; set; } 433 public Vector3 CameraPosition { get; set; }
348 434
349 public Quaternion CameraRotation 435 public Quaternion CameraRotation
@@ -375,7 +461,19 @@ namespace OpenSim.Region.Framework.Scenes
375 public string Firstname { get; private set; } 461 public string Firstname { get; private set; }
376 public string Lastname { get; private set; } 462 public string Lastname { get; private set; }
377 463
378 public string Grouptitle { get; set; } 464 public string Grouptitle
465 {
466 get { return UseFakeGroupTitle ? "(Loading)" : m_groupTitle; }
467 set { m_groupTitle = value; }
468 }
469 private string m_groupTitle;
470
471 /// <summary>
472 /// When this is 'true', return a dummy group title instead of the real group title. This is
473 /// used as part of a hack to force viewers to update the displayed avatar name.
474 /// </summary>
475 public bool UseFakeGroupTitle { get; set; }
476
379 477
380 // Agent's Draw distance. 478 // Agent's Draw distance.
381 public float DrawDistance { get; set; } 479 public float DrawDistance { get; set; }
@@ -424,7 +522,9 @@ namespace OpenSim.Region.Framework.Scenes
424 get { return (IClientCore)ControllingClient; } 522 get { return (IClientCore)ControllingClient; }
425 } 523 }
426 524
427 public Vector3 ParentPosition { get; set; } 525 public UUID COF { get; set; }
526
527// public Vector3 ParentPosition { get; set; }
428 528
429 /// <summary> 529 /// <summary>
430 /// Position of this avatar relative to the region the avatar is in 530 /// Position of this avatar relative to the region the avatar is in
@@ -437,12 +537,13 @@ namespace OpenSim.Region.Framework.Scenes
437 { 537 {
438 m_pos = PhysicsActor.Position; 538 m_pos = PhysicsActor.Position;
439 539
440 //m_log.DebugFormat( 540// m_log.DebugFormat(
441 // "[SCENE PRESENCE]: Set position {0} for {1} in {2} via getting AbsolutePosition!", 541// "[SCENE PRESENCE]: Set position of {0} in {1} to {2} via getting AbsolutePosition!",
442 // m_pos, Name, Scene.RegionInfo.RegionName); 542// Name, Scene.Name, m_pos);
443 } 543 }
444 else 544 else
445 { 545 {
546// m_log.DebugFormat("[SCENE PRESENCE]: Fetching abs pos where PhysicsActor == null and parent part {0} for {1}", Name, Scene.Name);
446 // Obtain the correct position of a seated avatar. 547 // Obtain the correct position of a seated avatar.
447 // In addition to providing the correct position while 548 // In addition to providing the correct position while
448 // the avatar is seated, this value will also 549 // the avatar is seated, this value will also
@@ -459,13 +560,16 @@ namespace OpenSim.Region.Framework.Scenes
459 SceneObjectPart sitPart = ParentPart; 560 SceneObjectPart sitPart = ParentPart;
460 561
461 if (sitPart != null) 562 if (sitPart != null)
462 return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation()); 563 return sitPart.ParentGroup.AbsolutePosition + (m_pos * sitPart.GetWorldRotation());
463 } 564 }
464 565
465 return m_pos; 566 return m_pos;
466 } 567 }
467 set 568 set
468 { 569 {
570// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} to {1} in {2}", Name, value, Scene.Name);
571// Util.PrintCallStack();
572
469 if (PhysicsActor != null) 573 if (PhysicsActor != null)
470 { 574 {
471 try 575 try
@@ -480,10 +584,7 @@ namespace OpenSim.Region.Framework.Scenes
480 584
481 // Don't update while sitting. The PhysicsActor above is null whilst sitting. 585 // Don't update while sitting. The PhysicsActor above is null whilst sitting.
482 if (ParentID == 0) 586 if (ParentID == 0)
483 {
484 m_pos = value; 587 m_pos = value;
485 ParentPosition = Vector3.Zero;
486 }
487 588
488 //m_log.DebugFormat( 589 //m_log.DebugFormat(
489 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", 590 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}",
@@ -513,8 +614,11 @@ namespace OpenSim.Region.Framework.Scenes
513 } 614 }
514 615
515 /// <summary> 616 /// <summary>
516 /// Current velocity of the avatar. 617 /// Velocity of the avatar with respect to its local reference frame.
517 /// </summary> 618 /// </summary>
619 /// <remarks>
620 /// So when sat on a vehicle this will be 0. To get velocity with respect to the world use GetWorldVelocity()
621 /// </remarks>
518 public override Vector3 Velocity 622 public override Vector3 Velocity
519 { 623 {
520 get 624 get
@@ -527,11 +631,21 @@ namespace OpenSim.Region.Framework.Scenes
527// "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", 631// "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!",
528// m_velocity, Name, Scene.RegionInfo.RegionName); 632// m_velocity, Name, Scene.RegionInfo.RegionName);
529 } 633 }
634// else if (ParentPart != null)
635// {
636// return ParentPart.ParentGroup.Velocity;
637// }
530 638
531 return m_velocity; 639 return m_velocity;
532 } 640 }
641
533 set 642 set
534 { 643 {
644// Util.PrintCallStack();
645// m_log.DebugFormat(
646// "[SCENE PRESENCE]: In {0} set velocity of {1} to {2}",
647// Scene.RegionInfo.RegionName, Name, value);
648
535 if (PhysicsActor != null) 649 if (PhysicsActor != null)
536 { 650 {
537 try 651 try
@@ -544,37 +658,86 @@ namespace OpenSim.Region.Framework.Scenes
544 } 658 }
545 } 659 }
546 660
547 m_velocity = value; 661 m_velocity = value;
548
549// m_log.DebugFormat(
550// "[SCENE PRESENCE]: In {0} set velocity of {1} to {2}",
551// Scene.RegionInfo.RegionName, Name, m_velocity);
552 } 662 }
553 } 663 }
664/*
665 public override Vector3 AngularVelocity
666 {
667 get
668 {
669 if (PhysicsActor != null)
670 {
671 m_rotationalvelocity = PhysicsActor.RotationalVelocity;
672
673 // m_log.DebugFormat(
674 // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!",
675 // m_velocity, Name, Scene.RegionInfo.RegionName);
676 }
554 677
678 return m_rotationalvelocity;
679 }
680 }
681*/
555 private Quaternion m_bodyRot = Quaternion.Identity; 682 private Quaternion m_bodyRot = Quaternion.Identity;
556 683
684 /// <summary>
685 /// The rotation of the avatar.
686 /// </summary>
687 /// <remarks>
688 /// If the avatar is not sitting, this is with respect to the world
689 /// If the avatar is sitting, this is a with respect to the part that it's sitting upon (a local rotation).
690 /// If you always want the world rotation, use GetWorldRotation()
691 /// </remarks>
557 public Quaternion Rotation 692 public Quaternion Rotation
558 { 693 {
559 get { return m_bodyRot; } 694 get
695 {
696 return m_bodyRot;
697 }
698
560 set 699 set
561 { 700 {
562 m_bodyRot = value; 701 m_bodyRot = value;
702
563 if (PhysicsActor != null) 703 if (PhysicsActor != null)
564 { 704 {
565 PhysicsActor.Orientation = m_bodyRot; 705 try
706 {
707 PhysicsActor.Orientation = m_bodyRot;
708 }
709 catch (Exception e)
710 {
711 m_log.Error("[SCENE PRESENCE]: Orientation " + e.Message);
712 }
566 } 713 }
567// m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot); 714// m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot);
568 } 715 }
569 } 716 }
570 717
718 // Used for limited viewer 'fake' user rotations.
719 private Vector3 m_AngularVelocity = Vector3.Zero;
720
721 public Vector3 AngularVelocity
722 {
723 get { return m_AngularVelocity; }
724 }
725
571 public bool IsChildAgent { get; set; } 726 public bool IsChildAgent { get; set; }
727 public bool IsLoggingIn { get; set; }
572 728
573 /// <summary> 729 /// <summary>
574 /// If the avatar is sitting, the local ID of the prim that it's sitting on. If not sitting then zero. 730 /// If the avatar is sitting, the local ID of the prim that it's sitting on. If not sitting then zero.
575 /// </summary> 731 /// </summary>
576 public uint ParentID { get; set; } 732 public uint ParentID { get; set; }
577 733
734 public UUID ParentUUID
735 {
736 get { return m_parentUUID; }
737 set { m_parentUUID = value; }
738 }
739 private UUID m_parentUUID = UUID.Zero;
740
578 /// <summary> 741 /// <summary>
579 /// Are we sitting on an object? 742 /// Are we sitting on an object?
580 /// </summary> 743 /// </summary>
@@ -595,6 +758,33 @@ namespace OpenSim.Region.Framework.Scenes
595 set { m_health = value; } 758 set { m_health = value; }
596 } 759 }
597 760
761 /// <summary>
762 /// Get rotation relative to the world.
763 /// </summary>
764 /// <returns></returns>
765 public Quaternion GetWorldRotation()
766 {
767 SceneObjectPart sitPart = ParentPart;
768
769 if (sitPart != null)
770 return sitPart.GetWorldRotation() * Rotation;
771
772 return Rotation;
773 }
774
775 /// <summary>
776 /// Get velocity relative to the world.
777 /// </summary>
778 public Vector3 GetWorldVelocity()
779 {
780 SceneObjectPart sitPart = ParentPart;
781
782 if (sitPart != null)
783 return sitPart.ParentGroup.Velocity;
784
785 return Velocity;
786 }
787
598 public void AdjustKnownSeeds() 788 public void AdjustKnownSeeds()
599 { 789 {
600 Dictionary<ulong, string> seeds; 790 Dictionary<ulong, string> seeds;
@@ -608,9 +798,8 @@ namespace OpenSim.Region.Framework.Scenes
608 foreach (ulong handle in seeds.Keys) 798 foreach (ulong handle in seeds.Keys)
609 { 799 {
610 uint x, y; 800 uint x, y;
611 Utils.LongToUInts(handle, out x, out y); 801 Util.RegionHandleToRegionLoc(handle, out x, out y);
612 x = x / Constants.RegionSize; 802
613 y = y / Constants.RegionSize;
614 if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY)) 803 if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
615 { 804 {
616 old.Add(handle); 805 old.Add(handle);
@@ -632,18 +821,22 @@ namespace OpenSim.Region.Framework.Scenes
632 foreach (KeyValuePair<ulong, string> kvp in KnownRegions) 821 foreach (KeyValuePair<ulong, string> kvp in KnownRegions)
633 { 822 {
634 uint x, y; 823 uint x, y;
635 Utils.LongToUInts(kvp.Key, out x, out y); 824 Util.RegionHandleToRegionLoc(kvp.Key, out x, out y);
636 x = x / Constants.RegionSize;
637 y = y / Constants.RegionSize;
638 m_log.Info(" >> "+x+", "+y+": "+kvp.Value); 825 m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
639 } 826 }
640 } 827 }
641 828
642 private bool m_mouseLook; 829 private bool m_mouseLook;
643 private bool m_leftButtonDown; 830// private bool m_leftButtonDown;
644 831
645 private bool m_inTransit; 832 private bool m_inTransit;
646 833
834 /// <summary>
835 /// This signals whether the presence is in transit between neighbouring regions.
836 /// </summary>
837 /// <remarks>
838 /// It is not set when the presence is teleporting or logging in/out directly to a region.
839 /// </remarks>
647 public bool IsInTransit 840 public bool IsInTransit
648 { 841 {
649 get { return m_inTransit; } 842 get { return m_inTransit; }
@@ -667,6 +860,14 @@ namespace OpenSim.Region.Framework.Scenes
667 set { m_speedModifier = value; } 860 set { m_speedModifier = value; }
668 } 861 }
669 862
863 /// <summary>
864 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running
865 /// </summary>
866 /// <remarks>
867 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers.
868 /// </remarks>
869 private float AgentControlStopSlowWhilstMoving = 0.5f;
870
670 private bool m_forceFly; 871 private bool m_forceFly;
671 872
672 public bool ForceFly 873 public bool ForceFly
@@ -685,23 +886,30 @@ namespace OpenSim.Region.Framework.Scenes
685 886
686 public string Viewer 887 public string Viewer
687 { 888 {
688 get { return m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode).Viewer; } 889 get { return Util.GetViewerName(m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode)); }
689 } 890 }
690 891
892 /// <summary>
893 /// Count of how many terse updates we have sent out. It doesn't matter if this overflows.
894 /// </summary>
895 private int m_terseUpdateCount;
896
691 #endregion 897 #endregion
692 898
693 #region Constructor(s) 899 #region Constructor(s)
694 900
695 public ScenePresence( 901 public ScenePresence(
696 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) 902 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
697 { 903 {
698 AttachmentsSyncLock = new Object(); 904 AttachmentsSyncLock = new Object();
699 AllowMovement = true; 905 AllowMovement = true;
700 IsChildAgent = true; 906 IsChildAgent = true;
907 IsLoggingIn = false;
701 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; 908 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault;
702 Animator = new ScenePresenceAnimator(this); 909 Animator = new ScenePresenceAnimator(this);
703 PresenceType = type; 910 PresenceType = type;
704 DrawDistance = world.DefaultDrawDistance; 911 // DrawDistance = world.DefaultDrawDistance;
912 DrawDistance = Constants.RegionSize;
705 RegionHandle = world.RegionInfo.RegionHandle; 913 RegionHandle = world.RegionInfo.RegionHandle;
706 ControllingClient = client; 914 ControllingClient = client;
707 Firstname = ControllingClient.FirstName; 915 Firstname = ControllingClient.FirstName;
@@ -739,12 +947,42 @@ namespace OpenSim.Region.Framework.Scenes
739 SetDirectionVectors(); 947 SetDirectionVectors();
740 948
741 Appearance = appearance; 949 Appearance = appearance;
950
951 m_stateMachine = new ScenePresenceStateMachine(this);
952 }
953
954 private void RegionHeartbeatEnd(Scene scene)
955 {
956 if (IsChildAgent)
957 return;
958
959 m_movementAnimationUpdateCounter ++;
960 if (m_movementAnimationUpdateCounter >= 2)
961 {
962 m_movementAnimationUpdateCounter = 0;
963 if (Animator != null)
964 {
965 // If the parentID == 0 we are not sitting
966 // if !SitGournd then we are not sitting on the ground
967 // Fairly straightforward, now here comes the twist
968 // if ParentUUID is NOT UUID.Zero, we are looking to
969 // be sat on an object that isn't there yet. Should
970 // be treated as if sat.
971 if(ParentID == 0 && !SitGround && ParentUUID == UUID.Zero) // skip it if sitting
972 Animator.UpdateMovementAnimations();
973 }
974 else
975 {
976 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
977 }
978 }
742 } 979 }
743 980
744 public void RegisterToEvents() 981 public void RegisterToEvents()
745 { 982 {
746 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 983 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
747 ControllingClient.OnAgentUpdate += HandleAgentUpdate; 984 ControllingClient.OnAgentUpdate += HandleAgentUpdate;
985 ControllingClient.OnAgentCameraUpdate += HandleAgentCamerasUpdate;
748 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; 986 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit;
749 ControllingClient.OnAgentSit += HandleAgentSit; 987 ControllingClient.OnAgentSit += HandleAgentSit;
750 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 988 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
@@ -772,23 +1010,6 @@ namespace OpenSim.Region.Framework.Scenes
772 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 1010 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
773 } 1011 }
774 1012
775 private Vector3[] GetWalkDirectionVectors()
776 {
777 Vector3[] vector = new Vector3[11];
778 vector[0] = new Vector3(CameraUpAxis.Z, 0f, -CameraAtAxis.Z); //FORWARD
779 vector[1] = new Vector3(-CameraUpAxis.Z, 0f, CameraAtAxis.Z); //BACK
780 vector[2] = Vector3.UnitY; //LEFT
781 vector[3] = -Vector3.UnitY; //RIGHT
782 vector[4] = new Vector3(CameraAtAxis.Z, 0f, CameraUpAxis.Z); //UP
783 vector[5] = new Vector3(-CameraAtAxis.Z, 0f, -CameraUpAxis.Z); //DOWN
784 vector[6] = new Vector3(CameraUpAxis.Z, 0f, -CameraAtAxis.Z); //FORWARD_NUDGE
785 vector[7] = new Vector3(-CameraUpAxis.Z, 0f, CameraAtAxis.Z); //BACK_NUDGE
786 vector[8] = Vector3.UnitY; //LEFT_NUDGE
787 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
788 vector[10] = new Vector3(-CameraAtAxis.Z, 0f, -CameraUpAxis.Z); //DOWN_NUDGE
789 return vector;
790 }
791
792 #endregion 1013 #endregion
793 1014
794 #region Status Methods 1015 #region Status Methods
@@ -796,6 +1017,7 @@ namespace OpenSim.Region.Framework.Scenes
796 /// <summary> 1017 /// <summary>
797 /// Turns a child agent into a root agent. 1018 /// Turns a child agent into a root agent.
798 /// </summary> 1019 /// </summary>
1020 /// <remarks>
799 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the 1021 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the
800 /// avatar is actual in the sim. They can perform all actions. 1022 /// avatar is actual in the sim. They can perform all actions.
801 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim, 1023 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim,
@@ -803,80 +1025,188 @@ namespace OpenSim.Region.Framework.Scenes
803 /// 1025 ///
804 /// This method is on the critical path for transferring an avatar from one region to another. Delay here 1026 /// This method is on the critical path for transferring an avatar from one region to another. Delay here
805 /// delays that crossing. 1027 /// delays that crossing.
806 /// </summary> 1028 /// </remarks>
807 public void MakeRootAgent(Vector3 pos, bool isFlying) 1029 private bool MakeRootAgent(Vector3 pos, bool isFlying)
808 { 1030 {
809 m_log.DebugFormat( 1031 lock (m_completeMovementLock)
810 "[SCENE]: Upgrading child to root agent for {0} in {1}", 1032 {
811 Name, m_scene.RegionInfo.RegionName); 1033 if (!IsChildAgent)
1034 return false;
1035
1036 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1037
1038 // m_log.InfoFormat(
1039 // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1040 // Name, m_scene.RegionInfo.RegionName);
1041
1042 if (ParentUUID != UUID.Zero)
1043 {
1044 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
1045 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
1046 if (part == null)
1047 {
1048 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1049 }
1050 else
1051 {
1052 part.AddSittingAvatar(this);
1053 // ParentPosition = part.GetWorldPosition();
1054 ParentID = part.LocalId;
1055 ParentPart = part;
1056 m_pos = PrevSitOffset;
1057 // pos = ParentPosition;
1058 pos = part.GetWorldPosition();
1059 }
1060 ParentUUID = UUID.Zero;
1061
1062 // Animator.TrySetMovementAnimation("SIT");
1063 }
1064 else
1065 {
1066 IsLoggingIn = false;
1067 }
812 1068
813 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); 1069 IsChildAgent = false;
1070 }
814 1071
815 bool wasChild = IsChildAgent; 1072 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
816 IsChildAgent = false; 1073 // set and prevent the close of the connection on a subsequent re-teleport.
1074 // Should not be needed if we are not trying to tell this region to close
1075// DoNotCloseAfterTeleport = false;
817 1076
818 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1077 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
819 if (gm != null) 1078 if (gm != null)
820 Grouptitle = gm.GetGroupTitle(m_uuid); 1079 Grouptitle = gm.GetGroupTitle(m_uuid);
821 1080
1081 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode);
1082 uint teleportFlags = (aCircuit == null) ? 0 : aCircuit.teleportFlags;
1083 if ((teleportFlags & (uint)TeleportFlags.ViaHGLogin) != 0)
1084 {
1085 // The avatar is arriving from another grid. This means that we may have changed the
1086 // avatar's name to or from the special Hypergrid format ("First.Last @grid.example.com").
1087 // Unfortunately, due to a viewer bug, viewers don't always show the new name.
1088 // But we have a trick that can force them to update the name anyway.
1089 ForceViewersUpdateName();
1090 }
1091
822 RegionHandle = m_scene.RegionInfo.RegionHandle; 1092 RegionHandle = m_scene.RegionInfo.RegionHandle;
823 1093
824 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 1094 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
825 1095
826 // Moved this from SendInitialData to ensure that Appearance is initialized 1096 UUID groupUUID = ControllingClient.ActiveGroupId;
827 // before the inventory is processed in MakeRootAgent. This fixes a race condition 1097 string groupName = string.Empty;
828 // related to the handling of attachments 1098 ulong groupPowers = 0;
829 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance); 1099
830 if (m_scene.TestBorderCross(pos, Cardinals.E)) 1100 // ----------------------------------
1101 // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status
1102 try
831 { 1103 {
832 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 1104 if (groupUUID != UUID.Zero && gm != null)
833 pos.X = crossedBorder.BorderLine.Z - 1; 1105 {
834 } 1106 GroupRecord record = gm.GetGroupRecord(groupUUID);
1107 if (record != null)
1108 groupName = record.GroupName;
1109
1110 GroupMembershipData groupMembershipData = gm.GetMembershipData(groupUUID, m_uuid);
835 1111
836 if (m_scene.TestBorderCross(pos, Cardinals.N)) 1112 if (groupMembershipData != null)
1113 groupPowers = groupMembershipData.GroupPowers;
1114 }
1115
1116 ControllingClient.SendAgentDataUpdate(
1117 m_uuid, groupUUID, Firstname, Lastname, groupPowers, groupName, Grouptitle);
1118 }
1119 catch (Exception e)
837 { 1120 {
838 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 1121 m_log.Error("[AGENTUPDATE]: Error ", e);
839 pos.Y = crossedBorder.BorderLine.Z - 1;
840 } 1122 }
1123 // ------------------------------------
841 1124
842 CheckAndAdjustLandingPoint(ref pos); 1125 if (ParentID == 0)
843
844 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
845 { 1126 {
846 m_log.WarnFormat( 1127 // Moved this from SendInitialData to ensure that Appearance is initialized
847 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", 1128 // before the inventory is processed in MakeRootAgent. This fixes a race condition
848 pos, Name, UUID); 1129 // related to the handling of attachments
1130 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
1131
1132 /* RA 20140111: Commented out these TestBorderCross's.
1133 * Not sure why this code is here. It is not checking all the borders
1134 * and 'in region' sanity checking is done in CheckAndAdjustLandingPoint and below.
1135 if (m_scene.TestBorderCross(pos, Cardinals.E))
1136 {
1137 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
1138 pos.X = crossedBorder.BorderLine.Z - 1;
1139 }
849 1140
850 if (pos.X < 0f) pos.X = 0f; 1141 if (m_scene.TestBorderCross(pos, Cardinals.N))
851 if (pos.Y < 0f) pos.Y = 0f; 1142 {
852 if (pos.Z < 0f) pos.Z = 0f; 1143 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
853 } 1144 pos.Y = crossedBorder.BorderLine.Z - 1;
1145 }
1146 */
854 1147
855 float localAVHeight = 1.56f; 1148 CheckAndAdjustLandingPoint(ref pos);
856 if (Appearance.AvatarHeight > 0)
857 localAVHeight = Appearance.AvatarHeight;
858 1149
859 float posZLimit = 0; 1150 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
1151 {
1152 m_log.WarnFormat(
1153 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
1154 pos, Name, UUID);
860 1155
861 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 1156 if (pos.X < 0f) pos.X = 0f;
862 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 1157 if (pos.Y < 0f) pos.Y = 0f;
863 1158 if (pos.Z < 0f) pos.Z = 0f;
864 float newPosZ = posZLimit + localAVHeight / 2; 1159 }
865 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
866 {
867 pos.Z = newPosZ;
868 }
869 AbsolutePosition = pos;
870 1160
871 AddToPhysicalScene(isFlying); 1161 float localAVHeight = 1.56f;
1162 if (Appearance.AvatarHeight > 0)
1163 localAVHeight = Appearance.AvatarHeight;
872 1164
873 if (ForceFly) 1165 float posZLimit = 0;
874 { 1166
875 Flying = true; 1167 if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY)
876 } 1168 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
877 else if (FlyDisabled) 1169
878 { 1170 float newPosZ = posZLimit + localAVHeight / 2;
879 Flying = false; 1171 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
1172 {
1173 pos.Z = newPosZ;
1174 }
1175 AbsolutePosition = pos;
1176
1177// m_log.DebugFormat(
1178// "Set pos {0}, vel {1} in {1} to {2} from input position of {3} on MakeRootAgent",
1179// Name, Scene.Name, AbsolutePosition, pos);
1180//
1181 if (m_teleportFlags == TeleportFlags.Default)
1182 {
1183 AddToPhysicalScene(isFlying);
1184//
1185// Console.WriteLine(
1186// "Set velocity of {0} in {1} to {2} from input velocity of {3} on MakeRootAgent",
1187// Name, Scene.Name, PhysicsActor.Velocity, vel);
1188// }
1189 }
1190 else
1191 {
1192 AddToPhysicalScene(isFlying);
1193 }
1194
1195 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a
1196 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it
1197 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset
1198 // the value to a negative position which does not trigger the border cross.
1199 // This may not be the best location for this.
1200 CheckForBorderCrossing();
1201
1202 if (ForceFly)
1203 {
1204 Flying = true;
1205 }
1206 else if (FlyDisabled)
1207 {
1208 Flying = false;
1209 }
880 } 1210 }
881 1211
882 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying 1212 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
@@ -886,26 +1216,33 @@ namespace OpenSim.Region.Framework.Scenes
886 1216
887 m_scene.SwapRootAgentCount(false); 1217 m_scene.SwapRootAgentCount(false);
888 1218
889 // The initial login scene presence is already root when it gets here 1219 if (Scene.AttachmentsModule != null)
890 // and it has already rezzed the attachments and started their scripts.
891 // We do the following only for non-login agents, because their scripts
892 // haven't started yet.
893 lock (m_attachments)
894 { 1220 {
895 if (wasChild && HasAttachments()) 1221 // The initial login scene presence is already root when it gets here
1222 // and it has already rezzed the attachments and started their scripts.
1223 // We do the following only for non-login agents, because their scripts
1224 // haven't started yet.
1225 if (PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags))
896 { 1226 {
897 m_log.DebugFormat( 1227 WorkManager.RunJob(
898 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); 1228 "RezAttachments",
899 1229 o => Scene.AttachmentsModule.RezAttachments(this),
900 // Resume scripts 1230 null,
901 foreach (SceneObjectGroup sog in m_attachments) 1231 string.Format("Rez attachments for {0} in {1}", Name, Scene.Name));
902 { 1232 }
903 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 1233 else
904 sog.ResumeScripts(); 1234 {
905 } 1235 WorkManager.RunJob(
1236 "StartAttachmentScripts",
1237 o => RestartAttachmentScripts(),
1238 null,
1239 string.Format("Start attachment scripts for {0} in {1}", Name, Scene.Name),
1240 true);
906 } 1241 }
907 } 1242 }
908 1243
1244 SendAvatarDataToAllClients();
1245
909 // send the animations of the other presences to me 1246 // send the animations of the other presences to me
910 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence) 1247 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
911 { 1248 {
@@ -916,9 +1253,75 @@ namespace OpenSim.Region.Framework.Scenes
916 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will 1253 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will
917 // stall on the border crossing since the existing child agent will still have the last movement 1254 // stall on the border crossing since the existing child agent will still have the last movement
918 // recorded, which stops the input from being processed. 1255 // recorded, which stops the input from being processed.
919 MovementFlag = 0; 1256 MovementFlag = ForceUpdateMovementFlagValue;
920 1257
921 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1258 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1259
1260 return true;
1261 }
1262
1263 private void RestartAttachmentScripts()
1264 {
1265 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
1266 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1267 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1268 // not transporting the required data.
1269 //
1270 // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of
1271 // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here
1272 // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status.
1273 //
1274 // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts().
1275 // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing
1276 // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the
1277 // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
1278 List<SceneObjectGroup> attachments = GetAttachments();
1279
1280 m_log.DebugFormat(
1281 "[SCENE PRESENCE]: Restarting scripts in {0} attachments for {1} in {2}", attachments.Count, Name, Scene.Name);
1282
1283 // Resume scripts
1284 foreach (SceneObjectGroup sog in attachments)
1285 {
1286 sog.ScheduleGroupForFullUpdate();
1287 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1288 sog.ResumeScripts();
1289 }
1290 }
1291
1292 private static bool IsRealLogin(TeleportFlags teleportFlags)
1293 {
1294 return ((teleportFlags & TeleportFlags.ViaLogin) != 0) && ((teleportFlags & TeleportFlags.ViaHGLogin) == 0);
1295 }
1296
1297 /// <summary>
1298 /// Force viewers to show the avatar's current name.
1299 /// </summary>
1300 /// <remarks>
1301 /// The avatar name that is shown above the avatar in the viewers is sent in ObjectUpdate packets,
1302 /// and they get the name from the ScenePresence. Unfortunately, viewers have a bug (as of April 2014)
1303 /// where they ignore changes to the avatar name. However, tey don't ignore changes to the avatar's
1304 /// Group Title. So the following trick makes viewers update the avatar's name by briefly changing
1305 /// the group title (to "(Loading)"), and then restoring it.
1306 /// </remarks>
1307 public void ForceViewersUpdateName()
1308 {
1309 m_log.DebugFormat("[SCENE PRESENCE]: Forcing viewers to update the avatar name for " + Name);
1310
1311 UseFakeGroupTitle = true;
1312 SendAvatarDataToAllClients(false);
1313
1314 Util.FireAndForget(o =>
1315 {
1316 // Viewers only update the avatar name when idle. Therefore, we must wait long
1317 // enough for the viewer to show the fake name that we had set above, and only
1318 // then switch back to the true name. This delay was chosen because it has a high
1319 // chance of succeeding (we don't want to choose a value that's too low).
1320 Thread.Sleep(5000);
1321
1322 UseFakeGroupTitle = false;
1323 SendAvatarDataToAllClients(false);
1324 }, null, "Scenepresence.ForceViewersUpdateName");
922 } 1325 }
923 1326
924 public int GetStateSource() 1327 public int GetStateSource()
@@ -946,12 +1349,21 @@ namespace OpenSim.Region.Framework.Scenes
946 /// </remarks> 1349 /// </remarks>
947 public void MakeChildAgent() 1350 public void MakeChildAgent()
948 { 1351 {
1352 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1353
949 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); 1354 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName);
950 1355
1356 // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating
1357 // from the source simulator has completed on a V2 teleport.
1358 lock (m_originRegionIDAccessLock)
1359 m_originRegionID = UUID.Zero;
1360
951 // Reset these so that teleporting in and walking out isn't seen 1361 // Reset these so that teleporting in and walking out isn't seen
952 // as teleporting back 1362 // as teleporting back
953 TeleportFlags = TeleportFlags.Default; 1363 TeleportFlags = TeleportFlags.Default;
954 1364
1365 MovementFlag = 0;
1366
955 // It looks like Animator is set to null somewhere, and MakeChild 1367 // It looks like Animator is set to null somewhere, and MakeChild
956 // is called after that. Probably in aborted teleports. 1368 // is called after that. Probably in aborted teleports.
957 if (Animator == null) 1369 if (Animator == null)
@@ -959,6 +1371,7 @@ namespace OpenSim.Region.Framework.Scenes
959 else 1371 else
960 Animator.ResetAnimations(); 1372 Animator.ResetAnimations();
961 1373
1374
962// m_log.DebugFormat( 1375// m_log.DebugFormat(
963// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", 1376// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
964// Name, UUID, m_scene.RegionInfo.RegionName); 1377// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -970,6 +1383,7 @@ namespace OpenSim.Region.Framework.Scenes
970 IsChildAgent = true; 1383 IsChildAgent = true;
971 m_scene.SwapRootAgentCount(true); 1384 m_scene.SwapRootAgentCount(true);
972 RemoveFromPhysicalScene(); 1385 RemoveFromPhysicalScene();
1386 ParentID = 0; // Child agents can't be sitting
973 1387
974 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into 1388 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into
975 1389
@@ -984,10 +1398,10 @@ namespace OpenSim.Region.Framework.Scenes
984 if (PhysicsActor != null) 1398 if (PhysicsActor != null)
985 { 1399 {
986// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1400// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
987 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall;
988 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
989 PhysicsActor.UnSubscribeEvents(); 1401 PhysicsActor.UnSubscribeEvents();
1402 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall;
990 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1403 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1404 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
991 PhysicsActor = null; 1405 PhysicsActor = null;
992 } 1406 }
993// else 1407// else
@@ -1004,7 +1418,7 @@ namespace OpenSim.Region.Framework.Scenes
1004 /// <param name="pos"></param> 1418 /// <param name="pos"></param>
1005 public void Teleport(Vector3 pos) 1419 public void Teleport(Vector3 pos)
1006 { 1420 {
1007 TeleportWithMomentum(pos, null); 1421 TeleportWithMomentum(pos, Vector3.Zero);
1008 } 1422 }
1009 1423
1010 public void TeleportWithMomentum(Vector3 pos, Vector3? v) 1424 public void TeleportWithMomentum(Vector3 pos, Vector3? v)
@@ -1024,14 +1438,141 @@ namespace OpenSim.Region.Framework.Scenes
1024 else 1438 else
1025 PhysicsActor.SetMomentum(vel); 1439 PhysicsActor.SetMomentum(vel);
1026 } 1440 }
1441 }
1027 1442
1028 SendTerseUpdateToAllClients(); 1443 public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY)
1444 {
1445 CheckLandingPoint(ref newpos);
1446 AbsolutePosition = newpos;
1447
1448 if (newvel.HasValue)
1449 {
1450 if ((Vector3)newvel == Vector3.Zero)
1451 {
1452 if (PhysicsActor != null)
1453 PhysicsActor.SetMomentum(Vector3.Zero);
1454 m_velocity = Vector3.Zero;
1455 }
1456 else
1457 {
1458 if (PhysicsActor != null)
1459 PhysicsActor.SetMomentum((Vector3)newvel);
1460 m_velocity = (Vector3)newvel;
1461
1462 if (rotateToVelXY)
1463 {
1464 Vector3 lookAt = (Vector3)newvel;
1465 lookAt.Z = 0;
1466 lookAt.Normalize();
1467 ControllingClient.SendLocalTeleport(newpos, lookAt, (uint)TeleportFlags.ViaLocation);
1468 return;
1469 }
1470 }
1471 }
1029 } 1472 }
1030 1473
1031 public void StopFlying() 1474 public void StopFlying()
1032 { 1475 {
1033 ControllingClient.StopFlying(this); 1476 Vector3 pos = AbsolutePosition;
1477 if (Appearance.AvatarHeight != 127.0f)
1478 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f));
1479 else
1480 pos += new Vector3(0f, 0f, (1.56f / 6f));
1481
1482 AbsolutePosition = pos;
1483
1484 // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
1485 // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
1486 // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
1487 // certain amount.. because the LLClient wouldn't land in that situation anyway.
1488
1489 // why are we still testing for this really old height value default???
1490 if (Appearance.AvatarHeight != 127.0f)
1491 CollisionPlane = new Vector4(0, 0, 0, pos.Z - Appearance.AvatarHeight / 6f);
1492 else
1493 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f));
1494
1495 ControllingClient.SendAgentTerseUpdate(this);
1496 }
1497
1498 /// <summary>
1499 /// Applies a roll accumulator to the avatar's angular velocity for the avatar fly roll effect.
1500 /// </summary>
1501 /// <param name="amount">Postive or negative roll amount in radians</param>
1502 private void ApplyFlyingRoll(float amount, bool PressingUp, bool PressingDown)
1503 {
1504
1505 float rollAmount = Util.Clamp(m_AngularVelocity.Z + amount, -FLY_ROLL_MAX_RADIANS, FLY_ROLL_MAX_RADIANS);
1506 m_AngularVelocity.Z = rollAmount;
1507
1508 // APPLY EXTRA consideration for flying up and flying down during this time.
1509 // if we're turning left
1510 if (amount > 0)
1511 {
1512
1513 // If we're at the max roll and pressing up, we want to swing BACK a bit
1514 // Automatically adds noise
1515 if (PressingUp)
1516 {
1517 if (m_AngularVelocity.Z >= FLY_ROLL_MAX_RADIANS - 0.04f)
1518 m_AngularVelocity.Z -= 0.9f;
1519 }
1520 // If we're at the max roll and pressing down, we want to swing MORE a bit
1521 if (PressingDown)
1522 {
1523 if (m_AngularVelocity.Z >= FLY_ROLL_MAX_RADIANS && m_AngularVelocity.Z < FLY_ROLL_MAX_RADIANS + 0.6f)
1524 m_AngularVelocity.Z += 0.6f;
1525 }
1526 }
1527 else // we're turning right.
1528 {
1529 // If we're at the max roll and pressing up, we want to swing BACK a bit
1530 // Automatically adds noise
1531 if (PressingUp)
1532 {
1533 if (m_AngularVelocity.Z <= (-FLY_ROLL_MAX_RADIANS))
1534 m_AngularVelocity.Z += 0.6f;
1535 }
1536 // If we're at the max roll and pressing down, we want to swing MORE a bit
1537 if (PressingDown)
1538 {
1539 if (m_AngularVelocity.Z >= -FLY_ROLL_MAX_RADIANS - 0.6f)
1540 m_AngularVelocity.Z -= 0.6f;
1541 }
1542 }
1543 }
1544
1545 /// <summary>
1546 /// incrementally sets roll amount to zero
1547 /// </summary>
1548 /// <param name="amount">Positive roll amount in radians</param>
1549 /// <returns></returns>
1550 private float CalculateFlyingRollResetToZero(float amount)
1551 {
1552 const float rollMinRadians = 0f;
1553
1554 if (m_AngularVelocity.Z > 0)
1555 {
1556
1557 float leftOverToMin = m_AngularVelocity.Z - rollMinRadians;
1558 if (amount > leftOverToMin)
1559 return -leftOverToMin;
1560 else
1561 return -amount;
1562
1563 }
1564 else
1565 {
1566
1567 float leftOverToMin = -m_AngularVelocity.Z - rollMinRadians;
1568 if (amount > leftOverToMin)
1569 return leftOverToMin;
1570 else
1571 return amount;
1572 }
1034 } 1573 }
1574
1575
1035 1576
1036 // neighbouring regions we have enabled a child agent in 1577 // neighbouring regions we have enabled a child agent in
1037 // holds the seed cap for the child agent in that region 1578 // holds the seed cap for the child agent in that region
@@ -1118,6 +1659,40 @@ namespace OpenSim.Region.Framework.Scenes
1118 PhysicsActor.Size = new Vector3(0.45f, 0.6f, height); 1659 PhysicsActor.Size = new Vector3(0.45f, 0.6f, height);
1119 } 1660 }
1120 1661
1662 public void SetSize(Vector3 size, float feetoffset)
1663 {
1664 if (PhysicsActor != null && !IsChildAgent)
1665 {
1666 // Eventually there will be a physics call that sets avatar size that includes offset info.
1667 // For the moment, just set the size as passed.
1668 PhysicsActor.Size = size;
1669 // PhysicsActor.setAvatarSize(size, feetoffset);
1670 }
1671 }
1672
1673 private bool WaitForUpdateAgent(IClientAPI client)
1674 {
1675 // Before the source region executes UpdateAgent
1676 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination,
1677 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
1678 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
1679 m_updateAgentReceivedAfterTransferEvent.WaitOne(10000);
1680
1681 UUID originID = UUID.Zero;
1682
1683 lock (m_originRegionIDAccessLock)
1684 originID = m_originRegionID;
1685
1686 if (originID.Equals(UUID.Zero))
1687 {
1688 // Movement into region will fail
1689 m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
1690 return false;
1691 }
1692
1693 return true;
1694 }
1695
1121 /// <summary> 1696 /// <summary>
1122 /// Complete Avatar's movement into the region. 1697 /// Complete Avatar's movement into the region.
1123 /// </summary> 1698 /// </summary>
@@ -1131,74 +1706,131 @@ namespace OpenSim.Region.Framework.Scenes
1131 { 1706 {
1132// DateTime startTime = DateTime.Now; 1707// DateTime startTime = DateTime.Now;
1133 1708
1134 m_log.DebugFormat( 1709 m_log.InfoFormat(
1135 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", 1710 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1136 client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); 1711 client.Name, Scene.Name, AbsolutePosition);
1137 1712
1138 Vector3 look = Velocity; 1713 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); // Get this ahead of time because IsInTransit modifies 'm_AgentControlFlags'
1139 1714
1140 if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) 1715 IsInTransit = true;
1716 try
1141 { 1717 {
1142 look = new Vector3(0.99f, 0.042f, 0); 1718 // Make sure it's not a login agent. We don't want to wait for updates during login
1143 } 1719 if (!(PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags)))
1720 {
1721 // Let's wait until UpdateAgent (called by departing region) is done
1722 if (!WaitForUpdateAgent(client))
1723 // The sending region never sent the UpdateAgent data, we have to refuse
1724 return;
1725 }
1144 1726
1145 // Prevent teleporting to an underground location 1727 Vector3 look = Velocity;
1146 // (may crash client otherwise)
1147 //
1148 Vector3 pos = AbsolutePosition;
1149 float ground = m_scene.GetGroundHeight(pos.X, pos.Y);
1150 if (pos.Z < ground + 1.5f)
1151 {
1152 pos.Z = ground + 1.5f;
1153 AbsolutePosition = pos;
1154 }
1155 1728
1156 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1729 // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0))
1157 MakeRootAgent(AbsolutePosition, flying); 1730 if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1))
1158 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); 1731 {
1732 look = new Vector3(0.99f, 0.042f, 0);
1733 }
1159 1734
1160// m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); 1735 // Prevent teleporting to an underground location
1736 // (may crash client otherwise)
1737 //
1738 Vector3 pos = AbsolutePosition;
1739 float ground = m_scene.GetGroundHeight(pos.X, pos.Y);
1740 if (pos.Z < ground + 1.5f)
1741 {
1742 pos.Z = ground + 1.5f;
1743 AbsolutePosition = pos;
1744 }
1161 1745
1162 if ((m_callbackURI != null) && !m_callbackURI.Equals("")) 1746 if (!MakeRootAgent(AbsolutePosition, flying))
1163 { 1747 {
1164 // We cannot sleep here since this would hold up the inbound packet processing thread, as 1748 m_log.DebugFormat(
1165 // CompleteMovement() is executed synchronously. However, it might be better to delay the release 1749 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
1166 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete 1750 Name, Scene.Name);
1167 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this
1168 // region as the current region, meaning that a close sent before then will fail the teleport.
1169// System.Threading.Thread.Sleep(2000);
1170 1751
1171 m_log.DebugFormat( 1752 return;
1172 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", 1753 }
1173 client.Name, client.AgentId, m_callbackURI);
1174 1754
1175 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); 1755 // Tell the client that we're totally ready
1176 m_callbackURI = null; 1756 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1177 }
1178// else
1179// {
1180// m_log.DebugFormat(
1181// "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}",
1182// client.Name, client.AgentId, m_scene.RegionInfo.RegionName);
1183// }
1184 1757
1185 ValidateAndSendAppearanceAndAgentData(); 1758 // Child agents send initial data up in LLUDPServer.HandleUseCircuitCode()
1759 if (!SentInitialDataToClient)
1760 SendInitialDataToClient();
1186 1761
1187 // Create child agents in neighbouring regions 1762 // m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
1188 if (openChildAgents && !IsChildAgent) 1763
1189 { 1764 if (!string.IsNullOrEmpty(m_callbackURI))
1190 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 1765 {
1191 if (m_agentTransfer != null) 1766 // We cannot sleep here since this would hold up the inbound packet processing thread, as
1192 Util.FireAndForget(delegate { m_agentTransfer.EnableChildAgents(this); }); 1767 // CompleteMovement() is executed synchronously. However, it might be better to delay the release
1768 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete
1769 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this
1770 // region as the current region, meaning that a close sent before then will fail the teleport.
1771 // System.Threading.Thread.Sleep(2000);
1772
1773 m_log.DebugFormat(
1774 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1775 client.Name, client.AgentId, m_callbackURI);
1776
1777 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI);
1778 m_callbackURI = null;
1779 }
1780 // else
1781 // {
1782 // m_log.DebugFormat(
1783 // "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}",
1784 // client.Name, client.AgentId, m_scene.RegionInfo.RegionName);
1785 // }
1786
1787 ValidateAndSendAppearanceAndAgentData();
1193 1788
1194 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); 1789 // Create child agents in neighbouring regions
1195 if (friendsModule != null) 1790 if (openChildAgents && !IsChildAgent)
1196 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); 1791 {
1792 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
1793 if (m_agentTransfer != null)
1794 {
1795 // Note: this call can take a while, because it notifies each of the simulator's neighbours.
1796 // It's important that we don't allow the avatar to cross regions meanwhile, as that will
1797 // cause serious errors. We've prevented that from happening by setting IsInTransit=true.
1798 m_agentTransfer.EnableChildAgents(this);
1799 }
1800
1801 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
1802 if (friendsModule != null)
1803 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
1804
1805 }
1806
1807 // XXX: If we force an update after activity has completed, then multiple attachments do appear correctly on a destination region
1808 // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work.
1809 // This may be due to viewer code or it may be something we're not doing properly simulator side.
1810 WorkManager.RunJob(
1811 "ScheduleAttachmentsForFullUpdate",
1812 o => ScheduleAttachmentsForFullUpdate(),
1813 null,
1814 string.Format("Schedule attachments for full update for {0} in {1}", Name, Scene.Name),
1815 true);
1816
1817 // m_log.DebugFormat(
1818 // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
1819 // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds);
1197 } 1820 }
1821 finally
1822 {
1823 IsInTransit = false;
1824 }
1825 }
1198 1826
1199// m_log.DebugFormat( 1827 private void ScheduleAttachmentsForFullUpdate()
1200// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", 1828 {
1201// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); 1829 lock (m_attachments)
1830 {
1831 foreach (SceneObjectGroup sog in m_attachments)
1832 sog.ScheduleGroupForFullUpdate();
1833 }
1202 } 1834 }
1203 1835
1204 /// <summary> 1836 /// <summary>
@@ -1209,36 +1841,69 @@ namespace OpenSim.Region.Framework.Scenes
1209 /// <param name="collisionPoint"></param> 1841 /// <param name="collisionPoint"></param>
1210 /// <param name="localid"></param> 1842 /// <param name="localid"></param>
1211 /// <param name="distance"></param> 1843 /// <param name="distance"></param>
1844 ///
1845
1846 private void UpdateCameraCollisionPlane(Vector4 plane)
1847 {
1848 if (m_lastCameraCollisionPlane != plane)
1849 {
1850 m_lastCameraCollisionPlane = plane;
1851 ControllingClient.SendCameraConstraint(plane);
1852 }
1853 }
1854
1212 public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal) 1855 public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal)
1213 { 1856 {
1214 const float POSITION_TOLERANCE = 0.02f; 1857 const float POSITION_TOLERANCE = 0.02f;
1215 const float VELOCITY_TOLERANCE = 0.02f;
1216 const float ROTATION_TOLERANCE = 0.02f; 1858 const float ROTATION_TOLERANCE = 0.02f;
1217 1859
1218 if (m_followCamAuto) 1860 m_doingCamRayCast = false;
1861 if (hitYN && localid != LocalId)
1219 { 1862 {
1220 if (hitYN) 1863 SceneObjectGroup group = m_scene.GetGroupByPrim(localid);
1864 bool IsPrim = group != null;
1865 if (IsPrim)
1221 { 1866 {
1222 CameraConstraintActive = true; 1867 SceneObjectPart part = group.GetPart(localid);
1223 //m_log.DebugFormat("[RAYCASTRESULT]: {0}, {1}, {2}, {3}", hitYN, collisionPoint, localid, distance); 1868 if (part != null && !part.VolumeDetectActive)
1224 1869 {
1225 Vector3 normal = Vector3.Normalize(new Vector3(0f, 0f, collisionPoint.Z) - collisionPoint); 1870 CameraConstraintActive = true;
1226 ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint))); 1871 pNormal.X = (float) Math.Round(pNormal.X, 2);
1872 pNormal.Y = (float) Math.Round(pNormal.Y, 2);
1873 pNormal.Z = (float) Math.Round(pNormal.Z, 2);
1874 pNormal.Normalize();
1875 collisionPoint.X = (float) Math.Round(collisionPoint.X, 1);
1876 collisionPoint.Y = (float) Math.Round(collisionPoint.Y, 1);
1877 collisionPoint.Z = (float) Math.Round(collisionPoint.Z, 1);
1878
1879 Vector4 plane = new Vector4(pNormal.X, pNormal.Y, pNormal.Z,
1880 Vector3.Dot(collisionPoint, pNormal));
1881 UpdateCameraCollisionPlane(plane);
1882 }
1227 } 1883 }
1228 else 1884 else
1229 { 1885 {
1230 if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 1886 CameraConstraintActive = true;
1231 !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || 1887 pNormal.X = (float) Math.Round(pNormal.X, 2);
1232 !Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)) 1888 pNormal.Y = (float) Math.Round(pNormal.Y, 2);
1233 { 1889 pNormal.Z = (float) Math.Round(pNormal.Z, 2);
1234 if (CameraConstraintActive) 1890 pNormal.Normalize();
1235 { 1891 collisionPoint.X = (float) Math.Round(collisionPoint.X, 1);
1236 ControllingClient.SendCameraConstraint(new Vector4(0f, 0.5f, 0.9f, -3000f)); 1892 collisionPoint.Y = (float) Math.Round(collisionPoint.Y, 1);
1237 CameraConstraintActive = false; 1893 collisionPoint.Z = (float) Math.Round(collisionPoint.Z, 1);
1238 } 1894
1239 } 1895 Vector4 plane = new Vector4(pNormal.X, pNormal.Y, pNormal.Z,
1896 Vector3.Dot(collisionPoint, pNormal));
1897 UpdateCameraCollisionPlane(plane);
1240 } 1898 }
1241 } 1899 }
1900 else if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
1901 !Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE))
1902 {
1903 Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -9000f); // not right...
1904 UpdateCameraCollisionPlane(plane);
1905 CameraConstraintActive = false;
1906 }
1242 } 1907 }
1243 1908
1244 /// <summary> 1909 /// <summary>
@@ -1248,18 +1913,14 @@ namespace OpenSim.Region.Framework.Scenes
1248 { 1913 {
1249// m_log.DebugFormat( 1914// m_log.DebugFormat(
1250// "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", 1915// "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}",
1251// Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); 1916// Scene.Name, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
1252 1917
1253 if (IsChildAgent) 1918 if (IsChildAgent)
1254 { 1919 {
1255 // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); 1920// m_log.DebugFormat("DEBUG: HandleAgentUpdate: child agent in {0}", Scene.Name);
1256 return; 1921 return;
1257 } 1922 }
1258 1923
1259 ++m_movementUpdateCount;
1260 if (m_movementUpdateCount < 1)
1261 m_movementUpdateCount = 1;
1262
1263 #region Sanity Checking 1924 #region Sanity Checking
1264 1925
1265 // This is irritating. Really. 1926 // This is irritating. Really.
@@ -1290,36 +1951,20 @@ namespace OpenSim.Region.Framework.Scenes
1290 1951
1291 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; 1952 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
1292 1953
1293 // Camera location in world. We'll need to raytrace
1294 // from this location from time to time.
1295 CameraPosition = agentData.CameraCenter;
1296 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
1297 {
1298 ReprioritizeUpdates();
1299 m_lastCameraPosition = CameraPosition;
1300 }
1301
1302 // Use these three vectors to figure out what the agent is looking at
1303 // Convert it to a Matrix and/or Quaternion
1304 CameraAtAxis = agentData.CameraAtAxis;
1305 CameraLeftAxis = agentData.CameraLeftAxis;
1306 CameraUpAxis = agentData.CameraUpAxis;
1307
1308 // The Agent's Draw distance setting 1954 // The Agent's Draw distance setting
1309 // When we get to the point of re-computing neighbors everytime this 1955 // When we get to the point of re-computing neighbors everytime this
1310 // changes, then start using the agent's drawdistance rather than the 1956 // changes, then start using the agent's drawdistance rather than the
1311 // region's draw distance. 1957 // region's draw distance.
1312 // DrawDistance = agentData.Far; 1958 DrawDistance = agentData.Far;
1313 DrawDistance = Scene.DefaultDrawDistance; 1959 // DrawDistance = Scene.DefaultDrawDistance;
1314
1315 // Check if Client has camera in 'follow cam' or 'build' mode.
1316 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
1317
1318 m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f)
1319 && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
1320 1960
1321 m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; 1961 m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
1322 m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; 1962
1963 // FIXME: This does not work as intended because the viewer only sends the lbutton down when the button
1964 // is first pressed, not whilst it is held down. If this is required in the future then need to look
1965 // for an AGENT_CONTROL_LBUTTON_UP event and make sure to handle cases where an initial DOWN is not
1966 // received (e.g. on holding LMB down on the avatar in a viewer).
1967// m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
1323 1968
1324 #endregion Inputs 1969 #endregion Inputs
1325 1970
@@ -1337,14 +1982,38 @@ namespace OpenSim.Region.Framework.Scenes
1337 StandUp(); 1982 StandUp();
1338 } 1983 }
1339 1984
1340 //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
1341 // Raycast from the avatar's head to the camera to see if there's anything blocking the view 1985 // Raycast from the avatar's head to the camera to see if there's anything blocking the view
1342 if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) 1986 // this exclude checks may not be complete
1987
1988 if (m_movementUpdateCount % NumMovementsBetweenRayCast == 0 && m_scene.PhysicsScene.SupportsRayCast())
1343 { 1989 {
1344 if (m_followCamAuto) 1990 if (!m_doingCamRayCast && !m_mouseLook && ParentID == 0)
1345 { 1991 {
1346 Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; 1992 Vector3 posAdjusted = AbsolutePosition;
1347 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback); 1993// posAdjusted.Z += 0.5f * Appearance.AvatarSize.Z - 0.5f;
1994 posAdjusted.Z += 1.0f; // viewer current camera focus point
1995 Vector3 tocam = CameraPosition - posAdjusted;
1996 tocam.X = (float)Math.Round(tocam.X, 1);
1997 tocam.Y = (float)Math.Round(tocam.Y, 1);
1998 tocam.Z = (float)Math.Round(tocam.Z, 1);
1999
2000 float distTocamlen = tocam.Length();
2001 if (distTocamlen > 0.3f)
2002 {
2003 tocam *= (1.0f / distTocamlen);
2004 posAdjusted.X = (float)Math.Round(posAdjusted.X, 1);
2005 posAdjusted.Y = (float)Math.Round(posAdjusted.Y, 1);
2006 posAdjusted.Z = (float)Math.Round(posAdjusted.Z, 1);
2007
2008 m_doingCamRayCast = true;
2009 m_scene.PhysicsScene.RaycastWorld(posAdjusted, tocam, distTocamlen + 1.0f, RayCastCameraCallback);
2010 }
2011 }
2012 else if (CameraConstraintActive && (m_mouseLook || ParentID != 0))
2013 {
2014 Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -10000f); // not right...
2015 UpdateCameraCollisionPlane(plane);
2016 CameraConstraintActive = false;
1348 } 2017 }
1349 } 2018 }
1350 2019
@@ -1358,9 +2027,16 @@ namespace OpenSim.Region.Framework.Scenes
1358 // Here's where you get them. 2027 // Here's where you get them.
1359 m_AgentControlFlags = flags; 2028 m_AgentControlFlags = flags;
1360 m_headrotation = agentData.HeadRotation; 2029 m_headrotation = agentData.HeadRotation;
2030 byte oldState = State;
1361 State = agentData.State; 2031 State = agentData.State;
1362 2032
2033 // We need to send this back to the client in order to stop the edit beams
2034 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
2035 ControllingClient.SendAgentTerseUpdate(this);
2036
1363 PhysicsActor actor = PhysicsActor; 2037 PhysicsActor actor = PhysicsActor;
2038
2039 // This will be the case if the agent is sitting on the groudn or on an object.
1364 if (actor == null) 2040 if (actor == null)
1365 { 2041 {
1366 SendControlsToScripts(flagsForScripts); 2042 SendControlsToScripts(flagsForScripts);
@@ -1369,17 +2045,26 @@ namespace OpenSim.Region.Framework.Scenes
1369 2045
1370 if (AllowMovement && !SitGround) 2046 if (AllowMovement && !SitGround)
1371 { 2047 {
1372 Quaternion bodyRotation = agentData.BodyRotation; 2048// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name);
2049
1373 bool update_rotation = false; 2050 bool update_rotation = false;
1374 2051
1375 if (bodyRotation != Rotation) 2052 if (agentData.BodyRotation != Rotation)
1376 { 2053 {
1377 Rotation = bodyRotation; 2054 Rotation = agentData.BodyRotation;
1378 update_rotation = true; 2055 update_rotation = true;
1379 } 2056 }
1380 2057
1381 bool update_movementflag = false; 2058 bool update_movementflag = false;
1382 2059
2060 // If we were just made root agent then we must perform movement updates for the first AgentUpdate that
2061 // we get
2062 if (MovementFlag == ForceUpdateMovementFlagValue)
2063 {
2064 MovementFlag = 0;
2065 update_movementflag = true;
2066 }
2067
1383 if (agentData.UseClientAgentPosition) 2068 if (agentData.UseClientAgentPosition)
1384 { 2069 {
1385 MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; 2070 MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
@@ -1411,19 +2096,7 @@ namespace OpenSim.Region.Framework.Scenes
1411 { 2096 {
1412 bool bAllowUpdateMoveToPosition = false; 2097 bool bAllowUpdateMoveToPosition = false;
1413 2098
1414 Vector3[] dirVectors;
1415
1416 // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying
1417 // this prevents 'jumping' in inappropriate situations.
1418 if (!Flying && (m_mouseLook || m_leftButtonDown))
1419 dirVectors = GetWalkDirectionVectors();
1420 else
1421 dirVectors = Dir_Vectors;
1422
1423 // The fact that MovementFlag is a byte needs to be fixed
1424 // it really should be a uint
1425 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. 2099 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction.
1426 uint nudgehack = 250;
1427 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 2100 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1428 { 2101 {
1429 if (((uint)flags & (uint)DCF) != 0) 2102 if (((uint)flags & (uint)DCF) != 0)
@@ -1432,7 +2105,9 @@ namespace OpenSim.Region.Framework.Scenes
1432 2105
1433 try 2106 try
1434 { 2107 {
1435 agent_control_v3 += dirVectors[i]; 2108 // Don't slide against ground when crouching if camera is panned around avatar
2109 if (Flying || DCF != Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN)
2110 agent_control_v3 += Dir_Vectors[i];
1436 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 2111 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]);
1437 } 2112 }
1438 catch (IndexOutOfRangeException) 2113 catch (IndexOutOfRangeException)
@@ -1440,29 +2115,19 @@ namespace OpenSim.Region.Framework.Scenes
1440 // Why did I get this? 2115 // Why did I get this?
1441 } 2116 }
1442 2117
1443 if ((MovementFlag & (byte)(uint)DCF) == 0) 2118 if (((MovementFlag & (uint)DCF) == 0) & !AgentControlStopActive)
1444 { 2119 {
1445 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
1446 DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
1447 {
1448 MovementFlag |= (byte)nudgehack;
1449 }
1450
1451 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); 2120 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
1452 MovementFlag += (byte)(uint)DCF; 2121 MovementFlag += (uint)DCF;
1453 update_movementflag = true; 2122 update_movementflag = true;
1454 } 2123 }
1455 } 2124 }
1456 else 2125 else
1457 { 2126 {
1458 if ((MovementFlag & (byte)(uint)DCF) != 0 || 2127 if ((MovementFlag & (uint)DCF) != 0)
1459 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
1460 DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
1461 && ((MovementFlag & (byte)nudgehack) == nudgehack))
1462 ) // This or is for Nudge forward
1463 { 2128 {
1464 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); 2129 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
1465 MovementFlag -= ((byte)(uint)DCF); 2130 MovementFlag -= (uint)DCF;
1466 update_movementflag = true; 2131 update_movementflag = true;
1467 2132
1468 /* 2133 /*
@@ -1482,6 +2147,13 @@ namespace OpenSim.Region.Framework.Scenes
1482 i++; 2147 i++;
1483 } 2148 }
1484 2149
2150 // Detect AGENT_CONTROL_STOP state changes
2151 if (AgentControlStopActive != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0))
2152 {
2153 AgentControlStopActive = !AgentControlStopActive;
2154 update_movementflag = true;
2155 }
2156
1485 if (MovingToTarget) 2157 if (MovingToTarget)
1486 { 2158 {
1487 // If the user has pressed a key then we want to cancel any move to target. 2159 // If the user has pressed a key then we want to cancel any move to target.
@@ -1507,30 +2179,79 @@ namespace OpenSim.Region.Framework.Scenes
1507 // Only do this if we're flying 2179 // Only do this if we're flying
1508 if (Flying && !ForceFly) 2180 if (Flying && !ForceFly)
1509 { 2181 {
1510 // Landing detection code 2182 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP
2183 if (AgentControlStopActive)
2184 {
2185 agent_control_v3 = Vector3.Zero;
2186 }
2187 else
2188 {
2189 // Landing detection code
1511 2190
1512 // Are the landing controls requirements filled? 2191 // Are the landing controls requirements filled?
1513 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || 2192 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
1514 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2193 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1515 2194
1516 if (Flying && IsColliding && controlland) 2195 //m_log.Debug("[CONTROL]: " +flags);
1517 { 2196 // Applies a satisfying roll effect to the avatar when flying.
1518 // nesting this check because LengthSquared() is expensive and we don't 2197 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
1519 // want to do it every step when flying. 2198 {
1520 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) 2199 ApplyFlyingRoll(
1521 StopFlying(); 2200 FLY_ROLL_RADIANS_PER_UPDATE,
2201 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2202 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2203 }
2204 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
2205 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
2206 {
2207 ApplyFlyingRoll(
2208 -FLY_ROLL_RADIANS_PER_UPDATE,
2209 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2210 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2211 }
2212 else
2213 {
2214 if (m_AngularVelocity.Z != 0)
2215 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
2216 }
2217
2218 if (Flying && IsColliding && controlland)
2219 {
2220 // nesting this check because LengthSquared() is expensive and we don't
2221 // want to do it every step when flying.
2222 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2223 StopFlying();
2224 }
1522 } 2225 }
1523 } 2226 }
1524 2227
2228// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);
2229
1525 // If the agent update does move the avatar, then calculate the force ready for the velocity update, 2230 // If the agent update does move the avatar, then calculate the force ready for the velocity update,
1526 // which occurs later in the main scene loop 2231 // which occurs later in the main scene loop
1527 if (update_movementflag || (update_rotation && DCFlagKeyPressed)) 2232 // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they
2233 // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update
2234 // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the
2235 // avatar location in place).
2236 if (update_movementflag
2237 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
1528 { 2238 {
1529// m_log.DebugFormat( 2239// if (update_movementflag || !AgentControlStopActive || MovementFlag != 0)
1530// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}", 2240// {
1531// m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation); 2241// m_log.DebugFormat(
2242// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, mf = {4}, ur = {5}",
2243// m_scene.RegionInfo.RegionName, agent_control_v3, Name,
2244// update_movementflag, MovementFlag, update_rotation);
2245
2246 float speedModifier;
1532 2247
1533 AddNewMovement(agent_control_v3); 2248 if (AgentControlStopActive)
2249 speedModifier = AgentControlStopSlowWhilstMoving;
2250 else
2251 speedModifier = 1;
2252
2253 AddNewMovement(agent_control_v3, speedModifier);
2254// }
1534 } 2255 }
1535// else 2256// else
1536// { 2257// {
@@ -1543,15 +2264,86 @@ namespace OpenSim.Region.Framework.Scenes
1543// } 2264// }
1544 2265
1545 if (update_movementflag && ParentID == 0) 2266 if (update_movementflag && ParentID == 0)
2267 {
2268// m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name);
1546 Animator.UpdateMovementAnimations(); 2269 Animator.UpdateMovementAnimations();
2270 }
1547 2271
1548 SendControlsToScripts(flagsForScripts); 2272 SendControlsToScripts(flagsForScripts);
1549 } 2273 }
1550 2274
2275 // We need to send this back to the client in order to see the edit beams
2276 if ((State & (uint)AgentState.Editing) != 0)
2277 ControllingClient.SendAgentTerseUpdate(this);
2278
1551 m_scene.EventManager.TriggerOnClientMovement(this); 2279 m_scene.EventManager.TriggerOnClientMovement(this);
1552 TriggerScenePresenceUpdated();
1553 } 2280 }
1554 2281
2282
2283 /// <summary>
2284 /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering.
2285 /// </summary>
2286 private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
2287 {
2288 //m_log.DebugFormat(
2289 // "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}",
2290 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
2291
2292 if (IsChildAgent)
2293 {
2294 // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
2295 return;
2296 }
2297
2298 ++m_movementUpdateCount;
2299 if (m_movementUpdateCount < 1)
2300 m_movementUpdateCount = 1;
2301
2302// AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
2303
2304 // Camera location in world. We'll need to raytrace
2305 // from this location from time to time.
2306 CameraPosition = agentData.CameraCenter;
2307 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
2308 {
2309 ReprioritizeUpdates();
2310 m_lastCameraPosition = CameraPosition;
2311 }
2312
2313 // Use these three vectors to figure out what the agent is looking at
2314 // Convert it to a Matrix and/or Quaternion
2315 CameraAtAxis = agentData.CameraAtAxis;
2316 CameraLeftAxis = agentData.CameraLeftAxis;
2317 CameraUpAxis = agentData.CameraUpAxis;
2318
2319 // The Agent's Draw distance setting
2320 // When we get to the point of re-computing neighbors everytime this
2321 // changes, then start using the agent's drawdistance rather than the
2322 // region's draw distance.
2323 DrawDistance = agentData.Far;
2324 // DrawDistance = Scene.DefaultDrawDistance;
2325
2326 // Check if Client has camera in 'follow cam' or 'build' mode.
2327 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
2328
2329 m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f)
2330 && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
2331
2332
2333 //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
2334 // Raycast from the avatar's head to the camera to see if there's anything blocking the view
2335 if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
2336 {
2337 if (m_followCamAuto)
2338 {
2339 Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
2340 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
2341 }
2342 }
2343
2344 TriggerScenePresenceUpdated();
2345 }
2346
1555 /// <summary> 2347 /// <summary>
1556 /// Calculate an update to move the presence to the set target. 2348 /// Calculate an update to move the presence to the set target.
1557 /// </summary> 2349 /// </summary>
@@ -1706,13 +2498,15 @@ namespace OpenSim.Region.Framework.Scenes
1706 if (regionCombinerModule != null) 2498 if (regionCombinerModule != null)
1707 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); 2499 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
1708 else 2500 else
1709 regionSize = new Vector2(Constants.RegionSize); 2501 regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY);
1710 2502
1711 if (pos.X < 0 || pos.X >= regionSize.X 2503 if (pos.X < 0 || pos.X >= regionSize.X
1712 || pos.Y < 0 || pos.Y >= regionSize.Y 2504 || pos.Y < 0 || pos.Y >= regionSize.Y
1713 || pos.Z < 0) 2505 || pos.Z < 0)
1714 return; 2506 return;
1715 2507
2508 Scene targetScene = m_scene;
2509
1716// Vector3 heightAdjust = new Vector3(0, 0, Appearance.AvatarHeight / 2); 2510// Vector3 heightAdjust = new Vector3(0, 0, Appearance.AvatarHeight / 2);
1717// pos += heightAdjust; 2511// pos += heightAdjust;
1718// 2512//
@@ -1724,15 +2518,23 @@ namespace OpenSim.Region.Framework.Scenes
1724// } 2518// }
1725 2519
1726 // Get terrain height for sub-region in a megaregion if necessary 2520 // Get terrain height for sub-region in a megaregion if necessary
1727 int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X);
1728 int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y);
1729 UUID target_regionID = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y).RegionID;
1730 Scene targetScene = m_scene;
1731 2521
1732 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene)) 2522 //COMMENT: If its only nessesary in a megaregion, why do it on normal region's too?
1733 targetScene = m_scene; 2523
2524 if (regionCombinerModule != null)
2525 {
2526 int x = (int)((m_scene.RegionInfo.WorldLocX) + pos.X);
2527 int y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y);
2528 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, x, y);
2529
2530 // If X and Y is NaN, target_region will be null
2531 if (target_region == null)
2532 return;
2533
2534 SceneManager.Instance.TryGetScene(target_region.RegionID, out targetScene);
2535 }
1734 2536
1735 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)]; 2537 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)];
1736 pos.Z = Math.Max(terrainHeight, pos.Z); 2538 pos.Z = Math.Max(terrainHeight, pos.Z);
1737 2539
1738 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 2540 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -1741,15 +2543,18 @@ namespace OpenSim.Region.Framework.Scenes
1741 if (pos.Z - terrainHeight < 0.2) 2543 if (pos.Z - terrainHeight < 0.2)
1742 pos.Z = terrainHeight; 2544 pos.Z = terrainHeight;
1743 2545
1744// m_log.DebugFormat(
1745// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
1746// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
1747
1748 if (noFly) 2546 if (noFly)
1749 Flying = false; 2547 Flying = false;
1750 else if (pos.Z > terrainHeight) 2548 else if (pos.Z > terrainHeight)
1751 Flying = true; 2549 Flying = true;
1752 2550
2551// m_log.DebugFormat(
2552// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
2553// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
2554
2555 if (noFly)
2556 Flying = false;
2557
1753 LandAtTarget = landAtTarget; 2558 LandAtTarget = landAtTarget;
1754 MovingToTarget = true; 2559 MovingToTarget = true;
1755 MoveToPositionTarget = pos; 2560 MoveToPositionTarget = pos;
@@ -1782,7 +2587,8 @@ namespace OpenSim.Region.Framework.Scenes
1782// m_log.DebugFormat("[SCENE PRESENCE]: Resetting move to target for {0}", Name); 2587// m_log.DebugFormat("[SCENE PRESENCE]: Resetting move to target for {0}", Name);
1783 2588
1784 MovingToTarget = false; 2589 MovingToTarget = false;
1785 MoveToPositionTarget = Vector3.Zero; 2590// MoveToPositionTarget = Vector3.Zero;
2591 m_forceToApply = null; // cancel possible last action
1786 2592
1787 // We need to reset the control flag as the ScenePresenceAnimator uses this to determine the correct 2593 // We need to reset the control flag as the ScenePresenceAnimator uses this to determine the correct
1788 // resting animation (e.g. hover or stand). NPCs don't have a client that will quickly reset this flag. 2594 // resting animation (e.g. hover or stand). NPCs don't have a client that will quickly reset this flag.
@@ -1799,13 +2605,15 @@ namespace OpenSim.Region.Framework.Scenes
1799 { 2605 {
1800// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 2606// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
1801 2607
2608 bool satOnObject = IsSatOnObject;
2609 SceneObjectPart part = ParentPart;
1802 SitGround = false; 2610 SitGround = false;
1803 if (PhysicsActor == null)
1804 AddToPhysicalScene(false);
1805 2611
1806 if (ParentID != 0) 2612 if (satOnObject)
1807 { 2613 {
1808 SceneObjectPart part = ParentPart; 2614 PrevSitOffset = m_pos; // Save sit offset
2615 UnRegisterSeatControls(part.ParentGroup.UUID);
2616
1809 TaskInventoryDictionary taskIDict = part.TaskInventory; 2617 TaskInventoryDictionary taskIDict = part.TaskInventory;
1810 if (taskIDict != null) 2618 if (taskIDict != null)
1811 { 2619 {
@@ -1821,24 +2629,70 @@ namespace OpenSim.Region.Framework.Scenes
1821 } 2629 }
1822 } 2630 }
1823 2631
1824 ParentPosition = part.GetWorldPosition();
1825 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 2632 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1826 2633
1827 m_pos += ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight);
1828 ParentPosition = Vector3.Zero;
1829
1830 ParentID = 0; 2634 ParentID = 0;
1831 ParentPart = null; 2635 ParentPart = null;
1832 SendAvatarDataToAllAgents(); 2636
2637 Quaternion standRotation;
2638
2639 if (part.SitTargetAvatar == UUID)
2640 {
2641 standRotation = part.GetWorldRotation();
2642
2643 if (!part.IsRoot)
2644 standRotation = standRotation * part.SitTargetOrientation;
2645// standRotation = part.RotationOffset * part.SitTargetOrientation;
2646// else
2647// standRotation = part.SitTargetOrientation;
2648
2649 }
2650 else
2651 {
2652 standRotation = Rotation;
2653 }
2654
2655 //Vector3 standPos = ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight);
2656 //Vector3 standPos = ParentPosition;
2657
2658// Vector3 standPositionAdjustment
2659// = part.SitTargetPosition + new Vector3(0.5f, 0f, m_sitAvatarHeight / 2f);
2660 Vector3 adjustmentForSitPosition = OffsetPosition * part.ParentGroup.GroupRotation - SIT_TARGET_ADJUSTMENT * part.GetWorldRotation();
2661
2662 // XXX: This is based on the physics capsule sizes. Need to find a better way to read this rather than
2663 // hardcoding here.
2664 Vector3 adjustmentForSitPose = new Vector3(0.74f, 0f, 0f) * standRotation;
2665
2666 Vector3 standPos = part.ParentGroup.AbsolutePosition + adjustmentForSitPosition + adjustmentForSitPose;
2667
2668// m_log.DebugFormat(
2669// "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}",
2670// standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name);
2671
2672 Rotation = standRotation;
2673 AbsolutePosition = standPos;
2674 }
2675
2676 // We need to wait until we have calculated proper stand positions before sitting up the physical
2677 // avatar to avoid race conditions.
2678 if (PhysicsActor == null)
2679 AddToPhysicalScene(false);
2680
2681 if (satOnObject)
2682 {
2683 SendAvatarDataToAllClients();
1833 m_requestedSitTargetID = 0; 2684 m_requestedSitTargetID = 0;
1834 2685
1835 part.RemoveSittingAvatar(UUID); 2686 part.RemoveSittingAvatar(this);
1836 2687
1837 if (part != null) 2688 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
1838 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
1839 } 2689 }
1840 2690
2691 else if (PhysicsActor == null)
2692 AddToPhysicalScene(false);
2693
1841 Animator.TrySetMovementAnimation("STAND"); 2694 Animator.TrySetMovementAnimation("STAND");
2695 TriggerScenePresenceUpdated();
1842 } 2696 }
1843 2697
1844 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) 2698 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
@@ -1885,14 +2739,10 @@ namespace OpenSim.Region.Framework.Scenes
1885 if (part == null) 2739 if (part == null)
1886 return; 2740 return;
1887 2741
1888 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1889 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1890
1891 if (PhysicsActor != null) 2742 if (PhysicsActor != null)
1892 m_sitAvatarHeight = PhysicsActor.Size.Z; 2743 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
1893 2744
1894 bool canSit = false; 2745 bool canSit = false;
1895 Vector3 pos = part.AbsolutePosition + offset;
1896 2746
1897 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) 2747 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
1898 { 2748 {
@@ -1902,45 +2752,88 @@ namespace OpenSim.Region.Framework.Scenes
1902 2752
1903 offset = part.SitTargetPosition; 2753 offset = part.SitTargetPosition;
1904 sitOrientation = part.SitTargetOrientation; 2754 sitOrientation = part.SitTargetOrientation;
2755
2756 if (!part.IsRoot)
2757 {
2758 // m_log.DebugFormat("Old sit orient {0}", sitOrientation);
2759 sitOrientation = part.RotationOffset * sitOrientation;
2760 // m_log.DebugFormat("New sit orient {0}", sitOrientation);
2761// m_log.DebugFormat("Old sit offset {0}", offset);
2762 offset = offset * part.RotationOffset;
2763// m_log.DebugFormat("New sit offset {0}", offset);
2764 }
2765
1905 canSit = true; 2766 canSit = true;
1906 } 2767 }
1907 else 2768 else
1908 { 2769 {
2770 if (PhysicsSit(part,offset)) // physics engine
2771 return;
2772
2773 Vector3 pos = part.AbsolutePosition + offset;
2774
1909 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) 2775 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10)
1910 { 2776 {
1911// m_log.DebugFormat(
1912// "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is unset and within 10m",
1913// Name, part.Name, part.LocalId);
1914
1915 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 2777 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1916 canSit = true; 2778 canSit = true;
1917 } 2779 }
1918// else
1919// {
1920// m_log.DebugFormat(
1921// "[SCENE PRESENCE]: Ignoring sit request of {0} on {1} {2} because sit target is unset and outside 10m",
1922// Name, part.Name, part.LocalId);
1923// }
1924 } 2780 }
1925 2781
1926 if (canSit) 2782 if (canSit)
1927 { 2783 {
2784
1928 if (PhysicsActor != null) 2785 if (PhysicsActor != null)
1929 { 2786 {
1930 // We can remove the physicsActor until they stand up. 2787 // We can remove the physicsActor until they stand up.
1931 RemoveFromPhysicalScene(); 2788 RemoveFromPhysicalScene();
1932 } 2789 }
1933 2790
1934 part.AddSittingAvatar(UUID); 2791 if (MovingToTarget)
2792 ResetMoveToTarget();
2793
2794 Velocity = Vector3.Zero;
2795
2796 part.AddSittingAvatar(this);
1935 2797
1936 cameraAtOffset = part.GetCameraAtOffset(); 2798 cameraAtOffset = part.GetCameraAtOffset();
2799
2800 if (!part.IsRoot && cameraAtOffset == Vector3.Zero)
2801 cameraAtOffset = part.ParentGroup.RootPart.GetCameraAtOffset();
2802
2803 bool cameraEyeOffsetFromRootForChild = false;
1937 cameraEyeOffset = part.GetCameraEyeOffset(); 2804 cameraEyeOffset = part.GetCameraEyeOffset();
2805
2806 if (!part.IsRoot && cameraEyeOffset == Vector3.Zero)
2807 {
2808 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
2809 cameraEyeOffsetFromRootForChild = true;
2810 }
2811
2812 if ((cameraEyeOffset != Vector3.Zero && !cameraEyeOffsetFromRootForChild) || cameraAtOffset != Vector3.Zero)
2813 {
2814 if (!part.IsRoot)
2815 {
2816 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
2817 cameraAtOffset += part.OffsetPosition;
2818 }
2819
2820 cameraEyeOffset += part.OffsetPosition;
2821 }
2822
2823// m_log.DebugFormat(
2824// "[SCENE PRESENCE]: Using cameraAtOffset {0}, cameraEyeOffset {1} for sit on {2} by {3} in {4}",
2825// cameraAtOffset, cameraEyeOffset, part.Name, Name, Scene.Name);
2826
1938 forceMouselook = part.GetForceMouselook(); 2827 forceMouselook = part.GetForceMouselook();
1939 2828
2829 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
2830 // being sat upon.
2831 offset += part.OffsetPosition;
2832
1940 ControllingClient.SendSitResponse( 2833 ControllingClient.SendSitResponse(
1941 targetID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 2834 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
1942 2835
1943 m_requestedSitTargetUUID = targetID; 2836 m_requestedSitTargetUUID = part.UUID;
1944 2837
1945 HandleAgentSit(ControllingClient, UUID); 2838 HandleAgentSit(ControllingClient, UUID);
1946 2839
@@ -1952,6 +2845,9 @@ namespace OpenSim.Region.Framework.Scenes
1952 2845
1953 public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset) 2846 public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset)
1954 { 2847 {
2848 if (IsChildAgent)
2849 return;
2850
1955 if (ParentID != 0) 2851 if (ParentID != 0)
1956 { 2852 {
1957 if (ParentPart.UUID == targetID) 2853 if (ParentPart.UUID == targetID)
@@ -1965,16 +2861,8 @@ namespace OpenSim.Region.Framework.Scenes
1965 if (part != null) 2861 if (part != null)
1966 { 2862 {
1967 m_requestedSitTargetID = part.LocalId; 2863 m_requestedSitTargetID = part.LocalId;
1968 m_requestedSitTargetUUID = targetID; 2864 m_requestedSitTargetUUID = part.UUID;
1969
1970// m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset);
1971 2865
1972 if (m_scene.PhysicsScene.SupportsRayCast())
1973 {
1974 //m_scene.PhysicsScene.RaycastWorld(Vector3.Zero,Vector3.Zero, 0.01f,new RaycastCallback());
1975 //SitRayCastAvatarPosition(part);
1976 //return;
1977 }
1978 } 2866 }
1979 else 2867 else
1980 { 2868 {
@@ -1984,200 +2872,119 @@ namespace OpenSim.Region.Framework.Scenes
1984 SendSitResponse(targetID, offset, Quaternion.Identity); 2872 SendSitResponse(targetID, offset, Quaternion.Identity);
1985 } 2873 }
1986 2874
1987 /* 2875 // returns false if does not suport so older sit can be tried
1988 public void SitRayCastAvatarPosition(SceneObjectPart part) 2876 public bool PhysicsSit(SceneObjectPart part, Vector3 offset)
1989 {
1990 Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
1991 Vector3 StartRayCastPosition = AbsolutePosition;
1992 Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
1993 float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
1994 m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionResponse);
1995 }
1996
1997 public void SitRayCastAvatarPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
1998 { 2877 {
1999 SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); 2878// TODO: Pull in these bits
2000 if (part != null) 2879 return false;
2001 { 2880/*
2002 if (hitYN) 2881 if (part == null || part.ParentGroup.IsAttachment)
2003 {
2004 if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
2005 {
2006 SitRaycastFindEdge(collisionPoint, normal);
2007 m_log.DebugFormat("[SIT]: Raycast Avatar Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
2008 }
2009 else
2010 {
2011 SitRayCastAvatarPositionCameraZ(part);
2012 }
2013 }
2014 else
2015 {
2016 SitRayCastAvatarPositionCameraZ(part);
2017 }
2018 }
2019 else
2020 { 2882 {
2021 ControllingClient.SendAlertMessage("Sit position no longer exists"); 2883 return true;
2022 m_requestedSitTargetUUID = UUID.Zero;
2023 m_requestedSitTargetID = 0;
2024 m_requestedSitOffset = Vector3.Zero;
2025 } 2884 }
2026 2885
2027 } 2886 if ( m_scene.PhysicsScene == null)
2028 2887 return false;
2029 public void SitRayCastAvatarPositionCameraZ(SceneObjectPart part)
2030 {
2031 // Next, try to raycast from the camera Z position
2032 Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
2033 Vector3 StartRayCastPosition = AbsolutePosition; StartRayCastPosition.Z = CameraPosition.Z;
2034 Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
2035 float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
2036 m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionCameraZResponse);
2037 }
2038 2888
2039 public void SitRayCastAvatarPositionCameraZResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) 2889 if (part.PhysActor == null)
2040 {
2041 SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
2042 if (part != null)
2043 { 2890 {
2044 if (hitYN) 2891 // none physcis shape
2045 { 2892 if (part.PhysicsShapeType == (byte)PhysicsShapeType.None)
2046 if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) 2893 ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot.");
2047 {
2048 SitRaycastFindEdge(collisionPoint, normal);
2049 m_log.DebugFormat("[SIT]: Raycast Avatar Position + CameraZ succeeded at point: {0}, normal:{1}", collisionPoint, normal);
2050 }
2051 else
2052 {
2053 SitRayCastCameraPosition(part);
2054 }
2055 }
2056 else 2894 else
2057 { 2895 { // non physical phantom TODO
2058 SitRayCastCameraPosition(part); 2896 ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot.");
2897 return false;
2059 } 2898 }
2060 } 2899 return true;
2061 else
2062 {
2063 ControllingClient.SendAlertMessage("Sit position no longer exists");
2064 m_requestedSitTargetUUID = UUID.Zero;
2065 m_requestedSitTargetID = 0;
2066 m_requestedSitOffset = Vector3.Zero;
2067 } 2900 }
2068 2901
2069 }
2070 2902
2071 public void SitRayCastCameraPosition(SceneObjectPart part) 2903 // not doing autopilot
2072 { 2904 m_requestedSitTargetID = 0;
2073 // Next, try to raycast from the camera position
2074 Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
2075 Vector3 StartRayCastPosition = CameraPosition;
2076 Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
2077 float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
2078 m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastCameraPositionResponse);
2079 }
2080 2905
2081 public void SitRayCastCameraPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) 2906 if (m_scene.PhysicsScene.SitAvatar(part.PhysActor, AbsolutePosition, CameraPosition, offset, new Vector3(0.35f, 0, 0.65f), PhysicsSitResponse) != 0)
2082 { 2907 return true;
2083 SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
2084 if (part != null)
2085 {
2086 if (hitYN)
2087 {
2088 if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
2089 {
2090 SitRaycastFindEdge(collisionPoint, normal);
2091 m_log.DebugFormat("[SIT]: Raycast Camera Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
2092 }
2093 else
2094 {
2095 SitRayHorizontal(part);
2096 }
2097 }
2098 else
2099 {
2100 SitRayHorizontal(part);
2101 }
2102 }
2103 else
2104 {
2105 ControllingClient.SendAlertMessage("Sit position no longer exists");
2106 m_requestedSitTargetUUID = UUID.Zero;
2107 m_requestedSitTargetID = 0;
2108 m_requestedSitOffset = Vector3.Zero;
2109 }
2110 2908
2909 return false;
2910*/
2111 } 2911 }
2112 2912
2113 public void SitRayHorizontal(SceneObjectPart part) 2913
2914 private bool CanEnterLandPosition(Vector3 testPos)
2114 { 2915 {
2115 // Next, try to raycast from the avatar position to fwd 2916 ILandObject land = m_scene.LandChannel.GetLandObject(testPos.X, testPos.Y);
2116 Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; 2917
2117 Vector3 StartRayCastPosition = CameraPosition; 2918 if (land == null || land.LandData.Name == "NO_LAND")
2118 Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); 2919 return true;
2119 float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); 2920
2120 m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastHorizontalResponse); 2921 return land.CanBeOnThisLand(UUID,testPos.Z);
2121 } 2922 }
2122 2923
2123 public void SitRayCastHorizontalResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) 2924 // status
2925 // < 0 ignore
2926 // 0 bad sit spot
2927 public void PhysicsSitResponse(int status, uint partID, Vector3 offset, Quaternion Orientation)
2124 { 2928 {
2125 SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); 2929 if (status < 0)
2126 if (part != null) 2930 return;
2931
2932 if (status == 0)
2127 { 2933 {
2128 if (hitYN) 2934 ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot.");
2129 { 2935 return;
2130 if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
2131 {
2132 SitRaycastFindEdge(collisionPoint, normal);
2133 m_log.DebugFormat("[SIT]: Raycast Horizontal Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
2134 // Next, try to raycast from the camera position
2135 Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
2136 Vector3 StartRayCastPosition = CameraPosition;
2137 Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
2138 float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
2139 //m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastResponseAvatarPosition);
2140 }
2141 else
2142 {
2143 ControllingClient.SendAlertMessage("Sit position not accessable.");
2144 m_requestedSitTargetUUID = UUID.Zero;
2145 m_requestedSitTargetID = 0;
2146 m_requestedSitOffset = Vector3.Zero;
2147 }
2148 }
2149 else
2150 {
2151 ControllingClient.SendAlertMessage("Sit position not accessable.");
2152 m_requestedSitTargetUUID = UUID.Zero;
2153 m_requestedSitTargetID = 0;
2154 m_requestedSitOffset = Vector3.Zero;
2155 }
2156 } 2936 }
2157 else 2937
2938 SceneObjectPart part = m_scene.GetSceneObjectPart(partID);
2939 if (part == null)
2940 return;
2941
2942 Vector3 targetPos = part.GetWorldPosition() + offset * part.GetWorldRotation();
2943 if(!CanEnterLandPosition(targetPos))
2158 { 2944 {
2159 ControllingClient.SendAlertMessage("Sit position no longer exists"); 2945 ControllingClient.SendAlertMessage(" Sit position on restricted land, try another spot");
2160 m_requestedSitTargetUUID = UUID.Zero; 2946 return;
2161 m_requestedSitTargetID = 0;
2162 m_requestedSitOffset = Vector3.Zero;
2163 } 2947 }
2164 2948
2165 } 2949 RemoveFromPhysicalScene();
2166 2950
2167 private void SitRaycastFindEdge(Vector3 collisionPoint, Vector3 collisionNormal) 2951 if (MovingToTarget)
2168 { 2952 ResetMoveToTarget();
2169 int i = 0; 2953
2170 //throw new NotImplementedException(); 2954 Velocity = Vector3.Zero;
2171 //m_requestedSitTargetUUID = UUID.Zero; 2955
2172 //m_requestedSitTargetID = 0; 2956 part.AddSittingAvatar(this);
2173 //m_requestedSitOffset = Vector3.Zero; 2957
2958 Vector3 cameraAtOffset = part.GetCameraAtOffset();
2959 Vector3 cameraEyeOffset = part.GetCameraEyeOffset();
2960 bool forceMouselook = part.GetForceMouselook();
2961
2962 ControllingClient.SendSitResponse(
2963 part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2964
2965 // not using autopilot
2174 2966
2175 SendSitResponse(ControllingClient, m_requestedSitTargetUUID, collisionPoint - m_requestedSitOffset, Quaternion.Identity); 2967 Rotation = Orientation;
2968 m_pos = offset;
2969
2970 m_requestedSitTargetID = 0;
2971
2972 ParentPart = part;
2973 ParentID = part.LocalId;
2974 if(status == 3)
2975 Animator.TrySetMovementAnimation("SIT_GROUND");
2976 else
2977 Animator.TrySetMovementAnimation("SIT");
2978 SendAvatarDataToAllClients();
2979
2980 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2176 } 2981 }
2177 */
2178 2982
2179 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) 2983 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
2180 { 2984 {
2985 if (IsChildAgent)
2986 return;
2987
2181 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 2988 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2182 2989
2183 if (part != null) 2990 if (part != null)
@@ -2205,23 +3012,75 @@ namespace OpenSim.Region.Framework.Scenes
2205 3012
2206 //Quaternion result = (sitTargetOrient * vq) * nq; 3013 //Quaternion result = (sitTargetOrient * vq) * nq;
2207 3014
2208 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 3015 double x, y, z, m1, m2;
2209 Rotation = sitTargetOrient; 3016
2210 ParentPosition = part.AbsolutePosition; 3017 Quaternion r = sitTargetOrient;
3018 m1 = r.X * r.X + r.Y * r.Y;
3019 m2 = r.Z * r.Z + r.W * r.W;
3020
3021 // Rotate the vector <0, 0, 1>
3022 x = 2 * (r.X * r.Z + r.Y * r.W);
3023 y = 2 * (-r.X * r.W + r.Y * r.Z);
3024 z = m2 - m1;
3025
3026 // Set m to be the square of the norm of r.
3027 double m = m1 + m2;
3028
3029 // This constant is emperically determined to be what is used in SL.
3030 // See also http://opensimulator.org/mantis/view.php?id=7096
3031 double offset = 0.05;
3032
3033 // Normally m will be ~ 1, but if someone passed a handcrafted quaternion
3034 // to llSitTarget with values so small that squaring them is rounded off
3035 // to zero, then m could be zero. The result of this floating point
3036 // round off error (causing us to skip this impossible normalization)
3037 // is only 5 cm.
3038 if (m > 0.000001)
3039 {
3040 offset /= m;
3041 }
3042
3043 Vector3 up = new Vector3((float)x, (float)y, (float)z);
3044 Vector3 sitOffset = up * (float)offset;
3045
3046 // sitOffset is in Avatar Center coordinates: from origin to 'sitTargetPos + SIT_TARGET_ADJUSTMENT'.
3047 // So, we need to _substract_ it to get to the origin of the Avatar Center.
3048 Vector3 newPos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset;
3049 Quaternion newRot;
3050
3051 if (part.IsRoot)
3052 {
3053 newRot = sitTargetOrient;
3054 }
3055 else
3056 {
3057 newPos = newPos * part.RotationOffset;
3058 newRot = part.RotationOffset * sitTargetOrient;
3059 }
3060
3061 newPos += part.OffsetPosition;
3062
3063 m_pos = newPos;
3064 Rotation = newRot;
3065
3066// ParentPosition = part.AbsolutePosition;
2211 } 3067 }
2212 else 3068 else
2213 { 3069 {
2214 m_pos -= part.AbsolutePosition; 3070 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
2215 ParentPosition = part.AbsolutePosition; 3071 // being sat upon.
3072 m_pos -= part.GroupPosition;
3073
3074// ParentPosition = part.AbsolutePosition;
2216 3075
2217// m_log.DebugFormat( 3076// m_log.DebugFormat(
2218// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 3077// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
2219// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); 3078// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
2220 } 3079 }
2221 3080
2222 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 3081 ParentPart = part;
2223 ParentID = m_requestedSitTargetID; 3082 ParentID = m_requestedSitTargetID;
2224 3083 m_AngularVelocity = Vector3.Zero;
2225 Velocity = Vector3.Zero; 3084 Velocity = Vector3.Zero;
2226 RemoveFromPhysicalScene(); 3085 RemoveFromPhysicalScene();
2227 3086
@@ -2231,14 +3090,20 @@ namespace OpenSim.Region.Framework.Scenes
2231 sitAnimation = part.SitAnimation; 3090 sitAnimation = part.SitAnimation;
2232 } 3091 }
2233 Animator.TrySetMovementAnimation(sitAnimation); 3092 Animator.TrySetMovementAnimation(sitAnimation);
2234 SendAvatarDataToAllAgents(); 3093 SendAvatarDataToAllClients();
3094 TriggerScenePresenceUpdated();
2235 } 3095 }
2236 } 3096 }
2237 3097
2238 public void HandleAgentSitOnGround() 3098 public void HandleAgentSitOnGround()
2239 { 3099 {
2240// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick. 3100 if (IsChildAgent)
3101 return;
3102
3103// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
3104 m_AngularVelocity = Vector3.Zero;
2241 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 3105 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
3106 TriggerScenePresenceUpdated();
2242 SitGround = true; 3107 SitGround = true;
2243 RemoveFromPhysicalScene(); 3108 RemoveFromPhysicalScene();
2244 } 3109 }
@@ -2255,22 +3120,39 @@ namespace OpenSim.Region.Framework.Scenes
2255 public void HandleStartAnim(IClientAPI remoteClient, UUID animID) 3120 public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
2256 { 3121 {
2257 Animator.AddAnimation(animID, UUID.Zero); 3122 Animator.AddAnimation(animID, UUID.Zero);
3123 TriggerScenePresenceUpdated();
2258 } 3124 }
2259 3125
2260 public void HandleStopAnim(IClientAPI remoteClient, UUID animID) 3126 public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
2261 { 3127 {
2262 Animator.RemoveAnimation(animID, false); 3128 Animator.RemoveAnimation(animID, false);
3129 TriggerScenePresenceUpdated();
2263 } 3130 }
2264 3131
2265 /// <summary> 3132 /// <summary>
2266 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 3133 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
2267 /// </summary> 3134 /// </summary>
2268 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 3135 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2269 public void AddNewMovement(Vector3 vec) 3136 /// <param name="thisAddSpeedModifier">
3137 /// Optional additional speed modifier for this particular add. Default is 1</param>
3138 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1)
2270 { 3139 {
2271// m_log.DebugFormat("[SCENE PRESENCE]: Adding new movement {0} for {1}", vec, Name); 3140// m_log.DebugFormat(
3141// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
3142// vec, Rotation, thisAddSpeedModifier, Name);
2272 3143
2273 Vector3 direc = vec * Rotation; 3144 Quaternion rot = Rotation;
3145 if (!Flying && PresenceType != PresenceType.Npc)
3146 {
3147 // The only situation in which we care about X and Y is avatar flying. The rest of the time
3148 // these parameters are not relevant for determining avatar movement direction and cause issues such
3149 // as wrong walk speed if the camera is rotated.
3150 rot.X = 0;
3151 rot.Y = 0;
3152 rot.Normalize();
3153 }
3154
3155 Vector3 direc = vec * rot;
2274 direc.Normalize(); 3156 direc.Normalize();
2275 3157
2276 if (Flying != FlyingOld) // add for fly velocity control 3158 if (Flying != FlyingOld) // add for fly velocity control
@@ -2286,7 +3168,9 @@ namespace OpenSim.Region.Framework.Scenes
2286 if ((vec.Z == 0f) && !Flying) 3168 if ((vec.Z == 0f) && !Flying)
2287 direc.Z = 0f; // Prevent camera WASD up. 3169 direc.Z = 0f; // Prevent camera WASD up.
2288 3170
2289 direc *= 0.03f * 128f * SpeedModifier; 3171 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier;
3172
3173// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
2290 3174
2291 if (PhysicsActor != null) 3175 if (PhysicsActor != null)
2292 { 3176 {
@@ -2315,14 +3199,17 @@ namespace OpenSim.Region.Framework.Scenes
2315 direc.Z *= 2.6f; 3199 direc.Z *= 2.6f;
2316 3200
2317 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 3201 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
2318 Animator.TrySetMovementAnimation("PREJUMP"); 3202// Animator.TrySetMovementAnimation("PREJUMP");
2319 Animator.TrySetMovementAnimation("JUMP"); 3203// Animator.TrySetMovementAnimation("JUMP");
2320 } 3204 }
2321 } 3205 }
2322 } 3206 }
2323 3207
3208// m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name);
3209
2324 // TODO: Add the force instead of only setting it to support multiple forces per frame? 3210 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2325 m_forceToApply = direc; 3211 m_forceToApply = direc;
3212 Animator.UpdateMovementAnimations();
2326 } 3213 }
2327 3214
2328 #endregion 3215 #endregion
@@ -2331,25 +3218,27 @@ namespace OpenSim.Region.Framework.Scenes
2331 3218
2332 public override void Update() 3219 public override void Update()
2333 { 3220 {
2334 const float ROTATION_TOLERANCE = 0.01f;
2335 const float VELOCITY_TOLERANCE = 0.001f;
2336 const float POSITION_TOLERANCE = 0.05f;
2337
2338 if (IsChildAgent == false) 3221 if (IsChildAgent == false)
2339 { 3222 {
2340 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to 3223 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to
2341 // grab the latest PhysicsActor velocity, whereas m_velocity is often 3224 // grab the latest PhysicsActor velocity, whereas m_velocity is often
2342 // storing a requested force instead of an actual traveling velocity 3225 // storing a requested force instead of an actual traveling velocity
2343 3226 if (Appearance.AvatarSize != m_lastSize && !IsLoggingIn)
2344 // Throw away duplicate or insignificant updates 3227 SendAvatarDataToAllClients();
2345 if ( 3228
2346 // If the velocity has become zero, send it no matter what. 3229 // Allow any updates for sitting avatars to that llSetPrimitiveLinkParams() can work for very
2347 (Velocity != m_lastVelocity && Velocity == Vector3.Zero) 3230 // small increments (e.g. sit position adjusters). An alternative may be to eliminate the tolerance
2348 // otherwise, if things have changed reasonably, send the update 3231 // checks on all updates but the ramifications of this would need careful consideration.
2349 || (!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) 3232 bool updateClients
2350 || !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) 3233 = IsSatOnObject && (Rotation != m_lastRotation || Velocity != m_lastVelocity || m_pos != m_lastPosition);
2351 || !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))) 3234
2352 3235 if (!updateClients)
3236 updateClients
3237 = !Rotation.ApproxEquals(m_lastRotation, Scene.RootRotationUpdateTolerance)
3238 || !Velocity.ApproxEquals(m_lastVelocity, Scene.RootVelocityUpdateTolerance)
3239 || !m_pos.ApproxEquals(m_lastPosition, Scene.RootPositionUpdateTolerance);
3240
3241 if (updateClients)
2353 { 3242 {
2354 SendTerseUpdateToAllClients(); 3243 SendTerseUpdateToAllClients();
2355 3244
@@ -2359,7 +3248,8 @@ namespace OpenSim.Region.Framework.Scenes
2359 m_lastVelocity = Velocity; 3248 m_lastVelocity = Velocity;
2360 } 3249 }
2361 3250
2362 CheckForBorderCrossing(); 3251 if (Scene.AllowAvatarCrossing)
3252 CheckForBorderCrossing();
2363 3253
2364 CheckForSignificantMovement(); // sends update to the modules. 3254 CheckForSignificantMovement(); // sends update to the modules.
2365 } 3255 }
@@ -2369,7 +3259,6 @@ namespace OpenSim.Region.Framework.Scenes
2369 3259
2370 #region Update Client(s) 3260 #region Update Client(s)
2371 3261
2372
2373 /// <summary> 3262 /// <summary>
2374 /// Sends a location update to the client connected to this scenePresence 3263 /// Sends a location update to the client connected to this scenePresence
2375 /// </summary> 3264 /// </summary>
@@ -2380,6 +3269,29 @@ namespace OpenSim.Region.Framework.Scenes
2380 // server. 3269 // server.
2381 if (remoteClient.IsActive) 3270 if (remoteClient.IsActive)
2382 { 3271 {
3272 if (Scene.RootTerseUpdatePeriod > 1)
3273 {
3274// Console.WriteLine(
3275// "{0} {1} {2} {3} {4} {5} for {6} to {7}",
3276// remoteClient.AgentId, UUID, remoteClient.SceneAgent.IsChildAgent, m_terseUpdateCount, Scene.RootTerseUpdatePeriod, Velocity.ApproxEquals(Vector3.Zero, 0.001f), Name, remoteClient.Name);
3277 if (remoteClient.AgentId != UUID
3278 && !remoteClient.SceneAgent.IsChildAgent
3279 && m_terseUpdateCount % Scene.RootTerseUpdatePeriod != 0
3280 && !Velocity.ApproxEquals(Vector3.Zero, 0.001f))
3281 {
3282// m_log.DebugFormat("[SCENE PRESENCE]: Discarded update from {0} to {1}, args {2} {3} {4} {5} {6} {7}",
3283// Name, remoteClient.Name, remoteClient.AgentId, UUID, remoteClient.SceneAgent.IsChildAgent, m_terseUpdateCount, Scene.RootTerseUpdatePeriod, Velocity.ApproxEquals(Vector3.Zero, 0.001f));
3284
3285 return;
3286 }
3287 }
3288
3289 if (Scene.ChildTerseUpdatePeriod > 1
3290 && remoteClient.SceneAgent.IsChildAgent
3291 && m_terseUpdateCount % Scene.ChildTerseUpdatePeriod != 0
3292 && !Velocity.ApproxEquals(Vector3.Zero, 0.001f))
3293 return;
3294
2383 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); 3295 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
2384 3296
2385 remoteClient.SendEntityUpdate( 3297 remoteClient.SendEntityUpdate(
@@ -2417,7 +3329,11 @@ namespace OpenSim.Region.Framework.Scenes
2417 float distanceError = Vector3.Distance(OffsetPosition, expectedPosition); 3329 float distanceError = Vector3.Distance(OffsetPosition, expectedPosition);
2418 3330
2419 float speed = Velocity.Length(); 3331 float speed = Velocity.Length();
2420 float velocidyDiff = Vector3.Distance(lastVelocitySentToAllClients, Velocity); 3332 float velocityDiff = Vector3.Distance(lastVelocitySentToAllClients, Velocity);
3333
3334// m_log.DebugFormat(
3335// "[SCENE PRESENCE]: Delta-v {0}, lastVelocity {1}, Velocity {2} for {3} in {4}",
3336// velocidyDiff, lastVelocitySentToAllClients, Velocity, Name, Scene.Name);
2421 3337
2422 // assuming 5 ms. worst case precision for timer, use 2x that 3338 // assuming 5 ms. worst case precision for timer, use 2x that
2423 // for distance error threshold 3339 // for distance error threshold
@@ -2425,12 +3341,19 @@ namespace OpenSim.Region.Framework.Scenes
2425 3341
2426 if (speed < 0.01f // allow rotation updates if avatar position is unchanged 3342 if (speed < 0.01f // allow rotation updates if avatar position is unchanged
2427 || Math.Abs(distanceError) > distanceErrorThreshold 3343 || Math.Abs(distanceError) > distanceErrorThreshold
2428 || velocidyDiff > 0.01f) // did velocity change from last update? 3344 || velocityDiff > 0.01f) // did velocity change from last update?
2429 { 3345 {
3346// m_log.DebugFormat(
3347// "[SCENE PRESENCE]: Update triggered with speed {0}, distanceError {1}, distanceThreshold {2}, delta-v {3} for {4} in {5}",
3348// speed, distanceError, distanceErrorThreshold, velocidyDiff, Name, Scene.Name);
3349
2430 lastVelocitySentToAllClients = Velocity; 3350 lastVelocitySentToAllClients = Velocity;
2431 lastTerseUpdateToAllClientsTick = currentTick; 3351 lastTerseUpdateToAllClientsTick = currentTick;
2432 lastPositionSentToAllClients = OffsetPosition; 3352 lastPositionSentToAllClients = OffsetPosition;
2433 3353
3354 m_terseUpdateCount++;
3355
3356// Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name);
2434 m_scene.ForEachClient(SendTerseUpdateToClient); 3357 m_scene.ForEachClient(SendTerseUpdateToClient);
2435 } 3358 }
2436 TriggerScenePresenceUpdated(); 3359 TriggerScenePresenceUpdated();
@@ -2456,24 +3379,30 @@ namespace OpenSim.Region.Framework.Scenes
2456 ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); 3379 ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations);
2457 } 3380 }
2458 3381
2459 public void SendInitialDataToMe() 3382 public void SendInitialDataToClient()
2460 { 3383 {
3384 SentInitialDataToClient = true;
3385
2461 // Send all scene object to the new client 3386 // Send all scene object to the new client
2462 Util.FireAndForget(delegate 3387 WorkManager.RunJob("SendInitialDataToClient", delegate
2463 { 3388 {
3389// m_log.DebugFormat(
3390// "[SCENE PRESENCE]: Sending initial data to {0} agent {1} in {2}, tp flags {3}",
3391// IsChildAgent ? "child" : "root", Name, Scene.Name, m_teleportFlags);
3392
2464 // we created a new ScenePresence (a new child agent) in a fresh region. 3393 // we created a new ScenePresence (a new child agent) in a fresh region.
2465 // Request info about all the (root) agents in this region 3394 // Request info about all the (root) agents in this region
2466 // Note: This won't send data *to* other clients in that region (children don't send) 3395 // Note: This won't send data *to* other clients in that region (children don't send)
2467 SendOtherAgentsAvatarDataToMe(); 3396 SendOtherAgentsAvatarDataToClient();
2468 SendOtherAgentsAppearanceToMe(); 3397 SendOtherAgentsAppearanceToClient();
2469 3398
2470 EntityBase[] entities = Scene.Entities.GetEntities(); 3399 EntityBase[] entities = Scene.Entities.GetEntities();
2471 foreach(EntityBase e in entities) 3400 foreach (EntityBase e in entities)
2472 { 3401 {
2473 if (e != null && e is SceneObjectGroup) 3402 if (e != null && e is SceneObjectGroup)
2474 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); 3403 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
2475 } 3404 }
2476 }); 3405 }, null, string.Format("SendInitialDataToClient ({0} in {1})", Name, Scene.Name), false, true);
2477 } 3406 }
2478 3407
2479 /// <summary> 3408 /// <summary>
@@ -2506,26 +3435,33 @@ namespace OpenSim.Region.Framework.Scenes
2506 // getting other avatars information was initiated elsewhere immediately after the child circuit connected... don't do it 3435 // getting other avatars information was initiated elsewhere immediately after the child circuit connected... don't do it
2507 // again here... this comes after the cached appearance check because the avatars 3436 // again here... this comes after the cached appearance check because the avatars
2508 // appearance goes into the avatar update packet 3437 // appearance goes into the avatar update packet
2509 SendAvatarDataToAllAgents(); 3438 SendAvatarDataToAllClients();
2510 SendAppearanceToAgent(this); 3439
3440 // This invocation always shows up in the viewer logs as an error. Is it needed?
3441 SendAppearanceToClient(this);
2511 3442
2512 // If we are using the the cached appearance then send it out to everyone 3443 // If we are using the the cached appearance then send it out to everyone
2513 if (cachedappearance) 3444 if (cachedappearance)
2514 { 3445 {
2515 m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name); 3446 m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name);
2516 3447
2517 // If the avatars baked textures are all in the cache, then we have a 3448 // If the avatars baked textures are all in the cache, then we have a
2518 // complete appearance... send it out, if not, then we'll send it when 3449 // complete appearance... send it out, if not, then we'll send it when
2519 // the avatar finishes updating its appearance 3450 // the avatar finishes updating its appearance
2520 SendAppearanceToAllOtherAgents(); 3451 SendAppearanceToAllOtherClients();
2521 } 3452 }
2522 } 3453 }
2523 3454
3455 public void SendAvatarDataToAllClients()
3456 {
3457 SendAvatarDataToAllClients(true);
3458 }
3459
2524 /// <summary> 3460 /// <summary>
2525 /// Send this agent's avatar data to all other root and child agents in the scene 3461 /// Send this agent's avatar data to all other root and child agents in the scene
2526 /// This agent must be root. This avatar will receive its own update. 3462 /// This agent must be root. This avatar will receive its own update.
2527 /// </summary> 3463 /// </summary>
2528 public void SendAvatarDataToAllAgents() 3464 public void SendAvatarDataToAllClients(bool full)
2529 { 3465 {
2530 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID); 3466 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID);
2531 // only send update from root agents to other clients; children are only "listening posts" 3467 // only send update from root agents to other clients; children are only "listening posts"
@@ -2538,12 +3474,17 @@ namespace OpenSim.Region.Framework.Scenes
2538 return; 3474 return;
2539 } 3475 }
2540 3476
3477 m_lastSize = Appearance.AvatarSize;
3478
2541 int count = 0; 3479 int count = 0;
2542 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3480 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
2543 { 3481 {
2544 SendAvatarDataToAgent(scenePresence); 3482 if (full)
2545 count++; 3483 SendAvatarDataToClient(scenePresence);
2546 }); 3484 else
3485 scenePresence.ControllingClient.SendAvatarDataImmediate(this);
3486 count++;
3487 });
2547 3488
2548 m_scene.StatsReporter.AddAgentUpdates(count); 3489 m_scene.StatsReporter.AddAgentUpdates(count);
2549 } 3490 }
@@ -2552,7 +3493,7 @@ namespace OpenSim.Region.Framework.Scenes
2552 /// Send avatar data for all other root agents to this agent, this agent 3493 /// Send avatar data for all other root agents to this agent, this agent
2553 /// can be either a child or root 3494 /// can be either a child or root
2554 /// </summary> 3495 /// </summary>
2555 public void SendOtherAgentsAvatarDataToMe() 3496 public void SendOtherAgentsAvatarDataToClient()
2556 { 3497 {
2557 int count = 0; 3498 int count = 0;
2558 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) 3499 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence)
@@ -2561,7 +3502,7 @@ namespace OpenSim.Region.Framework.Scenes
2561 if (scenePresence.UUID == UUID) 3502 if (scenePresence.UUID == UUID)
2562 return; 3503 return;
2563 3504
2564 scenePresence.SendAvatarDataToAgent(this); 3505 scenePresence.SendAvatarDataToClient(this);
2565 count++; 3506 count++;
2566 }); 3507 });
2567 3508
@@ -2572,9 +3513,9 @@ namespace OpenSim.Region.Framework.Scenes
2572 /// Send avatar data to an agent. 3513 /// Send avatar data to an agent.
2573 /// </summary> 3514 /// </summary>
2574 /// <param name="avatar"></param> 3515 /// <param name="avatar"></param>
2575 public void SendAvatarDataToAgent(ScenePresence avatar) 3516 public void SendAvatarDataToClient(ScenePresence avatar)
2576 { 3517 {
2577 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); 3518 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToClient from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
2578 3519
2579 avatar.ControllingClient.SendAvatarDataImmediate(this); 3520 avatar.ControllingClient.SendAvatarDataImmediate(this);
2580 Animator.SendAnimPackToClient(avatar.ControllingClient); 3521 Animator.SendAnimPackToClient(avatar.ControllingClient);
@@ -2584,9 +3525,9 @@ namespace OpenSim.Region.Framework.Scenes
2584 /// Send this agent's appearance to all other root and child agents in the scene 3525 /// Send this agent's appearance to all other root and child agents in the scene
2585 /// This agent must be root. 3526 /// This agent must be root.
2586 /// </summary> 3527 /// </summary>
2587 public void SendAppearanceToAllOtherAgents() 3528 public void SendAppearanceToAllOtherClients()
2588 { 3529 {
2589// m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID); 3530// m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherClients: {0} {1}", Name, UUID);
2590 3531
2591 // only send update from root agents to other clients; children are only "listening posts" 3532 // only send update from root agents to other clients; children are only "listening posts"
2592 if (IsChildAgent) 3533 if (IsChildAgent)
@@ -2605,7 +3546,7 @@ namespace OpenSim.Region.Framework.Scenes
2605 if (scenePresence.UUID == UUID) 3546 if (scenePresence.UUID == UUID)
2606 return; 3547 return;
2607 3548
2608 SendAppearanceToAgent(scenePresence); 3549 SendAppearanceToClient(scenePresence);
2609 count++; 3550 count++;
2610 }); 3551 });
2611 3552
@@ -2616,9 +3557,9 @@ namespace OpenSim.Region.Framework.Scenes
2616 /// Send appearance from all other root agents to this agent. this agent 3557 /// Send appearance from all other root agents to this agent. this agent
2617 /// can be either root or child 3558 /// can be either root or child
2618 /// </summary> 3559 /// </summary>
2619 public void SendOtherAgentsAppearanceToMe() 3560 public void SendOtherAgentsAppearanceToClient()
2620 { 3561 {
2621// m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} {1}", Name, UUID); 3562// m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToClient {0} {1}", Name, UUID);
2622 3563
2623 int count = 0; 3564 int count = 0;
2624 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) 3565 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence)
@@ -2627,7 +3568,7 @@ namespace OpenSim.Region.Framework.Scenes
2627 if (scenePresence.UUID == UUID) 3568 if (scenePresence.UUID == UUID)
2628 return; 3569 return;
2629 3570
2630 scenePresence.SendAppearanceToAgent(this); 3571 scenePresence.SendAppearanceToClient(this);
2631 count++; 3572 count++;
2632 }); 3573 });
2633 3574
@@ -2638,13 +3579,15 @@ namespace OpenSim.Region.Framework.Scenes
2638 /// Send appearance data to an agent. 3579 /// Send appearance data to an agent.
2639 /// </summary> 3580 /// </summary>
2640 /// <param name="avatar"></param> 3581 /// <param name="avatar"></param>
2641 public void SendAppearanceToAgent(ScenePresence avatar) 3582 public void SendAppearanceToClient(ScenePresence avatar)
2642 { 3583 {
2643// m_log.DebugFormat( 3584// m_log.DebugFormat(
2644// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID); 3585// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID);
2645 3586
2646 avatar.ControllingClient.SendAppearance( 3587 avatar.ControllingClient.SendAppearance(
2647 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); 3588 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
3589
3590
2648 } 3591 }
2649 3592
2650 #endregion 3593 #endregion
@@ -2663,11 +3606,10 @@ namespace OpenSim.Region.Framework.Scenes
2663 } 3606 }
2664 3607
2665 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m 3608 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
2666 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || 3609 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance)
2667 Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
2668 { 3610 {
2669 m_lastChildAgentUpdatePosition = AbsolutePosition; 3611 m_lastChildAgentUpdatePosition = AbsolutePosition;
2670 m_lastChildAgentUpdateCamPosition = CameraPosition; 3612// m_lastChildAgentUpdateCamPosition = CameraPosition;
2671 3613
2672 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); 3614 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
2673 cadu.ActiveGroupID = UUID.Zero.Guid; 3615 cadu.ActiveGroupID = UUID.Zero.Guid;
@@ -2694,10 +3636,11 @@ namespace OpenSim.Region.Framework.Scenes
2694 cadu.Velocity = Velocity; 3636 cadu.Velocity = Velocity;
2695 3637
2696 AgentPosition agentpos = new AgentPosition(); 3638 AgentPosition agentpos = new AgentPosition();
2697 agentpos.CopyFrom(cadu); 3639 agentpos.CopyFrom(cadu, ControllingClient.SessionId);
2698 3640
2699 // Let's get this out of the update loop 3641 // Let's get this out of the update loop
2700 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); 3642 Util.FireAndForget(
3643 o => m_scene.SendOutChildAgentUpdates(agentpos, this), null, "ScenePresence.SendOutChildAgentUpdates");
2701 } 3644 }
2702 } 3645 }
2703 3646
@@ -2719,140 +3662,84 @@ namespace OpenSim.Region.Framework.Scenes
2719 3662
2720 // If we don't have a PhysActor, we can't cross anyway 3663 // If we don't have a PhysActor, we can't cross anyway
2721 // Also don't do this while sat, sitting avatars cross with the 3664 // Also don't do this while sat, sitting avatars cross with the
2722 // object they sit on. 3665 // object they sit on. ParentUUID denoted a pending sit, don't
2723 if (ParentID != 0 || PhysicsActor == null) 3666 // interfere with it.
3667 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero)
2724 return; 3668 return;
2725 3669
2726 if (!IsInTransit) 3670 if (IsInTransit)
2727 { 3671 return;
2728 Vector3 pos2 = AbsolutePosition;
2729 Vector3 vel = Velocity;
2730 int neighbor = 0;
2731 int[] fix = new int[2];
2732 3672
2733 float timeStep = 0.1f; 3673 Vector3 pos2 = AbsolutePosition;
2734 pos2.X = pos2.X + (vel.X * timeStep); 3674 Vector3 origPosition = pos2;
2735 pos2.Y = pos2.Y + (vel.Y * timeStep); 3675 Vector3 vel = Velocity;
2736 pos2.Z = pos2.Z + (vel.Z * timeStep);
2737 3676
2738 if (!IsInTransit) 3677 // Compute the future avatar position.
2739 { 3678 // If the avatar will be crossing, we force the crossing to happen now
2740 // Checks if where it's headed exists a region 3679 // in the hope that this will make the avatar movement smoother when crossing.
2741 bool needsTransit = false; 3680 pos2 += vel * 0.05f;
2742 if (m_scene.TestBorderCross(pos2, Cardinals.W))
2743 {
2744 if (m_scene.TestBorderCross(pos2, Cardinals.S))
2745 {
2746 needsTransit = true;
2747 neighbor = m_scene.HaveNeighbor(Cardinals.SW, ref fix);
2748 }
2749 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
2750 {
2751 needsTransit = true;
2752 neighbor = m_scene.HaveNeighbor(Cardinals.NW, ref fix);
2753 }
2754 else
2755 {
2756 needsTransit = true;
2757 neighbor = m_scene.HaveNeighbor(Cardinals.W, ref fix);
2758 }
2759 }
2760 else if (m_scene.TestBorderCross(pos2, Cardinals.E))
2761 {
2762 if (m_scene.TestBorderCross(pos2, Cardinals.S))
2763 {
2764 needsTransit = true;
2765 neighbor = m_scene.HaveNeighbor(Cardinals.SE, ref fix);
2766 }
2767 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
2768 {
2769 needsTransit = true;
2770 neighbor = m_scene.HaveNeighbor(Cardinals.NE, ref fix);
2771 }
2772 else
2773 {
2774 needsTransit = true;
2775 neighbor = m_scene.HaveNeighbor(Cardinals.E, ref fix);
2776 }
2777 }
2778 else if (m_scene.TestBorderCross(pos2, Cardinals.S))
2779 {
2780 needsTransit = true;
2781 neighbor = m_scene.HaveNeighbor(Cardinals.S, ref fix);
2782 }
2783 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
2784 {
2785 needsTransit = true;
2786 neighbor = m_scene.HaveNeighbor(Cardinals.N, ref fix);
2787 }
2788 3681
2789 // Makes sure avatar does not end up outside region 3682 if (m_scene.PositionIsInCurrentRegion(pos2))
2790 if (neighbor <= 0) 3683 return;
2791 { 3684
2792 if (needsTransit) 3685 m_log.DebugFormat("{0} CheckForBorderCrossing: position outside region. {1} in {2} at pos {3}",
2793 { 3686 LogHeader, Name, Scene.Name, pos2);
2794 if (m_requestedSitTargetUUID == UUID.Zero) 3687
2795 { 3688 // Disconnect from the current region
2796 bool isFlying = Flying; 3689 bool isFlying = Flying;
2797 RemoveFromPhysicalScene(); 3690 RemoveFromPhysicalScene();
2798 3691
2799 Vector3 pos = AbsolutePosition; 3692 // pos2 is the forcasted position so make that the 'current' position so the crossing
2800 if (AbsolutePosition.X < 0) 3693 // code will move us into the newly addressed region.
2801 pos.X += Velocity.X * 2; 3694 m_pos = pos2;
2802 else if (AbsolutePosition.X > Constants.RegionSize) 3695
2803 pos.X -= Velocity.X * 2; 3696 if (CrossToNewRegion())
2804 if (AbsolutePosition.Y < 0) 3697 {
2805 pos.Y += Velocity.Y * 2; 3698 AddToPhysicalScene(isFlying);
2806 else if (AbsolutePosition.Y > Constants.RegionSize) 3699 }
2807 pos.Y -= Velocity.Y * 2; 3700 else
2808 Velocity = Vector3.Zero; 3701 {
2809 AbsolutePosition = pos; 3702 // Tried to make crossing happen but it failed.
2810 3703 if (m_requestedSitTargetUUID == UUID.Zero)
2811// m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition);
2812
2813 AddToPhysicalScene(isFlying);
2814 }
2815 }
2816 }
2817 else if (neighbor > 0)
2818 {
2819 if (!CrossToNewRegion())
2820 {
2821 if (m_requestedSitTargetUUID == UUID.Zero)
2822 {
2823 bool isFlying = Flying;
2824 RemoveFromPhysicalScene();
2825
2826 Vector3 pos = AbsolutePosition;
2827 if (AbsolutePosition.X < 0)
2828 pos.X += Velocity.X * 2;
2829 else if (AbsolutePosition.X > Constants.RegionSize)
2830 pos.X -= Velocity.X * 2;
2831 if (AbsolutePosition.Y < 0)
2832 pos.Y += Velocity.Y * 2;
2833 else if (AbsolutePosition.Y > Constants.RegionSize)
2834 pos.Y -= Velocity.Y * 2;
2835 Velocity = Vector3.Zero;
2836 AbsolutePosition = pos;
2837
2838 AddToPhysicalScene(isFlying);
2839 }
2840 }
2841 }
2842 }
2843 else
2844 { 3704 {
2845 // This constant has been inferred from experimentation 3705 m_log.DebugFormat("{0} CheckForBorderCrossing: Crossing failed. Restoring old position.", LogHeader);
2846 // I'm not sure what this value should be, so I tried a few values. 3706
2847 timeStep = 0.04f; 3707 Velocity = Vector3.Zero;
2848 pos2 = AbsolutePosition; 3708 AbsolutePosition = EnforceSanityOnPosition(origPosition);
2849 pos2.X = pos2.X + (vel.X * timeStep); 3709
2850 pos2.Y = pos2.Y + (vel.Y * timeStep); 3710 AddToPhysicalScene(isFlying);
2851 // Don't touch the Z
2852 m_pos = pos2;
2853 m_log.DebugFormat("[SCENE PRESENCE]: In transit m_pos={0}", m_pos);
2854 } 3711 }
2855 } 3712 }
3713 }
3714
3715 // Given a position, make sure it is within the current region.
3716 // If just outside some border, the returned position will be just inside the border on that side.
3717 private Vector3 EnforceSanityOnPosition(Vector3 origPosition)
3718 {
3719 const float borderFudge = 0.1f;
3720 Vector3 ret = origPosition;
3721
3722 // Sanity checking on the position to make sure it is in the region we couldn't cross from
3723 float extentX = (float)m_scene.RegionInfo.RegionSizeX;
3724 float extentY = (float)m_scene.RegionInfo.RegionSizeY;
3725 IRegionCombinerModule combiner = m_scene.RequestModuleInterface<IRegionCombinerModule>();
3726 if (combiner != null)
3727 {
3728 // If a mega-region, the size could be much bigger
3729 Vector2 megaExtent = combiner.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
3730 extentX = megaExtent.X;
3731 extentY = megaExtent.Y;
3732 }
3733 if (ret.X < 0)
3734 ret.X = borderFudge;
3735 else if (ret.X >= extentX)
3736 ret.X = extentX - borderFudge;
3737 if (ret.Y < 0)
3738 ret.Y = borderFudge;
3739 else if (ret.Y >= extentY)
3740 ret.Y = extentY - borderFudge;
3741
3742 return ret;
2856 } 3743 }
2857 3744
2858 /// <summary> 3745 /// <summary>
@@ -2873,18 +3760,13 @@ namespace OpenSim.Region.Framework.Scenes
2873 } 3760 }
2874 } 3761 }
2875 3762
2876 public void RestoreInCurrentScene()
2877 {
2878 AddToPhysicalScene(false); // not exactly false
2879 }
2880
2881 public void Reset() 3763 public void Reset()
2882 { 3764 {
2883// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); 3765// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
2884 3766
2885 // Put the child agent back at the center 3767 // Put the child agent back at the center
2886 AbsolutePosition 3768 AbsolutePosition
2887 = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70); 3769 = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
2888 3770
2889 Animator.ResetAnimations(); 3771 Animator.ResetAnimations();
2890 } 3772 }
@@ -2911,13 +3793,13 @@ namespace OpenSim.Region.Framework.Scenes
2911 if (handle != Scene.RegionInfo.RegionHandle) 3793 if (handle != Scene.RegionInfo.RegionHandle)
2912 { 3794 {
2913 uint x, y; 3795 uint x, y;
2914 Utils.LongToUInts(handle, out x, out y); 3796 Util.RegionHandleToRegionLoc(handle, out x, out y);
2915 x = x / Constants.RegionSize;
2916 y = y / Constants.RegionSize;
2917 3797
2918// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); 3798// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
2919// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); 3799// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
2920 if (Util.IsOutsideView(DrawDistance, x, newRegionX, y, newRegionY)) 3800 float dist = (float)Math.Max(Scene.DefaultDrawDistance,
3801 (float)Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
3802 if (Util.IsOutsideView(dist, x, newRegionX, y, newRegionY))
2921 { 3803 {
2922 byebyeRegions.Add(handle); 3804 byebyeRegions.Add(handle);
2923 } 3805 }
@@ -2927,10 +3809,12 @@ namespace OpenSim.Region.Framework.Scenes
2927 if (byebyeRegions.Count > 0) 3809 if (byebyeRegions.Count > 0)
2928 { 3810 {
2929 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); 3811 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
2930 Util.FireAndForget(delegate 3812
2931 { 3813 AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID);
2932 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, byebyeRegions); 3814 string auth = string.Empty;
2933 }); 3815 if (acd != null)
3816 auth = acd.SessionID.ToString();
3817 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
2934 } 3818 }
2935 3819
2936 foreach (ulong handle in byebyeRegions) 3820 foreach (ulong handle in byebyeRegions)
@@ -2971,36 +3855,45 @@ namespace OpenSim.Region.Framework.Scenes
2971 3855
2972 #region Child Agent Updates 3856 #region Child Agent Updates
2973 3857
2974 public void ChildAgentDataUpdate(AgentData cAgentData) 3858 public void UpdateChildAgent(AgentData cAgentData)
2975 { 3859 {
2976// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); 3860// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
2977 if (!IsChildAgent) 3861 if (!IsChildAgent)
2978 return; 3862 return;
2979 3863
2980 CopyFrom(cAgentData); 3864 CopyFrom(cAgentData);
3865
3866 m_updateAgentReceivedAfterTransferEvent.Set();
2981 } 3867 }
2982 3868
2983 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 3869 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
3870
2984 /// <summary> 3871 /// <summary>
2985 /// This updates important decision making data about a child agent 3872 /// This updates important decision making data about a child agent
2986 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region 3873 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
2987 /// </summary> 3874 /// </summary>
2988 public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) 3875 public void UpdateChildAgent(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
2989 { 3876 {
2990 if (!IsChildAgent) 3877 if (!IsChildAgent)
2991 return; 3878 return;
2992 3879
2993 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); 3880// m_log.DebugFormat(
2994 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; 3881// "[SCENE PRESENCE]: ChildAgentPositionUpdate for {0} in {1}, tRegion {2},{3}, rRegion {4},{5}, pos {6}",
2995 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; 3882// Name, Scene.Name, tRegionX, tRegionY, rRegionX, rRegionY, cAgentData.Position);
3883
3884 // Find the distance (in meters) between the two regions
3885 // XXX: We cannot use Util.RegionLocToHandle() here because a negative value will silently overflow the
3886 // uint
3887 int shiftx = (int)(((int)rRegionX - (int)tRegionX) * Constants.RegionSize);
3888 int shifty = (int)(((int)rRegionY - (int)tRegionY) * Constants.RegionSize);
2996 3889
2997 Vector3 offset = new Vector3(shiftx, shifty, 0f); 3890 Vector3 offset = new Vector3(shiftx, shifty, 0f);
2998 3891
2999 // When we get to the point of re-computing neighbors everytime this 3892 // When we get to the point of re-computing neighbors everytime this
3000 // changes, then start using the agent's drawdistance rather than the 3893 // changes, then start using the agent's drawdistance rather than the
3001 // region's draw distance. 3894 // region's draw distance.
3002 // DrawDistance = cAgentData.Far; 3895 DrawDistance = cAgentData.Far;
3003 DrawDistance = Scene.DefaultDrawDistance; 3896 // DrawDistance = Scene.DefaultDrawDistance;
3004 3897
3005 if (cAgentData.Position != marker) // UGH!! 3898 if (cAgentData.Position != marker) // UGH!!
3006 m_pos = cAgentData.Position + offset; 3899 m_pos = cAgentData.Position + offset;
@@ -3027,6 +3920,7 @@ namespace OpenSim.Region.Framework.Scenes
3027 3920
3028 cAgent.AgentID = UUID; 3921 cAgent.AgentID = UUID;
3029 cAgent.RegionID = Scene.RegionInfo.RegionID; 3922 cAgent.RegionID = Scene.RegionInfo.RegionID;
3923 cAgent.SessionID = ControllingClient.SessionId;
3030 3924
3031 cAgent.Position = AbsolutePosition; 3925 cAgent.Position = AbsolutePosition;
3032 cAgent.Velocity = m_velocity; 3926 cAgent.Velocity = m_velocity;
@@ -3061,6 +3955,9 @@ namespace OpenSim.Region.Framework.Scenes
3061 cAgent.AlwaysRun = SetAlwaysRun; 3955 cAgent.AlwaysRun = SetAlwaysRun;
3062 3956
3063 cAgent.Appearance = new AvatarAppearance(Appearance); 3957 cAgent.Appearance = new AvatarAppearance(Appearance);
3958
3959 cAgent.ParentPart = ParentUUID;
3960 cAgent.SitOffset = PrevSitOffset;
3064 3961
3065 lock (scriptedcontrols) 3962 lock (scriptedcontrols)
3066 { 3963 {
@@ -3069,7 +3966,7 @@ namespace OpenSim.Region.Framework.Scenes
3069 3966
3070 foreach (ScriptControllers c in scriptedcontrols.Values) 3967 foreach (ScriptControllers c in scriptedcontrols.Values)
3071 { 3968 {
3072 controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls); 3969 controls[i++] = new ControllerData(c.objectID, c.itemID, (uint)c.ignoreControls, (uint)c.eventControls);
3073 } 3970 }
3074 cAgent.Controllers = controls; 3971 cAgent.Controllers = controls;
3075 } 3972 }
@@ -3089,8 +3986,6 @@ namespace OpenSim.Region.Framework.Scenes
3089 3986
3090 private void CopyFrom(AgentData cAgent) 3987 private void CopyFrom(AgentData cAgent)
3091 { 3988 {
3092 m_originRegionID = cAgent.RegionID;
3093
3094 m_callbackURI = cAgent.CallbackURI; 3989 m_callbackURI = cAgent.CallbackURI;
3095// m_log.DebugFormat( 3990// m_log.DebugFormat(
3096// "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()", 3991// "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()",
@@ -3102,12 +3997,14 @@ namespace OpenSim.Region.Framework.Scenes
3102 CameraAtAxis = cAgent.AtAxis; 3997 CameraAtAxis = cAgent.AtAxis;
3103 CameraLeftAxis = cAgent.LeftAxis; 3998 CameraLeftAxis = cAgent.LeftAxis;
3104 CameraUpAxis = cAgent.UpAxis; 3999 CameraUpAxis = cAgent.UpAxis;
4000 ParentUUID = cAgent.ParentPart;
4001 PrevSitOffset = cAgent.SitOffset;
3105 4002
3106 // When we get to the point of re-computing neighbors everytime this 4003 // When we get to the point of re-computing neighbors everytime this
3107 // changes, then start using the agent's drawdistance rather than the 4004 // changes, then start using the agent's drawdistance rather than the
3108 // region's draw distance. 4005 // region's draw distance.
3109 // DrawDistance = cAgent.Far; 4006 DrawDistance = cAgent.Far;
3110 DrawDistance = Scene.DefaultDrawDistance; 4007 // DrawDistance = Scene.DefaultDrawDistance;
3111 4008
3112 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) 4009 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
3113 ControllingClient.SetChildAgentThrottle(cAgent.Throttles); 4010 ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
@@ -3139,6 +4036,7 @@ namespace OpenSim.Region.Framework.Scenes
3139 foreach (ControllerData c in cAgent.Controllers) 4036 foreach (ControllerData c in cAgent.Controllers)
3140 { 4037 {
3141 ScriptControllers sc = new ScriptControllers(); 4038 ScriptControllers sc = new ScriptControllers();
4039 sc.objectID = c.ObjectID;
3142 sc.itemID = c.ItemID; 4040 sc.itemID = c.ItemID;
3143 sc.ignoreControls = (ScriptControlled)c.IgnoreControls; 4041 sc.ignoreControls = (ScriptControlled)c.IgnoreControls;
3144 sc.eventControls = (ScriptControlled)c.EventControls; 4042 sc.eventControls = (ScriptControlled)c.EventControls;
@@ -3159,7 +4057,27 @@ namespace OpenSim.Region.Framework.Scenes
3159 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); 4057 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero);
3160 4058
3161 if (Scene.AttachmentsModule != null) 4059 if (Scene.AttachmentsModule != null)
3162 Scene.AttachmentsModule.CopyAttachments(cAgent, this); 4060 {
4061 // If the JobEngine is running we can schedule this job now and continue rather than waiting for all
4062 // attachments to copy, which might take a long time in the Hypergrid case as the entire inventory
4063 // graph is inspected for each attachments and assets possibly fetched.
4064 //
4065 // We don't need to worry about a race condition as the job to later start the scripts is also
4066 // JobEngine scheduled and so will always occur after this task.
4067 // XXX: This will not be true if JobEngine ever gets more than one thread.
4068 WorkManager.RunJob(
4069 "CopyAttachments",
4070 o => Scene.AttachmentsModule.CopyAttachments(cAgent, this),
4071 null,
4072 string.Format("Copy attachments for {0} entering {1}", Name, Scene.Name),
4073 true);
4074 }
4075
4076 // This must occur after attachments are copied or scheduled to be copied, as it releases the CompleteMovement() calling thread
4077 // originating from the client completing a teleport. Otherwise, CompleteMovement() code to restart
4078 // script attachments can outrace this thread.
4079 lock (m_originRegionIDAccessLock)
4080 m_originRegionID = cAgent.RegionID;
3163 } 4081 }
3164 4082
3165 public bool CopyAgent(out IAgentData agent) 4083 public bool CopyAgent(out IAgentData agent)
@@ -3180,8 +4098,6 @@ namespace OpenSim.Region.Framework.Scenes
3180 { 4098 {
3181 Vector3 force = m_forceToApply.Value; 4099 Vector3 force = m_forceToApply.Value;
3182 4100
3183 Updated = true;
3184
3185 Velocity = force; 4101 Velocity = force;
3186 4102
3187 m_forceToApply = null; 4103 m_forceToApply = null;
@@ -3206,20 +4122,23 @@ namespace OpenSim.Region.Framework.Scenes
3206 } 4122 }
3207 4123
3208 if (Appearance.AvatarHeight == 0) 4124 if (Appearance.AvatarHeight == 0)
3209 Appearance.SetHeight(); 4125// Appearance.SetHeight();
3210 4126 Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f));
3211 PhysicsScene scene = m_scene.PhysicsScene; 4127
3212 4128/*
3213 Vector3 pVec = AbsolutePosition;
3214
3215 PhysicsActor = scene.AddAvatar( 4129 PhysicsActor = scene.AddAvatar(
3216 LocalId, Firstname + "." + Lastname, pVec, 4130 LocalId, Firstname + "." + Lastname, pVec,
3217 new Vector3(0f, 0f, Appearance.AvatarHeight), isFlying); 4131 new Vector3(0.45f, 0.6f, Appearance.AvatarHeight), isFlying);
4132*/
4133
4134 PhysicsActor = m_scene.PhysicsScene.AddAvatar(
4135 LocalId, Firstname + "." + Lastname, AbsolutePosition, Velocity,
4136 Appearance.AvatarBoxSize, isFlying);
3218 4137
3219 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 4138 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3220 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 4139 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
3221 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong 4140 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
3222 PhysicsActor.SubscribeEvents(500); 4141 PhysicsActor.SubscribeEvents(100);
3223 PhysicsActor.LocalID = LocalId; 4142 PhysicsActor.LocalID = LocalId;
3224 } 4143 }
3225 4144
@@ -3233,6 +4152,7 @@ namespace OpenSim.Region.Framework.Scenes
3233 ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true); 4152 ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true);
3234 } 4153 }
3235 4154
4155
3236 /// <summary> 4156 /// <summary>
3237 /// Event called by the physics plugin to tell the avatar about a collision. 4157 /// Event called by the physics plugin to tell the avatar about a collision.
3238 /// </summary> 4158 /// </summary>
@@ -3246,7 +4166,7 @@ namespace OpenSim.Region.Framework.Scenes
3246 /// <param name="e"></param> 4166 /// <param name="e"></param>
3247 public void PhysicsCollisionUpdate(EventArgs e) 4167 public void PhysicsCollisionUpdate(EventArgs e)
3248 { 4168 {
3249 if (IsChildAgent) 4169 if (IsChildAgent || Animator == null)
3250 return; 4170 return;
3251 4171
3252 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 4172 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
@@ -3255,14 +4175,14 @@ namespace OpenSim.Region.Framework.Scenes
3255 4175
3256// if (m_updateCount > 0) 4176// if (m_updateCount > 0)
3257// { 4177// {
3258 Animator.UpdateMovementAnimations(); 4178 if (Animator.UpdateMovementAnimations())
4179 TriggerScenePresenceUpdated();
3259// m_updateCount--; 4180// m_updateCount--;
3260// } 4181// }
3261 4182
3262 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 4183 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3263 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 4184 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3264 4185
3265 CollisionPlane = Vector4.UnitW;
3266 4186
3267// // No collisions at all means we may be flying. Update always 4187// // No collisions at all means we may be flying. Update always
3268// // to make falling work 4188// // to make falling work
@@ -3272,34 +4192,7 @@ namespace OpenSim.Region.Framework.Scenes
3272// m_lastColCount = coldata.Count; 4192// m_lastColCount = coldata.Count;
3273// } 4193// }
3274 4194
3275 if (coldata.Count != 0) 4195 CollisionPlane = Vector4.UnitW;
3276 {
3277 switch (Animator.CurrentMovementAnimation)
3278 {
3279 case "STAND":
3280 case "WALK":
3281 case "RUN":
3282 case "CROUCH":
3283 case "CROUCHWALK":
3284 {
3285 ContactPoint lowest;
3286 lowest.SurfaceNormal = Vector3.Zero;
3287 lowest.Position = Vector3.Zero;
3288 lowest.Position.Z = Single.NaN;
3289
3290 foreach (ContactPoint contact in coldata.Values)
3291 {
3292 if (Single.IsNaN(lowest.Position.Z) || contact.Position.Z < lowest.Position.Z)
3293 {
3294 lowest = contact;
3295 }
3296 }
3297
3298 CollisionPlane = new Vector4(-lowest.SurfaceNormal, -Vector3.Dot(lowest.Position, lowest.SurfaceNormal));
3299 }
3300 break;
3301 }
3302 }
3303 4196
3304 // Gods do not take damage and Invulnerable is set depending on parcel/region flags 4197 // Gods do not take damage and Invulnerable is set depending on parcel/region flags
3305 if (Invulnerable || GodLevel > 0) 4198 if (Invulnerable || GodLevel > 0)
@@ -3398,6 +4291,14 @@ namespace OpenSim.Region.Framework.Scenes
3398 // m_reprioritizationTimer.Dispose(); 4291 // m_reprioritizationTimer.Dispose();
3399 4292
3400 RemoveFromPhysicalScene(); 4293 RemoveFromPhysicalScene();
4294
4295 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
4296
4297// if (Animator != null)
4298// Animator.Close();
4299 Animator = null;
4300
4301 LifecycleState = ScenePresenceState.Removed;
3401 } 4302 }
3402 4303
3403 public void AddAttachment(SceneObjectGroup gobj) 4304 public void AddAttachment(SceneObjectGroup gobj)
@@ -3602,7 +4503,7 @@ namespace OpenSim.Region.Framework.Scenes
3602 } 4503 }
3603 } 4504 }
3604 } 4505 }
3605 }); 4506 }, null, "ScenePresence.SendScriptEventToAttachments");
3606 } 4507 }
3607 4508
3608 /// <summary> 4509 /// <summary>
@@ -3631,10 +4532,18 @@ namespace OpenSim.Region.Framework.Scenes
3631 4532
3632 public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID) 4533 public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID)
3633 { 4534 {
4535 SceneObjectPart p = m_scene.GetSceneObjectPart(Obj_localID);
4536 if (p == null)
4537 return;
4538
4539 ControllingClient.SendTakeControls(controls, false, false);
4540 ControllingClient.SendTakeControls(controls, true, false);
4541
3634 ScriptControllers obj = new ScriptControllers(); 4542 ScriptControllers obj = new ScriptControllers();
3635 obj.ignoreControls = ScriptControlled.CONTROL_ZERO; 4543 obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
3636 obj.eventControls = ScriptControlled.CONTROL_ZERO; 4544 obj.eventControls = ScriptControlled.CONTROL_ZERO;
3637 4545
4546 obj.objectID = p.ParentGroup.UUID;
3638 obj.itemID = Script_item_UUID; 4547 obj.itemID = Script_item_UUID;
3639 if (pass_on == 0 && accept == 0) 4548 if (pass_on == 0 && accept == 0)
3640 { 4549 {
@@ -3683,6 +4592,21 @@ namespace OpenSim.Region.Framework.Scenes
3683 ControllingClient.SendTakeControls(int.MaxValue, false, false); 4592 ControllingClient.SendTakeControls(int.MaxValue, false, false);
3684 } 4593 }
3685 4594
4595 private void UnRegisterSeatControls(UUID obj)
4596 {
4597 List<UUID> takers = new List<UUID>();
4598
4599 foreach (ScriptControllers c in scriptedcontrols.Values)
4600 {
4601 if (c.objectID == obj)
4602 takers.Add(c.itemID);
4603 }
4604 foreach (UUID t in takers)
4605 {
4606 UnRegisterControlEventsToScript(0, t);
4607 }
4608 }
4609
3686 public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) 4610 public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID)
3687 { 4611 {
3688 ScriptControllers takecontrols; 4612 ScriptControllers takecontrols;
@@ -3899,6 +4823,7 @@ namespace OpenSim.Region.Framework.Scenes
3899 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || 4823 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 ||
3900 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0) 4824 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)
3901 { 4825 {
4826
3902 if (GodLevel < 200 && 4827 if (GodLevel < 200 &&
3903 ((!m_scene.Permissions.IsGod(m_uuid) && 4828 ((!m_scene.Permissions.IsGod(m_uuid) &&
3904 !m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) || 4829 !m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) ||
@@ -3907,7 +4832,14 @@ namespace OpenSim.Region.Framework.Scenes
3907 { 4832 {
3908 SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray(); 4833 SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray();
3909 if (spawnPoints.Length == 0) 4834 if (spawnPoints.Length == 0)
4835 {
4836 if(m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid))
4837 {
4838 pos.X = 128.0f;
4839 pos.Y = 128.0f;
4840 }
3910 return; 4841 return;
4842 }
3911 4843
3912 int index; 4844 int index;
3913 bool selected = false; 4845 bool selected = false;
@@ -3916,6 +4848,8 @@ namespace OpenSim.Region.Framework.Scenes
3916 { 4848 {
3917 case "random": 4849 case "random":
3918 4850
4851 if (spawnPoints.Length == 0)
4852 return;
3919 do 4853 do
3920 { 4854 {
3921 index = Util.RandomClass.Next(spawnPoints.Length - 1); 4855 index = Util.RandomClass.Next(spawnPoints.Length - 1);
@@ -3927,6 +4861,7 @@ namespace OpenSim.Region.Framework.Scenes
3927 // SpawnPoint sp = spawnPoints[index]; 4861 // SpawnPoint sp = spawnPoints[index];
3928 4862
3929 ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y); 4863 ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y);
4864
3930 if (land == null || land.IsEitherBannedOrRestricted(UUID)) 4865 if (land == null || land.IsEitherBannedOrRestricted(UUID))
3931 selected = false; 4866 selected = false;
3932 else 4867 else
@@ -3999,8 +4934,15 @@ namespace OpenSim.Region.Framework.Scenes
3999 } 4934 }
4000 } 4935 }
4001 4936
4937 // Modify landing point based on possible banning, telehubs or parcel restrictions.
4002 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 4938 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
4003 { 4939 {
4940 string reason;
4941
4942 // Honor bans
4943 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
4944 return;
4945
4004 SceneObjectGroup telehub = null; 4946 SceneObjectGroup telehub = null;
4005 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 4947 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
4006 { 4948 {
@@ -4040,11 +4982,119 @@ namespace OpenSim.Region.Framework.Scenes
4040 pos = land.LandData.UserLocation; 4982 pos = land.LandData.UserLocation;
4041 } 4983 }
4042 } 4984 }
4043 4985
4044 land.SendLandUpdateToClient(ControllingClient); 4986 land.SendLandUpdateToClient(ControllingClient);
4045 } 4987 }
4046 } 4988 }
4047 4989
4990 private DetectedObject CreateDetObject(SceneObjectPart obj)
4991 {
4992 DetectedObject detobj = new DetectedObject();
4993 detobj.keyUUID = obj.UUID;
4994 detobj.nameStr = obj.Name;
4995 detobj.ownerUUID = obj.OwnerID;
4996 detobj.posVector = obj.AbsolutePosition;
4997 detobj.rotQuat = obj.GetWorldRotation();
4998 detobj.velVector = obj.Velocity;
4999 detobj.colliderType = 0;
5000 detobj.groupUUID = obj.GroupID;
5001
5002 return detobj;
5003 }
5004
5005 private DetectedObject CreateDetObject(ScenePresence av)
5006 {
5007 DetectedObject detobj = new DetectedObject();
5008 detobj.keyUUID = av.UUID;
5009 detobj.nameStr = av.ControllingClient.Name;
5010 detobj.ownerUUID = av.UUID;
5011 detobj.posVector = av.AbsolutePosition;
5012 detobj.rotQuat = av.Rotation;
5013 detobj.velVector = av.Velocity;
5014 detobj.colliderType = 0;
5015 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
5016
5017 return detobj;
5018 }
5019
5020 private DetectedObject CreateDetObjectForGround()
5021 {
5022 DetectedObject detobj = new DetectedObject();
5023 detobj.keyUUID = UUID.Zero;
5024 detobj.nameStr = "";
5025 detobj.ownerUUID = UUID.Zero;
5026 detobj.posVector = AbsolutePosition;
5027 detobj.rotQuat = Quaternion.Identity;
5028 detobj.velVector = Vector3.Zero;
5029 detobj.colliderType = 0;
5030 detobj.groupUUID = UUID.Zero;
5031
5032 return detobj;
5033 }
5034
5035 private ColliderArgs CreateColliderArgs(SceneObjectPart dest, List<uint> colliders)
5036 {
5037 ColliderArgs colliderArgs = new ColliderArgs();
5038 List<DetectedObject> colliding = new List<DetectedObject>();
5039 foreach (uint localId in colliders)
5040 {
5041 if (localId == 0)
5042 continue;
5043
5044 SceneObjectPart obj = m_scene.GetSceneObjectPart(localId);
5045 if (obj != null)
5046 {
5047 if (!dest.CollisionFilteredOut(obj.UUID, obj.Name))
5048 colliding.Add(CreateDetObject(obj));
5049 }
5050 else
5051 {
5052 ScenePresence av = m_scene.GetScenePresence(localId);
5053 if (av != null && (!av.IsChildAgent))
5054 {
5055 if (!dest.CollisionFilteredOut(av.UUID, av.Name))
5056 colliding.Add(CreateDetObject(av));
5057 }
5058 }
5059 }
5060
5061 colliderArgs.Colliders = colliding;
5062
5063 return colliderArgs;
5064 }
5065
5066 private delegate void ScriptCollidingNotification(uint localID, ColliderArgs message);
5067
5068 private void SendCollisionEvent(SceneObjectGroup dest, scriptEvents ev, List<uint> colliders, ScriptCollidingNotification notify)
5069 {
5070 ColliderArgs CollidingMessage;
5071
5072 if (colliders.Count > 0)
5073 {
5074 if ((dest.RootPart.ScriptEvents & ev) != 0)
5075 {
5076 CollidingMessage = CreateColliderArgs(dest.RootPart, colliders);
5077
5078 if (CollidingMessage.Colliders.Count > 0)
5079 notify(dest.RootPart.LocalId, CollidingMessage);
5080 }
5081 }
5082 }
5083
5084 private void SendLandCollisionEvent(SceneObjectGroup dest, scriptEvents ev, ScriptCollidingNotification notify)
5085 {
5086 if ((dest.RootPart.ScriptEvents & ev) != 0)
5087 {
5088 ColliderArgs LandCollidingMessage = new ColliderArgs();
5089 List<DetectedObject> colliding = new List<DetectedObject>();
5090
5091 colliding.Add(CreateDetObjectForGround());
5092 LandCollidingMessage.Colliders = colliding;
5093
5094 notify(dest.RootPart.LocalId, LandCollidingMessage);
5095 }
5096 }
5097
4048 private void TeleportFlagsDebug() { 5098 private void TeleportFlagsDebug() {
4049 5099
4050 // Some temporary debugging help to show all the TeleportFlags we have... 5100 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -4069,6 +5119,5 @@ namespace OpenSim.Region.Framework.Scenes
4069 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 5119 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
4070 5120
4071 } 5121 }
4072
4073 } 5122 }
4074} 5123}