OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
ScenePresence.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Xml;
30 using System.Collections.Generic;
31 using System.Reflection;
32 using System.Threading;
33 using System.Timers;
35 using OpenMetaverse;
36 using log4net;
37 using Nini.Config;
38 using OpenSim.Framework;
39 using OpenSim.Framework.Client;
40 using OpenSim.Framework.Monitoring;
41 using OpenSim.Region.Framework.Interfaces;
43 using OpenSim.Region.Framework.Scenes.Types;
44 using OpenSim.Region.PhysicsModules.SharedBase;
46 using OpenSim.Services.Interfaces;
48 
49 namespace OpenSim.Region.Framework.Scenes
50 {
51  [Flags]
52  enum ScriptControlled : uint
53  {
54  CONTROL_ZERO = 0,
55  CONTROL_FWD = 1,
56  CONTROL_BACK = 2,
57  CONTROL_LEFT = 4,
58  CONTROL_RIGHT = 8,
59  CONTROL_UP = 16,
60  CONTROL_DOWN = 32,
61  CONTROL_ROT_LEFT = 256,
62  CONTROL_ROT_RIGHT = 512,
63  CONTROL_LBUTTON = 268435456,
64  CONTROL_ML_LBUTTON = 1073741824
65  }
66 
68  {
69  public UUID objectID;
70  public UUID itemID;
73  }
74 
75  public delegate void SendCoarseLocationsMethod(UUID scene, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs);
76 
78  {
79  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
80  private static readonly String LogHeader = "[SCENE PRESENCE]";
81 
82 // ~ScenePresence()
83 // {
84 // m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
85 // }
86 
88  {
89  if (m_scene != null)
90  m_scene.EventManager.TriggerScenePresenceUpdated(this);
91  }
92 
93  public bool isNPC { get; private set; }
94 
95  private PresenceType m_presenceType;
97  get {return m_presenceType;}
98  private set
99  {
100  m_presenceType = value;
101  isNPC = (m_presenceType == PresenceType.Npc);
102  }
103  }
104 
105  private ScenePresenceStateMachine m_stateMachine;
106 
111  public ScenePresenceState LifecycleState
112  {
113  get
114  {
115  return m_stateMachine.GetState();
116  }
117 
118  set
119  {
120  m_stateMachine.SetState(value);
121  }
122  }
123 
132  private object m_completeMovementLock = new object();
133 
134 // private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
135  private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
136  private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
137 
146  public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f);
147  public bool LegacySitOffsets = true;
148 
155  public static readonly float MOVEMENT = .25f;
156  public static readonly float SIGNIFICANT_MOVEMENT = 16.0f;
157  public static readonly float CHILDUPDATES_MOVEMENT = 100.0f;
158  public static readonly float CHILDUPDATES_TIME = 10000f; // min time between child updates (ms)
159 
160  private UUID m_previusParcelUUID = UUID.Zero;
161  private UUID m_currentParcelUUID = UUID.Zero;
162  private bool m_previusParcelHide = false;
163  private bool m_currentParcelHide = false;
164  private object parcelLock = new Object();
165 
166  public UUID currentParcelUUID
167  {
168  get { return m_currentParcelUUID; }
169  set
170  {
171  lock (parcelLock)
172  {
173  bool oldhide = m_currentParcelHide;
174  bool checksame = true;
175  if (value != m_currentParcelUUID)
176  {
177  m_previusParcelHide = m_currentParcelHide;
178  m_previusParcelUUID = m_currentParcelUUID;
179  checksame = false;
180  }
181  m_currentParcelUUID = value;
182  m_currentParcelHide = false;
183 
184  ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
185  if (land != null && !land.LandData.SeeAVs)
186  m_currentParcelHide = true;
187 
188  if (m_previusParcelUUID != UUID.Zero || checksame)
189  ParcelCrossCheck(m_currentParcelUUID,m_previusParcelUUID,m_currentParcelHide, m_previusParcelHide, oldhide,checksame);
190  }
191  }
192  }
193 
194  public void sitSOGmoved()
195  {
196 /*
197  if (IsDeleted || !IsSatOnObject)
198  //what me? nahh
199  return;
200  if (IsInTransit)
201  return;
202 
203  ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
204  if (land == null)
205  return; //??
206  UUID parcelID = land.LandData.GlobalID;
207  if (m_currentParcelUUID != parcelID)
208  currentParcelUUID = parcelID;
209 */
210  }
211 
212  public bool ParcelAllowThisAvatarSounds
213  {
214  get
215  {
216  try
217  {
218  lock (parcelLock)
219  {
220  ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
221  if (land == null)
222  return true;
223  if (land.LandData.AnyAVSounds)
224  return true;
225  if (!land.LandData.GroupAVSounds)
226  return false;
227  return land.LandData.GroupID == ControllingClient.ActiveGroupId;
228  }
229  }
230  catch
231  {
232  return true;
233  }
234  }
235  }
236 
237  public bool ParcelHideThisAvatar
238  {
239  get
240  {
241  return m_currentParcelHide;
242  }
243  }
244 
248  public ScenePresenceAnimator Animator { get; private set; }
249 
253  public MovementAnimationOverrides Overrides { get; private set; }
254  public String sitAnimation = "SIT";
262  private List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
263 
264  public Object AttachmentsSyncLock { get; private set; }
265 
266  private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
267  private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
268  private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
269  private bool MouseDown = false;
270 // private SceneObjectGroup proxyObjectGroup;
271  //private SceneObjectPart proxyObjectPart = null;
272  public Vector3 lastKnownAllowedPosition;
274  public Vector4 CollisionPlane = Vector4.UnitW;
275 
276  private Vector3 m_lastPosition;
277  private Quaternion m_lastRotation;
278  private Vector3 m_lastVelocity;
279  private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f);
280 
281  private bool m_followCamAuto = false;
282 
283  private Vector3? m_forceToApply;
284  private int m_userFlags;
285  public int UserFlags
286  {
287  get { return m_userFlags; }
288  }
289 
290  // Flying
291  public bool Flying
292  {
293  get { return PhysicsActor != null && PhysicsActor.Flying; }
294  set { PhysicsActor.Flying = value; }
295  }
296 
297  public bool IsColliding
298  {
299  get { return PhysicsActor != null && PhysicsActor.IsColliding; }
300  // We would expect setting IsColliding to be private but it's used by a hack in Scene
301  set { PhysicsActor.IsColliding = value; }
302  }
303 
304 // private int m_lastColCount = -1; //KF: Look for Collision chnages
305 // private int m_updateCount = 0; //KF: Update Anims for a while
306 // private static readonly int UPDATE_COUNT = 10; // how many frames to update for
307  private List<uint> m_lastColliders = new List<uint>();
308 
309  private TeleportFlags m_teleportFlags;
311  {
312  get { return m_teleportFlags; }
313  set { m_teleportFlags = value; }
314  }
315 
316  private uint m_requestedSitTargetID;
317  private UUID m_requestedSitTargetUUID;
318 
322  public bool SitGround { get; private set; }
323 
324  private SendCoarseLocationsMethod m_sendCoarseLocationsMethod;
325 
326  //private Vector3 m_requestedSitOffset = new Vector3();
327 
328  private Vector3 m_LastFinitePos;
329 
330  private float m_sitAvatarHeight = 2.0f;
331 
332  private bool childUpdatesBusy = false;
333  private int lastChildUpdatesTime;
334  private Vector3 m_lastChildAgentUpdatePosition;
335 // private Vector3 m_lastChildAgentUpdateCamPosition;
336 
337  private const int LAND_VELOCITYMAG_MAX = 12;
338 
339  private const float FLY_ROLL_MAX_RADIANS = 1.1f;
340 
341  private const float FLY_ROLL_RADIANS_PER_UPDATE = 0.06f;
342  private const float FLY_ROLL_RESET_RADIANS_PER_UPDATE = 0.02f;
343 
344  private float m_health = 100f;
345 
346  protected ulong crossingFromRegion;
347 
348  private readonly Vector3[] Dir_Vectors = new Vector3[12];
349 
351  protected bool m_reprioritizationBusy;
353 
354  private Quaternion m_headrotation = Quaternion.Identity;
355 
356  //PauPaw:Proper PID Controler for autopilot************
357  public bool MovingToTarget { get; private set; }
358  public Vector3 MoveToPositionTarget { get; private set; }
359 
363  public bool LandAtTarget { get; private set; }
364 
365  private int m_movementUpdateCount;
366  private const int NumMovementsBetweenRayCast = 5;
367 
368  private bool CameraConstraintActive;
369  //private int m_moveToPositionStateStatus;
370  //*****************************************************
371 
372  //private bool m_collisionEventFlag = false;
373  private object m_collisionEventLock = new Object();
374 
375  private int m_movementAnimationUpdateCounter = 0;
376 
377  public Vector3 PrevSitOffset { get; set; }
378 
380 
381  public AvatarAppearance Appearance
382  {
383  get { return m_appearance; }
384  set
385  {
386  m_appearance = value;
387 // m_log.DebugFormat("[SCENE PRESENCE]: Set appearance for {0} to {1}", Name, value);
388  }
389  }
390 
391 
396  public List<string> InTransitScriptStates
397  {
398  get { return m_InTransitScriptStates; }
399  private set { m_InTransitScriptStates = value; }
400  }
401  private List<string> m_InTransitScriptStates = new List<string>();
402 
406  private enum Dir_ControlFlags:uint
407  {
408  DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
409  DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
410  DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
411  DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
412  DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
413  DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
414  DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
415  DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
416  DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
417  DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
418  DIR_CONTROL_FLAG_UP_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS,
419  DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
420  }
421 
425  private Vector3 posLastSignificantMove;
426  private Vector3 posLastMove;
427 
428  #region For teleports and crossings callbacks
429 
433  private string m_callbackURI;
434 
442  private UUID m_originRegionID;
443 
449  private object m_originRegionIDAccessLock = new object();
450 
456  public bool DoNotCloseAfterTeleport { get; set; }
457 
458  #endregion
459 
463  private IScriptModule[] m_scriptEngines;
464 
465  #region Properties
466 
470  public PhysicsActor PhysicsActor { get; private set; }
471 
475  public uint MovementFlag { get; private set; }
476 
480  public bool AgentControlStopActive { get; private set; }
481 
482  private bool m_invulnerable = true;
483 
484  public bool Invulnerable
485  {
486  set { m_invulnerable = value; }
487  get { return m_invulnerable; }
488  }
489 
490  private int m_userLevel;
491 
492  public int UserLevel
493  {
494  get { return m_userLevel; }
495  private set { m_userLevel = value; }
496  }
497 
498  private int m_godLevel;
499 
500  public int GodLevel
501  {
502  get { return m_godLevel; }
503  private set { m_godLevel = value; }
504  }
505 
506  private ulong m_rootRegionHandle;
507  private Vector3 m_rootRegionPosition = new Vector3();
508 
509  public ulong RegionHandle
510  {
511  get { return m_rootRegionHandle; }
512  private set
513  {
514  m_rootRegionHandle = value;
515  // position rounded to lower multiple of 256m
516  m_rootRegionPosition.X = (float)((m_rootRegionHandle >> 32) & 0xffffff00);
517  m_rootRegionPosition.Y = (float)(m_rootRegionHandle & 0xffffff00);
518  }
519  }
520 
521  #region Client Camera
522 
526 // protected Vector3 m_lastCameraPosition;
527 
528  private Vector4 m_lastCameraCollisionPlane = new Vector4(0f, 0f, 0f, 1);
529  private bool m_doingCamRayCast = false;
530 
531  public Vector3 CameraPosition { get; set; }
532 
533  public Quaternion CameraRotation
534  {
535  get { return Util.Axes2Rot(CameraAtAxis, CameraLeftAxis, CameraUpAxis); }
536  }
537 
538  // Use these three vectors to figure out what the agent is looking at
539  // Convert it to a Matrix and/or Quaternion
540  //
541  public Vector3 CameraAtAxis { get; set; }
542  public Vector3 CameraLeftAxis { get; set; }
543  public Vector3 CameraUpAxis { get; set; }
544 
545  public Vector3 Lookat
546  {
547  get
548  {
549  Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0);
550  a.Normalize();
551  return a;
552  }
553  }
554  #endregion
555 
556  public string Firstname { get; private set; }
557  public string Lastname { get; private set; }
558 
559  public string Grouptitle
560  {
561  get { return UseFakeGroupTitle ? "(Loading)" : m_groupTitle; }
562  set { m_groupTitle = value; }
563  }
564  private string m_groupTitle;
565 
570  public bool UseFakeGroupTitle { get; set; }
571 
572  // Agent's Draw distance.
573  private float m_drawDistance = 255f;
574  public float DrawDistance
575  {
576  get
577  {
578  return m_drawDistance;
579  }
580  set
581  {
582  m_drawDistance = Util.Clamp(value, 32f, m_scene.MaxDrawDistance);
583  }
584  }
585 
586  public float RegionViewDistance
587  {
588  get
589  {
590  return Util.Clamp(m_drawDistance, 32f, m_scene.MaxRegionViewDistance);
591  }
592  }
593 
594  public bool AllowMovement { get; set; }
595 
596  private bool m_setAlwaysRun;
597 
598  public bool SetAlwaysRun
599  {
600  get
601  {
602  if (PhysicsActor != null)
603  {
605  }
606  else
607  {
608  return m_setAlwaysRun;
609  }
610  }
611  set
612  {
613  m_setAlwaysRun = value;
614  if (PhysicsActor != null)
615  {
616  PhysicsActor.SetAlwaysRun = value;
617  }
618  }
619  }
620 
621 
622  public byte State { get; set; }
623 
624  private AgentManager.ControlFlags m_AgentControlFlags;
625 
626  public uint AgentControlFlags
627  {
628  get { return (uint)m_AgentControlFlags; }
629  set { m_AgentControlFlags = (AgentManager.ControlFlags)value; }
630  }
631 
632  public IClientAPI ControllingClient { get; set; }
633 
634  public IClientCore ClientView
635  {
636  get { return (IClientCore)ControllingClient; }
637  }
638 
639  public UUID COF { get; set; }
640 
641 // public Vector3 ParentPosition { get; set; }
642 
646  public override Vector3 AbsolutePosition
647  {
648  get
649  {
650  if (PhysicsActor != null)
651  {
652  m_pos = PhysicsActor.Position;
653 
654 // m_log.DebugFormat(
655 // "[SCENE PRESENCE]: Set position of {0} in {1} to {2} via getting AbsolutePosition!",
656 // Name, Scene.Name, m_pos);
657  }
658  else
659  {
660 // m_log.DebugFormat("[SCENE PRESENCE]: Fetching abs pos where PhysicsActor == null and parent part {0} for {1}", Name, Scene.Name);
661  // Obtain the correct position of a seated avatar.
662  // In addition to providing the correct position while
663  // the avatar is seated, this value will also
664  // be used as the location to unsit to.
665  //
666  // If ParentID is not 0, assume we are a seated avatar
667  // and we should return the position based on the sittarget
668  // offset and rotation of the prim we are seated on.
669  //
670  // Generally, m_pos will contain the position of the avatar
671  // in the sim unless the avatar is on a sit target. While
672  // on a sit target, m_pos will contain the desired offset
673  // without the parent rotation applied.
674  if (ParentPart != null)
675  {
676  SceneObjectPart rootPart = ParentPart.ParentGroup.RootPart;
677  // if (sitPart != null)
678  // return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation());
679  if (rootPart != null)
680  return rootPart.AbsolutePosition + (m_pos * rootPart.GetWorldRotation());
681  }
682  }
683 
684  return m_pos;
685  }
686  set
687  {
688 // m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} to {1} in {2}", Name, value, Scene.Name);
689 // Util.PrintCallStack();
690 
691  if (PhysicsActor != null)
692  {
693  try
694  {
695  PhysicsActor.Position = value;
696  }
697  catch (Exception e)
698  {
699  m_log.Error("[SCENE PRESENCE]: ABSOLUTE POSITION " + e.Message);
700  }
701  }
702 
703  // Don't update while sitting. The PhysicsActor above is null whilst sitting.
704  if (ParentID == 0)
705  m_pos = value;
706 
707  //m_log.DebugFormat(
708  // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}",
709  // Scene.RegionInfo.RegionName, Name, m_pos);
710  TriggerScenePresenceUpdated();
711  }
712  }
713 
718  public Vector3 OffsetPosition
719  {
720  get { return m_pos; }
721  // Don't remove setter. It's not currently used in core but
722  // upcoming Avination code needs it.
723  set
724  {
725  // There is no offset position when not seated
726  if (ParentID == 0)
727  return;
728 
729  m_pos = value;
730  TriggerScenePresenceUpdated();
731  }
732  }
733 
737  public override Vector3 Velocity
738  {
739  get
740  {
741  if (PhysicsActor != null)
742  {
743  m_velocity = PhysicsActor.Velocity;
744 
745 // m_log.DebugFormat(
746 // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!",
747 // m_velocity, Name, Scene.RegionInfo.RegionName);
748  }
749 
750  return m_velocity;
751  }
752 
753  set
754  {
755  if (PhysicsActor != null)
756  {
757  try
758  {
759  PhysicsActor.TargetVelocity = value;
760  }
761  catch (Exception e)
762  {
763  m_log.Error("[SCENE PRESENCE]: VELOCITY " + e.Message);
764  }
765  }
766 
767  m_velocity = value;
768 
769 // m_log.DebugFormat(
770 // "[SCENE PRESENCE]: In {0} set velocity of {1} to {2}",
771 // Scene.RegionInfo.RegionName, Name, m_velocity);
772  }
773  }
774 
775  private Quaternion m_bodyRot = Quaternion.Identity;
776 
785  public Quaternion Rotation
786  {
787  get
788  {
789  return m_bodyRot;
790  }
791 
792  set
793  {
794  m_bodyRot = value;
795 
796  if (PhysicsActor != null)
797  {
798  try
799  {
800  PhysicsActor.Orientation = m_bodyRot;
801  }
802  catch (Exception e)
803  {
804  m_log.Error("[SCENE PRESENCE]: Orientation " + e.Message);
805  }
806  }
807 // m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot);
808  }
809  }
810 
811  // Used for limited viewer 'fake' user rotations.
812  private Vector3 m_AngularVelocity = Vector3.Zero;
813 
814  public Vector3 AngularVelocity
815  {
816  get { return m_AngularVelocity; }
817  }
818 
819  public bool IsChildAgent { get; set; }
820  public bool IsLoggingIn { get; set; }
821 
825  public uint ParentID { get; set; }
826 
827  public UUID ParentUUID
828  {
829  get { return m_parentUUID; }
830  set { m_parentUUID = value; }
831  }
832  private UUID m_parentUUID = UUID.Zero;
833 
838  public bool IsSatOnObject { get { return ParentID != 0; } }
839 
846  public SceneObjectPart ParentPart { get; set; }
847 
848  public float Health
849  {
850  get { return m_health; }
851  set { m_health = value; }
852  }
853 
861  public Quaternion GetWorldRotation()
862  {
863  if (IsSatOnObject)
864  {
865  SceneObjectPart sitPart = ParentPart;
866 
867  if (sitPart != null)
868  return sitPart.GetWorldRotation() * Rotation;
869  }
870 
871  return Rotation;
872  }
873 
877  public Vector3 GetWorldVelocity()
878  {
879  SceneObjectPart sitPart = ParentPart;
880 
881  if (sitPart != null)
882  return sitPart.ParentGroup.Velocity;
883 
884  return Velocity;
885  }
886 
887  public void AdjustKnownSeeds()
888  {
889  Dictionary<ulong, string> seeds;
890 
891  if (Scene.CapsModule != null)
892  seeds = Scene.CapsModule.GetChildrenSeeds(UUID);
893  else
894  seeds = new Dictionary<ulong, string>();
895 
896 /* we can't do this anymore
897  List<ulong> old = new List<ulong>();
898  foreach (ulong handle in seeds.Keys)
899  {
900  uint x, y;
901  Util.RegionHandleToRegionLoc(handle, out x, out y);
902 // if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY,))
903  {
904  old.Add(handle);
905  }
906  }
907 
908  DropOldNeighbours(old);
909 
910  if (Scene.CapsModule != null)
911  Scene.CapsModule.SetChildrenSeed(UUID, seeds);
912 */
913  KnownRegions = seeds;
914  //m_log.Debug(" ++++++++++AFTER+++++++++++++ ");
915  //DumpKnownRegions();
916  }
917 
918  public void DumpKnownRegions()
919  {
920  m_log.Info("================ KnownRegions "+Scene.RegionInfo.RegionName+" ================");
921  foreach (KeyValuePair<ulong, string> kvp in KnownRegions)
922  {
923  uint x, y;
924  Util.RegionHandleToRegionLoc(kvp.Key, out x, out y);
925  m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
926  }
927  }
928 
929  private bool m_mouseLook;
930  private bool m_leftButtonDown;
931 
932  private bool m_inTransit;
933 
940  public bool IsInTransit
941  {
942  get { return m_inTransit; }
943  set {
944  if(value)
945  {
946  if (Flying)
947  m_AgentControlFlags |= AgentManager.ControlFlags.AGENT_CONTROL_FLY;
948  else
949  m_AgentControlFlags &= ~AgentManager.ControlFlags.AGENT_CONTROL_FLY;
950  }
951  m_inTransit = value;
952  }
953  }
954 
955 
962  private const float AgentControlStopSlowVel = 0.2f;
963  // velocities
964  public const float AgentControlNudgeVel = 1.0f; // setting this diferent from normal as no effect currently
965  public const float AgentControlNormalVel = 1.0f;
966 
967  // old normal speed was tuned to match sl normal plus Fast modifiers
968  // so we need to rescale it
969  private float m_speedModifier = 1.0f;
970 
971  public float SpeedModifier
972  {
973  get { return m_speedModifier; }
974  set { m_speedModifier = value; }
975  }
976 
977  private bool m_forceFly;
978 
979  public bool ForceFly
980  {
981  get { return m_forceFly; }
982  set { m_forceFly = value; }
983  }
984 
985  private bool m_flyDisabled;
986 
987  public bool FlyDisabled
988  {
989  get { return m_flyDisabled; }
990  set { m_flyDisabled = value; }
991  }
992 
993  public string Viewer
994  {
995  get { return Util.GetViewerName(m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode)); }
996  }
997 
998  #endregion
999 
1000  #region Constructor(s)
1001 
1003  IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
1004  {
1005  m_scene = world;
1006  AttachmentsSyncLock = new Object();
1007  AllowMovement = true;
1008  IsChildAgent = true;
1009  IsLoggingIn = false;
1010  m_sendCoarseLocationsMethod = SendCoarseLocationsDefault;
1011  Animator = new ScenePresenceAnimator(this);
1012  Overrides = new MovementAnimationOverrides();
1013  PresenceType = type;
1014  DrawDistance = world.DefaultDrawDistance;
1015  RegionHandle = world.RegionInfo.RegionHandle;
1016  ControllingClient = client;
1017  Firstname = ControllingClient.FirstName;
1018  Lastname = ControllingClient.LastName;
1019  m_name = String.Format("{0} {1}", Firstname, Lastname);
1020  m_uuid = client.AgentId;
1021  LocalId = m_scene.AllocateLocalId();
1022  LegacySitOffsets = m_scene.LegacySitOffsets;
1023 
1024  UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
1025  if (account != null)
1026  m_userFlags = account.UserFlags;
1027  else
1028  m_userFlags = 0;
1029 
1030  if (account != null)
1031  UserLevel = account.UserLevel;
1032 
1033  IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
1034  if (gm != null)
1035  Grouptitle = gm.GetGroupTitle(m_uuid);
1036 
1037  m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>();
1038 
1039  AbsolutePosition = posLastMove = posLastSignificantMove = CameraPosition =
1040  m_reprioritizationLastPosition = ControllingClient.StartPos;
1041 
1042  // disable updates workjobs for now
1043  childUpdatesBusy = true;
1044  m_reprioritizationBusy = true;
1045 
1046  AdjustKnownSeeds();
1047 
1048  RegisterToEvents();
1049  SetDirectionVectors();
1050 
1051  Appearance = appearance;
1052 
1053  m_stateMachine = new ScenePresenceStateMachine(this);
1054  }
1055 
1056  private void RegionHeartbeatEnd(Scene scene)
1057  {
1058  if (IsChildAgent)
1059  return;
1060 
1061  m_movementAnimationUpdateCounter ++;
1062  if (m_movementAnimationUpdateCounter >= 2)
1063  {
1064  m_movementAnimationUpdateCounter = 0;
1065  if (Animator != null)
1066  {
1067  // If the parentID == 0 we are not sitting
1068  // if !SitGournd then we are not sitting on the ground
1069  // Fairly straightforward, now here comes the twist
1070  // if ParentUUID is NOT UUID.Zero, we are looking to
1071  // be sat on an object that isn't there yet. Should
1072  // be treated as if sat.
1073  if(ParentID == 0 && !SitGround && ParentUUID == UUID.Zero) // skip it if sitting
1074  Animator.UpdateMovementAnimations();
1075  }
1076  else
1077  {
1078  m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1079  }
1080  }
1081  }
1082 
1083  public void RegisterToEvents()
1084  {
1085  ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
1086  ControllingClient.OnAgentUpdate += HandleAgentUpdate;
1087  ControllingClient.OnAgentCameraUpdate += HandleAgentCamerasUpdate;
1088  ControllingClient.OnAgentRequestSit += HandleAgentRequestSit;
1089  ControllingClient.OnAgentSit += HandleAgentSit;
1090  ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
1091  ControllingClient.OnStartAnim += HandleStartAnim;
1092  ControllingClient.OnStopAnim += HandleStopAnim;
1093  ControllingClient.OnChangeAnim += avnHandleChangeAnim;
1094  ControllingClient.OnForceReleaseControls += HandleForceReleaseControls;
1095  ControllingClient.OnAutoPilotGo += MoveToTarget;
1096  ControllingClient.OnUpdateThrottles += RaiseUpdateThrottles;
1097 
1098  // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
1099  // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
1100  }
1101 
1102  private void SetDirectionVectors()
1103  {
1104  Dir_Vectors[0] = new Vector3(AgentControlNormalVel,0,0); //FORWARD
1105  Dir_Vectors[1] = new Vector3(-AgentControlNormalVel,0,0);; //BACK
1106  Dir_Vectors[2] = new Vector3(0,AgentControlNormalVel,0); //LEFT
1107  Dir_Vectors[3] = new Vector3(0,-AgentControlNormalVel,0); //RIGHT
1108  Dir_Vectors[4] = new Vector3(0,0,AgentControlNormalVel); //UP
1109  Dir_Vectors[5] = new Vector3(0,0,-AgentControlNormalVel); //DOWN
1110  Dir_Vectors[6] = new Vector3(AgentControlNudgeVel, 0f, 0f); //FORWARD_NUDGE
1111  Dir_Vectors[7] = new Vector3(-AgentControlNudgeVel, 0f, 0f); //BACK_NUDGE
1112  Dir_Vectors[8] = new Vector3(0f, AgentControlNudgeVel, 0f); //LEFT_NUDGE
1113  Dir_Vectors[9] = new Vector3(0f, -AgentControlNudgeVel, 0f); //RIGHT_NUDGE
1114  Dir_Vectors[10] = new Vector3(0f, 0f, AgentControlNudgeVel); //UP_Nudge
1115  Dir_Vectors[11] = new Vector3(0f, 0f, -AgentControlNudgeVel); //DOWN_Nudge
1116  }
1117  #endregion
1118 
1119  #region Status Methods
1120 
1133 
1134  // constants for physics position search
1135  const float PhysSearchHeight = 600f;
1136  const float PhysMinSkipGap = 50f;
1137  const int PhysNumberCollisions = 30;
1138 
1139  // only in use as part of completemovement
1140  // other uses need fix
1141  private bool MakeRootAgent(Vector3 pos, bool isFlying, ref Vector3 lookat)
1142  {
1143  int ts = Util.EnvironmentTickCount();
1144 
1145  lock (m_completeMovementLock)
1146  {
1147  if (!IsChildAgent)
1148  return false;
1149 
1150  m_log.DebugFormat("[MakeRootAgent] enter lock: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1151  //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1152 
1153  // m_log.InfoFormat(
1154  // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1155  // Name, m_scene.RegionInfo.RegionName);
1156 
1157  if (ParentUUID != UUID.Zero)
1158  {
1159  m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
1160  SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
1161  if (part == null)
1162  {
1163  m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1164  ParentID = 0;
1165  ParentPart = null;
1166  PrevSitOffset = Vector3.Zero;
1167  HandleForceReleaseControls(ControllingClient, UUID); // needs testing
1168  IsLoggingIn = false;
1169  }
1170  else
1171  {
1172  part.AddSittingAvatar(this);
1173  if (part.SitTargetPosition != Vector3.Zero)
1174  part.SitTargetAvatar = UUID;
1175  ParentID = part.LocalId;
1176  ParentPart = part;
1177  m_pos = PrevSitOffset;
1178  pos = part.GetWorldPosition();
1179  }
1180  ParentUUID = UUID.Zero;
1181  }
1182  else
1183  {
1184  IsLoggingIn = false;
1185  }
1186 
1187  IsChildAgent = false;
1188  }
1189 
1190  m_log.DebugFormat("[MakeRootAgent] out lock: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1191 
1192  // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
1193  // set and prevent the close of the connection on a subsequent re-teleport.
1194  // Should not be needed if we are not trying to tell this region to close
1195  // DoNotCloseAfterTeleport = false;
1196 
1197  IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
1198  if (gm != null)
1199  Grouptitle = gm.GetGroupTitle(m_uuid);
1200 
1201  m_log.DebugFormat("[MakeRootAgent] Grouptitle: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1202 
1203  RegionHandle = m_scene.RegionInfo.RegionHandle;
1204 
1205  m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
1206  m_log.DebugFormat("[MakeRootAgent] TriggerSetRootAgentScene: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1207 
1208  if (ParentID == 0)
1209  {
1210  bool positionChanged = false;
1211  if(!CheckAndAdjustLandingPoint(ref pos, ref lookat, ref positionChanged ))
1212  {
1213  m_log.DebugFormat("[SCENE PRESENCE MakeRootAgent]: houston we have a problem.. {0}({1} got here banned",Name, UUID);
1214  }
1215 
1216  if (pos.X < 0f || pos.Y < 0f
1217  || pos.X >= m_scene.RegionInfo.RegionSizeX
1218  || pos.Y >= m_scene.RegionInfo.RegionSizeY)
1219  {
1220  m_log.WarnFormat(
1221  "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
1222  pos, Name, UUID);
1223 
1224  if (pos.X < 0f)
1225  pos.X = 0.5f;
1226  else if(pos.X >= m_scene.RegionInfo.RegionSizeX)
1227  pos.X = m_scene.RegionInfo.RegionSizeX - 0.5f;
1228  if (pos.Y < 0f)
1229  pos.Y = 0.5f;
1230  else if(pos.Y >= m_scene.RegionInfo.RegionSizeY)
1231  pos.Y = m_scene.RegionInfo.RegionSizeY - 0.5f;
1232  }
1233 
1234  float groundHeight = m_scene.GetGroundHeight(pos.X, pos.Y) + .01f;
1235  float physTestHeight;
1236 
1237  if(PhysSearchHeight < groundHeight + 100f)
1238  physTestHeight = groundHeight + 100f;
1239  else
1240  physTestHeight = PhysSearchHeight;
1241 
1242  float localAVHalfHeight = 0.8f;
1243  if (Appearance != null && Appearance.AvatarHeight > 0)
1244  localAVHalfHeight = 0.5f * Appearance.AvatarHeight;
1245 
1246  groundHeight += localAVHalfHeight;
1247  if (groundHeight > pos.Z)
1248  pos.Z = groundHeight;
1249 
1250  bool checkPhysics = !positionChanged &&
1251  m_scene.SupportsRayCastFiltered() &&
1252  pos.Z < physTestHeight &&
1253  ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) ==
1254  (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)
1255  || (m_teleportFlags & TeleportFlags.ViaLocation) != 0
1256  || (m_teleportFlags & TeleportFlags.ViaHGLogin) != 0);
1257 
1258  if(checkPhysics)
1259  {
1260  // land check was done above
1261  RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull;
1262  rayfilter |= RayFilterFlags.PrimsNonPhantomAgents;
1263 
1264  int physcount = PhysNumberCollisions;
1265 
1266  float dist = physTestHeight - groundHeight + localAVHalfHeight;
1267 
1268  Vector3 direction = new Vector3(0f, 0f, -1f);
1269  Vector3 RayStart = pos;
1270  RayStart.Z = physTestHeight;
1271 
1272  List<ContactResult> physresults =
1273  (List<ContactResult>)m_scene.RayCastFiltered(RayStart, direction, dist, physcount, rayfilter);
1274  if (physresults != null && physresults.Count > 0)
1275  {
1276  float dest = physresults[0].Pos.Z;
1277 
1278  if(physresults.Count > 1)
1279  {
1280  physresults.Sort(delegate(ContactResult a, ContactResult b)
1281  {
1282  return a.Depth.CompareTo(b.Depth);
1283  });
1284 
1285  int sel = 0;
1286  int count = physresults.Count;
1287  float curd = physresults[0].Depth;
1288  float nextd = curd + PhysMinSkipGap;
1289  float maxDepth = dist - pos.Z;
1290  for(int i = 1; i < count; i++)
1291  {
1292  curd = physresults[i].Depth;
1293  if(curd >= nextd)
1294  {
1295  sel = i;
1296  if(curd >= maxDepth)
1297  break;
1298  }
1299  nextd = curd + PhysMinSkipGap;
1300  }
1301  dest = physresults[sel].Pos.Z;
1302  }
1303 
1304  dest += localAVHalfHeight;
1305  if(dest > pos.Z)
1306  pos.Z = dest;
1307  }
1308  }
1309 
1310  AbsolutePosition = pos;
1311 
1312 // m_log.DebugFormat(
1313 // "Set pos {0}, vel {1} in {1} to {2} from input position of {3} on MakeRootAgent",
1314 // Name, Scene.Name, AbsolutePosition, pos);
1315 //
1316  if (m_teleportFlags == TeleportFlags.Default)
1317  {
1318  Vector3 vel = Velocity;
1319  AddToPhysicalScene(isFlying);
1320  if (PhysicsActor != null)
1321  PhysicsActor.SetMomentum(vel);
1322  }
1323  else
1324  {
1325  AddToPhysicalScene(isFlying);
1326 
1327  // reset camera to avatar pos
1328  CameraPosition = pos;
1329  }
1330 
1331  if (ForceFly)
1332  {
1333  Flying = true;
1334  }
1335  else if (FlyDisabled)
1336  {
1337  Flying = false;
1338  }
1339  }
1340 
1341 
1342  m_log.DebugFormat("[MakeRootAgent] position and physical: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1343  m_scene.SwapRootAgentCount(false);
1344 
1345  // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will
1346  // stall on the border crossing since the existing child agent will still have the last movement
1347  // recorded, which stops the input from being processed.
1348  MovementFlag = 0;
1349 
1350  m_scene.EventManager.TriggerOnMakeRootAgent(this);
1351  m_log.DebugFormat("[MakeRootAgent] TriggerOnMakeRootAgent and done: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1352 
1353  return true;
1354  }
1355 
1356  private void RestartAttachmentScripts()
1357  {
1358  // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
1359  // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1360  // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1361  // not transporting the required data.
1362  //
1363  // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of
1364  // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here
1365  // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status.
1366  //
1367  // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts().
1368  // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing
1369  // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the
1370  // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
1371  List<SceneObjectGroup> attachments = GetAttachments();
1372 
1373  m_log.DebugFormat(
1374  "[SCENE PRESENCE]: Restarting scripts in {0} attachments for {1} in {2}", attachments.Count, Name, Scene.Name);
1375 
1376  // Resume scripts
1377  foreach (SceneObjectGroup sog in attachments)
1378  {
1379  sog.ScheduleGroupForFullUpdate();
1380  sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1381  sog.ResumeScripts();
1382  }
1383  }
1384 
1385  private static bool IsRealLogin(TeleportFlags teleportFlags)
1386  {
1387  return ((teleportFlags & TeleportFlags.ViaLogin) != 0) && ((teleportFlags & TeleportFlags.ViaHGLogin) == 0);
1388  }
1389 
1400 /*
1401  public void ForceViewersUpdateName()
1402  {
1403  m_log.DebugFormat("[SCENE PRESENCE]: Forcing viewers to update the avatar name for " + Name);
1404 
1405  UseFakeGroupTitle = true;
1406 
1407 
1408  Util.FireAndForget(o =>
1409  {
1410  // Viewers only update the avatar name when idle. Therefore, we must wait long
1411  // enough for the viewer to show the fake name that we had set above, and only
1412  // then switch back to the true name. This delay was chosen because it has a high
1413  // chance of succeeding (we don't want to choose a value that's too low).
1414  Thread.Sleep(5000);
1415 
1416  UseFakeGroupTitle = false;
1417  SendAvatarDataToAllClients(false);
1418  }, null, "Scenepresence.ForceViewersUpdateName");
1419  }
1420 */
1421  public int GetStateSource()
1422  {
1423  AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(UUID);
1424 
1425  if (aCircuit != null && (aCircuit.teleportFlags != (uint)TeleportFlags.Default))
1426  {
1427  // This will get your attention
1428  //m_log.Error("[XXX] Triggering CHANGED_TELEPORT");
1429 
1430  return 5; // StateSource.Teleporting
1431  }
1432  return 2; // StateSource.PrimCrossing
1433  }
1434 
1444  public void MakeChildAgent(ulong newRegionHandle)
1445  {
1446  m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1447 
1448  RegionHandle = newRegionHandle;
1449 
1450  m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1} from root region {2}",
1451  Name, Scene.RegionInfo.RegionName, newRegionHandle);
1452 
1453  // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating
1454  // from the source simulator has completed on a V2 teleport.
1455  lock (m_originRegionIDAccessLock)
1456  m_originRegionID = UUID.Zero;
1457 
1458  // Reset these so that teleporting in and walking out isn't seen
1459  // as teleporting back
1460  TeleportFlags = TeleportFlags.Default;
1461 
1462  MovementFlag = 0;
1463 
1464  // It looks like Animator is set to null somewhere, and MakeChild
1465  // is called after that. Probably in aborted teleports.
1466  if (Animator == null)
1467  Animator = new ScenePresenceAnimator(this);
1468  else
1469  Animator.ResetAnimations();
1470 
1471 
1472 // m_log.DebugFormat(
1473 // "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
1474 // Name, UUID, m_scene.RegionInfo.RegionName);
1475 
1476  // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing,
1477  // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated.
1478  //Velocity = new Vector3(0, 0, 0);
1479 
1480  IsChildAgent = true;
1481  m_scene.SwapRootAgentCount(true);
1482  RemoveFromPhysicalScene();
1483  ParentID = 0; // Child agents can't be sitting
1484 
1485 // we dont have land information for child
1486  m_previusParcelHide = false;
1487  m_previusParcelUUID = UUID.Zero;
1488  m_currentParcelHide = false;
1489  m_currentParcelUUID = UUID.Zero;
1490  // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into
1491 
1492  CollisionPlane = Vector4.UnitW;
1493 
1494  m_scene.EventManager.TriggerOnMakeChildAgent(this);
1495  }
1496 
1501  {
1502  if (PhysicsActor != null)
1503  {
1504 // PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
1505 
1506  PhysicsActor.OnOutOfBounds -= OutOfBoundsCall;
1507  PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1508  PhysicsActor.UnSubscribeEvents();
1509  m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1510  PhysicsActor = null;
1511  }
1512 // else
1513 // {
1514 // m_log.ErrorFormat(
1515 // "[SCENE PRESENCE]: Attempt to remove physics actor for {0} on {1} but this scene presence has no physics actor",
1516 // Name, Scene.RegionInfo.RegionName);
1517 // }
1518  }
1519 
1524  public void Teleport(Vector3 pos)
1525  {
1526  TeleportWithMomentum(pos, Vector3.Zero);
1527  }
1528 
1529  public void TeleportWithMomentum(Vector3 pos, Vector3? v)
1530  {
1531  if(!CheckLocalTPLandingPoint(ref pos))
1532  return;
1533 
1534  if (ParentID != (uint)0)
1535  StandUp();
1536 
1537  bool isFlying = Flying;
1538  Vector3 vel = Velocity;
1539  RemoveFromPhysicalScene();
1540 
1541  AbsolutePosition = pos;
1542  AddToPhysicalScene(isFlying);
1543  if (PhysicsActor != null)
1544  {
1545  if (v.HasValue)
1546  PhysicsActor.SetMomentum((Vector3)v);
1547  else
1548  PhysicsActor.SetMomentum(vel);
1549  }
1550 
1551  SendTerseUpdateToAllClients();
1552  }
1553 
1554  public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY)
1555  {
1556  if(!CheckLocalTPLandingPoint(ref newpos))
1557  return;
1558 
1559  AbsolutePosition = newpos;
1560 
1561  if (newvel.HasValue)
1562  {
1563  if ((Vector3)newvel == Vector3.Zero)
1564  {
1565  if (PhysicsActor != null)
1566  PhysicsActor.SetMomentum(Vector3.Zero);
1567  m_velocity = Vector3.Zero;
1568  }
1569  else
1570  {
1571  if (PhysicsActor != null)
1572  PhysicsActor.SetMomentum((Vector3)newvel);
1573  m_velocity = (Vector3)newvel;
1574 
1575  if (rotateToVelXY)
1576  {
1577  Vector3 lookAt = (Vector3)newvel;
1578  lookAt.Z = 0;
1579  lookAt.Normalize();
1580  ControllingClient.SendLocalTeleport(newpos, lookAt, (uint)TeleportFlags.ViaLocation);
1581  return;
1582  }
1583  }
1584  }
1585  SendTerseUpdateToAllClients();
1586  }
1587 
1588  public void StopFlying()
1589  {
1590  if (IsInTransit)
1591  return;
1592 
1593  Vector3 pos = AbsolutePosition;
1594  if (Appearance.AvatarHeight != 127.0f)
1595  pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f));
1596  else
1597  pos += new Vector3(0f, 0f, (1.56f / 6f));
1598 
1599  AbsolutePosition = pos;
1600 
1601  // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
1602  // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
1603  // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
1604  // certain amount.. because the LLClient wouldn't land in that situation anyway.
1605 
1606  // why are we still testing for this really old height value default???
1607  if (Appearance.AvatarHeight != 127.0f)
1608  CollisionPlane = new Vector4(0, 0, 0, pos.Z - Appearance.AvatarHeight / 6f);
1609  else
1610  CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f));
1611 
1612  SendAgentTerseUpdate(this);
1613  }
1614 
1619  private void ApplyFlyingRoll(float amount, bool PressingUp, bool PressingDown)
1620  {
1621 
1622  float rollAmount = Util.Clamp(m_AngularVelocity.Z + amount, -FLY_ROLL_MAX_RADIANS, FLY_ROLL_MAX_RADIANS);
1623  m_AngularVelocity.Z = rollAmount;
1624 
1625  // APPLY EXTRA consideration for flying up and flying down during this time.
1626  // if we're turning left
1627  if (amount > 0)
1628  {
1629 
1630  // If we're at the max roll and pressing up, we want to swing BACK a bit
1631  // Automatically adds noise
1632  if (PressingUp)
1633  {
1634  if (m_AngularVelocity.Z >= FLY_ROLL_MAX_RADIANS - 0.04f)
1635  m_AngularVelocity.Z -= 0.9f;
1636  }
1637  // If we're at the max roll and pressing down, we want to swing MORE a bit
1638  if (PressingDown)
1639  {
1640  if (m_AngularVelocity.Z >= FLY_ROLL_MAX_RADIANS && m_AngularVelocity.Z < FLY_ROLL_MAX_RADIANS + 0.6f)
1641  m_AngularVelocity.Z += 0.6f;
1642  }
1643  }
1644  else // we're turning right.
1645  {
1646  // If we're at the max roll and pressing up, we want to swing BACK a bit
1647  // Automatically adds noise
1648  if (PressingUp)
1649  {
1650  if (m_AngularVelocity.Z <= (-FLY_ROLL_MAX_RADIANS))
1651  m_AngularVelocity.Z += 0.6f;
1652  }
1653  // If we're at the max roll and pressing down, we want to swing MORE a bit
1654  if (PressingDown)
1655  {
1656  if (m_AngularVelocity.Z >= -FLY_ROLL_MAX_RADIANS - 0.6f)
1657  m_AngularVelocity.Z -= 0.6f;
1658  }
1659  }
1660  }
1661 
1667  private float CalculateFlyingRollResetToZero(float amount)
1668  {
1669  const float rollMinRadians = 0f;
1670 
1671  if (m_AngularVelocity.Z > 0)
1672  {
1673 
1674  float leftOverToMin = m_AngularVelocity.Z - rollMinRadians;
1675  if (amount > leftOverToMin)
1676  return -leftOverToMin;
1677  else
1678  return -amount;
1679 
1680  }
1681  else
1682  {
1683 
1684  float leftOverToMin = -m_AngularVelocity.Z - rollMinRadians;
1685  if (amount > leftOverToMin)
1686  return leftOverToMin;
1687  else
1688  return amount;
1689  }
1690  }
1691 
1692 
1693 
1694  // neighbouring regions we have enabled a child agent in
1695  // holds the seed cap for the child agent in that region
1696  private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>();
1697 
1698  struct spRegionSizeInfo
1699  {
1700  public int sizeX;
1701  public int sizeY;
1702  }
1703 
1704  private Dictionary<ulong, spRegionSizeInfo> m_knownChildRegionsSizeInfo = new Dictionary<ulong, spRegionSizeInfo>();
1705 
1706 
1708  {
1709  lock (m_knownChildRegions)
1710  {
1711  spRegionSizeInfo sizeInfo = new spRegionSizeInfo();
1712  sizeInfo.sizeX = region.RegionSizeX;
1713  sizeInfo.sizeY = region.RegionSizeY;
1714  ulong regionHandle = region.RegionHandle;
1715 
1716  if (!m_knownChildRegionsSizeInfo.ContainsKey(regionHandle))
1717  {
1718  m_knownChildRegionsSizeInfo.Add(regionHandle, sizeInfo);
1719 
1720  }
1721  else
1722  m_knownChildRegionsSizeInfo[regionHandle] = sizeInfo;
1723  }
1724  }
1725 
1726  public void SetNeighbourRegionSizeInfo(List<GridRegion> regionsList)
1727  {
1728  lock (m_knownChildRegions)
1729  {
1730  m_knownChildRegionsSizeInfo.Clear();
1731  foreach (GridRegion region in regionsList)
1732  {
1733  spRegionSizeInfo sizeInfo = new spRegionSizeInfo();
1734  sizeInfo.sizeX = region.RegionSizeX;
1735  sizeInfo.sizeY = region.RegionSizeY;
1736  ulong regionHandle = region.RegionHandle;
1737  m_knownChildRegionsSizeInfo.Add(regionHandle, sizeInfo);
1738  }
1739  }
1740  }
1741 
1742  public void RemoveNeighbourRegion(ulong regionHandle)
1743  {
1744  lock (m_knownChildRegions)
1745  {
1746  // Checking ContainsKey is redundant as Remove works either way and returns a bool
1747  // This is here to allow the Debug output to be conditional on removal
1748  //if (m_knownChildRegions.ContainsKey(regionHandle))
1749  // m_log.DebugFormat(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count);
1750  m_knownChildRegions.Remove(regionHandle);
1751  m_knownChildRegionsSizeInfo.Remove(regionHandle);
1752  }
1753  }
1754 
1755  public void DropOldNeighbours(List<ulong> oldRegions)
1756  {
1757  foreach (ulong handle in oldRegions)
1758  {
1759  RemoveNeighbourRegion(handle);
1760  Scene.CapsModule.DropChildSeed(UUID, handle);
1761  }
1762  }
1763 
1765  {
1766  ulong handle = m_scene.RegionInfo.RegionHandle;
1767  RemoveNeighbourRegion(handle);
1768  Scene.CapsModule.DropChildSeed(UUID, handle);
1769  }
1770 
1771  public Dictionary<ulong, string> KnownRegions
1772  {
1773  get
1774  {
1775  lock (m_knownChildRegions)
1776  return new Dictionary<ulong, string>(m_knownChildRegions);
1777  }
1778  set
1779  {
1780  // Replacing the reference is atomic but we still need to lock on
1781  // the original dictionary object which may be in use elsewhere
1782  lock (m_knownChildRegions)
1783  m_knownChildRegions = value;
1784  }
1785  }
1786 
1787  public List<ulong> KnownRegionHandles
1788  {
1789  get
1790  {
1791  return new List<ulong>(KnownRegions.Keys);
1792  }
1793  }
1794 
1795  public int KnownRegionCount
1796  {
1797  get
1798  {
1799  lock (m_knownChildRegions)
1800  return m_knownChildRegions.Count;
1801  }
1802  }
1803 
1804  #endregion
1805 
1806  #region Event Handlers
1807 
1812  public void SetHeight(float height)
1813  {
1814  if (PhysicsActor != null && !IsChildAgent)
1815  PhysicsActor.Size = new Vector3(0.45f, 0.6f, height);
1816  }
1817 
1818  public void SetSize(Vector3 size, float feetoffset)
1819  {
1820  if (PhysicsActor != null && !IsChildAgent)
1821  PhysicsActor.setAvatarSize(size, feetoffset);
1822  }
1823 
1824  private bool WaitForUpdateAgent(IClientAPI client)
1825  {
1826  // Before the source region executes UpdateAgent
1827  // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination,
1828  // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
1829  // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
1830 // m_updateAgentReceivedAfterTransferEvent.WaitOne(10000);
1831  int count = 50;
1832  UUID originID = UUID.Zero;
1833 
1834  lock (m_originRegionIDAccessLock)
1835  originID = m_originRegionID;
1836 
1837 
1838  while (originID.Equals(UUID.Zero) && count-- > 0)
1839  {
1840  lock (m_originRegionIDAccessLock)
1841  originID = m_originRegionID;
1842 
1843  m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
1844  Thread.Sleep(200);
1845  }
1846 
1847  if (originID.Equals(UUID.Zero))
1848  {
1849  // Movement into region will fail
1850  m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
1851  return false;
1852  }
1853 
1854  return true;
1855  }
1856 
1866  public void CompleteMovement(IClientAPI client, bool openChildAgents)
1867  {
1868  int ts = Util.EnvironmentTickCount();
1869 
1870  m_log.InfoFormat(
1871  "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1872  client.Name, Scene.Name, AbsolutePosition);
1873 
1874  m_inTransit = true;
1875 
1876  try
1877  {
1878  // Make sure it's not a login agent. We don't want to wait for updates during login
1879  if (!isNPC && !IsRealLogin(m_teleportFlags))
1880  {
1881 
1882  // Let's wait until UpdateAgent (called by departing region) is done
1883  if (!WaitForUpdateAgent(client))
1884  // The sending region never sent the UpdateAgent data, we have to refuse
1885  return;
1886  }
1887 
1888  m_log.DebugFormat("[CompleteMovement] WaitForUpdateAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1889 
1890  bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1891 
1892  Vector3 look = Lookat;
1893  if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01))
1894  {
1895  look = Velocity;
1896  look.Z = 0;
1897  look.Normalize();
1898  if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01) )
1899  look = new Vector3(0.99f, 0.042f, 0);
1900  }
1901 
1902  if (!MakeRootAgent(AbsolutePosition, flying, ref look))
1903  {
1904  m_log.DebugFormat(
1905  "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
1906  Name, Scene.Name);
1907 
1908  return;
1909  }
1910 
1911  m_log.DebugFormat("[CompleteMovement] MakeRootAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1912 
1913 
1914 // start sending terrain patchs
1915  if (!isNPC)
1916  Scene.SendLayerData(ControllingClient);
1917 
1918  if (!IsChildAgent && !isNPC)
1919  {
1920  InventoryFolderBase cof = m_scene.InventoryService.GetFolderForType(client.AgentId, (FolderType)46);
1921  if (cof == null)
1922  COF = UUID.Zero;
1923  else
1924  COF = cof.ID;
1925 
1926  m_log.DebugFormat("[ScenePresence]: CompleteMovement COF for {0} is {1}", client.AgentId, COF);
1927  }
1928 
1929  // Tell the client that we're totally ready
1930  ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1931 
1932  m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1933 
1934  if (!string.IsNullOrEmpty(m_callbackURI))
1935  {
1936  // We cannot sleep here since this would hold up the inbound packet processing thread, as
1937  // CompleteMovement() is executed synchronously. However, it might be better to delay the release
1938  // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete
1939  // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this
1940  // region as the current region, meaning that a close sent before then will fail the teleport.
1941  // System.Threading.Thread.Sleep(2000);
1942 
1943  m_log.DebugFormat(
1944  "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1945  client.Name, client.AgentId, m_callbackURI);
1946 
1947  UUID originID;
1948 
1949  lock (m_originRegionIDAccessLock)
1950  originID = m_originRegionID;
1951 
1952  Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
1953  m_callbackURI = null;
1954  }
1955 // else
1956 // {
1957 // m_log.DebugFormat(
1958 // "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}",
1959 // client.Name, client.AgentId, m_scene.RegionInfo.RegionName);
1960 // }
1961 
1962  m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1963 
1964  m_previusParcelHide = false;
1965  m_previusParcelUUID = UUID.Zero;
1966  m_currentParcelHide = false;
1967  m_currentParcelUUID = UUID.Zero;
1968 
1969  // send initial land overlay and parcel
1970  ILandChannel landch = m_scene.LandChannel;
1971  if (landch != null)
1972  landch.sendClientInitialLandInfo(client);
1973 
1974  if (!IsChildAgent)
1975  {
1976  // verify baked textures and cache
1977  bool cachedbaked = false;
1978 
1979  if (isNPC)
1980  cachedbaked = true;
1981  else
1982  {
1983  if (m_scene.AvatarFactory != null)
1984  cachedbaked = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
1985 
1986  // not sure we need this
1987  if (!cachedbaked)
1988  {
1989  if (m_scene.AvatarFactory != null)
1990  m_scene.AvatarFactory.QueueAppearanceSave(UUID);
1991  }
1992  }
1993 
1994  List<ScenePresence> allpresences = m_scene.GetScenePresences();
1995 
1996  // send avatar object to all presences including us, so they cross it into region
1997  // then hide if necessary
1998  SendInitialAvatarDataToAllAgents(allpresences);
1999 
2000  // send this look
2001  SendAppearanceToAgent(this);
2002 
2003  // send this animations
2004 
2005  UUID[] animIDs = null;
2006  int[] animseqs = null;
2007  UUID[] animsobjs = null;
2008 
2009  if (Animator != null)
2010  Animator.GetArrays(out animIDs, out animseqs, out animsobjs);
2011 
2012  bool haveAnims = (animIDs != null && animseqs != null && animsobjs != null);
2013 
2014  if (haveAnims)
2015  SendAnimPackToAgent(this, animIDs, animseqs, animsobjs);
2016 
2017  // we should be able to receive updates, etc
2018  // so release them
2019  m_inTransit = false;
2020 
2021  // send look and animations to others
2022  // if not cached we send greys
2023  // uncomented if will wait till avatar does baking
2024  //if (cachedbaked)
2025  {
2026  foreach (ScenePresence p in allpresences)
2027  {
2028  if (p == this)
2029  continue;
2030 
2031  if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
2032  continue;
2033 
2034  SendAppearanceToAgentNF(p);
2035  if (haveAnims)
2036  SendAnimPackToAgentNF(p, animIDs, animseqs, animsobjs);
2037  }
2038  } // greys if
2039 
2040  m_log.DebugFormat("[CompleteMovement] ValidateAndSendAppearanceAndAgentData: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2041 
2042  // attachments
2043  if (isNPC || IsRealLogin(m_teleportFlags))
2044  {
2045  if (Scene.AttachmentsModule != null)
2046  // Util.FireAndForget(
2047  // o =>
2048  // {
2049 
2050  if (!isNPC)
2051  Scene.AttachmentsModule.RezAttachments(this);
2052  else
2053  Util.FireAndForget(x =>
2054  {
2055  Scene.AttachmentsModule.RezAttachments(this);
2056  });
2057 
2058  // });
2059  }
2060  else
2061  {
2062  if (m_attachments.Count > 0)
2063  {
2064  m_log.DebugFormat(
2065  "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
2066 
2067  foreach (SceneObjectGroup sog in m_attachments)
2068  {
2069  sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
2070  sog.ResumeScripts();
2071  }
2072 
2073  foreach (ScenePresence p in allpresences)
2074  {
2075  if (p == this)
2076  {
2077  SendAttachmentsToAgentNF(this);
2078  continue;
2079  }
2080 
2081  if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
2082  continue;
2083 
2084  SendAttachmentsToAgentNF(p);
2085  }
2086  }
2087  }
2088 
2089  m_log.DebugFormat("[CompleteMovement] attachments: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2090  if (openChildAgents)
2091  {
2092  // Create child agents in neighbouring regions
2093  IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
2094  if (m_agentTransfer != null)
2095  {
2096  m_agentTransfer.EnableChildAgents(this);
2097  }
2098  // let updates be sent, with some delay
2099  lastChildUpdatesTime = Util.EnvironmentTickCount() + 10000;
2100  childUpdatesBusy = false; // allow them
2101  }
2102  }
2103 
2104  m_log.DebugFormat("[CompleteMovement] openChildAgents: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2105 
2106  // send the rest of the world
2107  if (m_teleportFlags > 0 && !isNPC || m_currentParcelHide)
2108  SendInitialDataToMe();
2109 
2110  // priority uses avatar position only
2111  m_reprioritizationLastPosition = AbsolutePosition;
2112  m_reprioritizationLastTime = Util.EnvironmentTickCount() + 15000; // delay it
2113  m_reprioritizationBusy = false;
2114 
2115  m_log.DebugFormat("[CompleteMovement] SendInitialDataToMe: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2116 
2117  if (!IsChildAgent && openChildAgents)
2118  {
2119  IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
2120  if (friendsModule != null)
2121  friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
2122 
2123  m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2124 
2125  }
2126  }
2127  finally
2128  {
2129  m_inTransit = false;
2130  }
2131  // if hide force a check
2132  // if (!IsChildAgent && newhide)
2133  // {
2134  // ParcelLoginCheck(m_currentParcelUUID);
2135  // m_currentParcelHide = newhide;
2136  // }
2137 
2138  m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd;
2139 
2140  m_log.DebugFormat("[CompleteMovement] end: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2141  }
2142 
2152 
2153  private void UpdateCameraCollisionPlane(Vector4 plane)
2154  {
2155  if (m_lastCameraCollisionPlane != plane)
2156  {
2157  m_lastCameraCollisionPlane = plane;
2158  ControllingClient.SendCameraConstraint(plane);
2159  }
2160  }
2161 
2162  public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal)
2163  {
2164  const float POSITION_TOLERANCE = 0.02f;
2165  const float ROTATION_TOLERANCE = 0.02f;
2166 
2167  m_doingCamRayCast = false;
2168  if (hitYN && localid != LocalId)
2169  {
2170  SceneObjectGroup group = m_scene.GetGroupByPrim(localid);
2171  bool IsPrim = group != null;
2172  if (IsPrim)
2173  {
2174  SceneObjectPart part = group.GetPart(localid);
2175  if (part != null && !part.VolumeDetectActive)
2176  {
2177  CameraConstraintActive = true;
2178  pNormal.X = (float) Math.Round(pNormal.X, 2);
2179  pNormal.Y = (float) Math.Round(pNormal.Y, 2);
2180  pNormal.Z = (float) Math.Round(pNormal.Z, 2);
2181  pNormal.Normalize();
2182  collisionPoint.X = (float) Math.Round(collisionPoint.X, 1);
2183  collisionPoint.Y = (float) Math.Round(collisionPoint.Y, 1);
2184  collisionPoint.Z = (float) Math.Round(collisionPoint.Z, 1);
2185 
2186  Vector4 plane = new Vector4(pNormal.X, pNormal.Y, pNormal.Z,
2187  Vector3.Dot(collisionPoint, pNormal));
2188  UpdateCameraCollisionPlane(plane);
2189  }
2190  }
2191  else
2192  {
2193  CameraConstraintActive = true;
2194  pNormal.X = (float) Math.Round(pNormal.X, 2);
2195  pNormal.Y = (float) Math.Round(pNormal.Y, 2);
2196  pNormal.Z = (float) Math.Round(pNormal.Z, 2);
2197  pNormal.Normalize();
2198  collisionPoint.X = (float) Math.Round(collisionPoint.X, 1);
2199  collisionPoint.Y = (float) Math.Round(collisionPoint.Y, 1);
2200  collisionPoint.Z = (float) Math.Round(collisionPoint.Z, 1);
2201 
2202  Vector4 plane = new Vector4(pNormal.X, pNormal.Y, pNormal.Z,
2203  Vector3.Dot(collisionPoint, pNormal));
2204  UpdateCameraCollisionPlane(plane);
2205  }
2206  }
2207  else if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
2208  !Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE))
2209  {
2210  Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -9000f); // not right...
2211  UpdateCameraCollisionPlane(plane);
2212  CameraConstraintActive = false;
2213  }
2214  }
2215 
2219  public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
2220  {
2221 // m_log.DebugFormat(
2222 // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}",
2223 // Scene.Name, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
2224 
2225  if (IsChildAgent)
2226  {
2227 // m_log.DebugFormat("DEBUG: HandleAgentUpdate: child agent in {0}", Scene.Name);
2228  return;
2229  }
2230 
2231  if (IsInTransit)
2232  return;
2233 
2234  #region Sanity Checking
2235 
2236  // This is irritating. Really.
2237  if (!AbsolutePosition.IsFinite())
2238  {
2239  RemoveFromPhysicalScene();
2240  m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
2241 
2242  m_pos = m_LastFinitePos;
2243  if (!m_pos.IsFinite())
2244  {
2245  m_pos.X = 127f;
2246  m_pos.Y = 127f;
2247  m_pos.Z = 127f;
2248  m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903");
2249  }
2250 
2251  AddToPhysicalScene(false);
2252  }
2253  else
2254  {
2255  m_LastFinitePos = m_pos;
2256  }
2257 
2258  #endregion Sanity Checking
2259 
2260  #region Inputs
2261 
2262  AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
2263 
2264  // The Agent's Draw distance setting
2265  // When we get to the point of re-computing neighbors everytime this
2266  // changes, then start using the agent's drawdistance rather than the
2267  // region's draw distance.
2268 
2269  DrawDistance = agentData.Far;
2270 
2271  m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
2272 
2273  // FIXME: This does not work as intended because the viewer only sends the lbutton down when the button
2274  // is first pressed, not whilst it is held down. If this is required in the future then need to look
2275  // for an AGENT_CONTROL_LBUTTON_UP event and make sure to handle cases where an initial DOWN is not
2276  // received (e.g. on holding LMB down on the avatar in a viewer).
2277  m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
2278 
2279  #endregion Inputs
2280 
2281 // // Make anims work for client side autopilot
2282 // if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0)
2283 // m_updateCount = UPDATE_COUNT;
2284 //
2285 // // Make turning in place work
2286 // if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0 ||
2287 // (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
2288 // m_updateCount = UPDATE_COUNT;
2289 
2290 
2291  if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
2292  {
2293  StandUp();
2294  }
2295 
2296  // Raycast from the avatar's head to the camera to see if there's anything blocking the view
2297  // this exclude checks may not be complete
2298 
2299  if (m_movementUpdateCount % NumMovementsBetweenRayCast == 0 && m_scene.PhysicsScene.SupportsRayCast())
2300  {
2301  if (!m_doingCamRayCast && !m_mouseLook && ParentID == 0)
2302  {
2303  Vector3 posAdjusted = AbsolutePosition;
2304 // posAdjusted.Z += 0.5f * Appearance.AvatarSize.Z - 0.5f;
2305  posAdjusted.Z += 1.0f; // viewer current camera focus point
2306  Vector3 tocam = CameraPosition - posAdjusted;
2307  tocam.X = (float)Math.Round(tocam.X, 1);
2308  tocam.Y = (float)Math.Round(tocam.Y, 1);
2309  tocam.Z = (float)Math.Round(tocam.Z, 1);
2310 
2311  float distTocamlen = tocam.Length();
2312  if (distTocamlen > 0.3f)
2313  {
2314  tocam *= (1.0f / distTocamlen);
2315  posAdjusted.X = (float)Math.Round(posAdjusted.X, 1);
2316  posAdjusted.Y = (float)Math.Round(posAdjusted.Y, 1);
2317  posAdjusted.Z = (float)Math.Round(posAdjusted.Z, 1);
2318 
2319  m_doingCamRayCast = true;
2320  m_scene.PhysicsScene.RaycastWorld(posAdjusted, tocam, distTocamlen + 1.0f, RayCastCameraCallback);
2321  }
2322  }
2323  else if (CameraConstraintActive && (m_mouseLook || ParentID != 0))
2324  {
2325  Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -10000f); // not right...
2326  UpdateCameraCollisionPlane(plane);
2327  CameraConstraintActive = false;
2328  }
2329  }
2330 
2331  uint flagsForScripts = (uint)flags;
2332  flags = RemoveIgnoredControls(flags, IgnoredControls);
2333 
2334  if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
2335  HandleAgentSitOnGround();
2336 
2337  // In the future, these values might need to go global.
2338  // Here's where you get them.
2339  m_AgentControlFlags = flags;
2340  m_headrotation = agentData.HeadRotation;
2341  byte oldState = State;
2342  State = agentData.State;
2343 
2344  // We need to send this back to the client in order to stop the edit beams
2345  if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
2346  SendAgentTerseUpdate(this);
2347 
2348  PhysicsActor actor = PhysicsActor;
2349 
2350  // This will be the case if the agent is sitting on the groudn or on an object.
2351  if (actor == null)
2352  {
2353  SendControlsToScripts(flagsForScripts);
2354  return;
2355  }
2356 
2357  if (AllowMovement && !SitGround)
2358  {
2359 // m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name);
2360  bool update_rotation = false;
2361  if (agentData.BodyRotation != Rotation)
2362  {
2363  Rotation = agentData.BodyRotation;
2364  update_rotation = true;
2365  }
2366 
2367  bool update_movementflag = false;
2368 
2369  if (agentData.UseClientAgentPosition)
2370  {
2371  MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
2372  MoveToPositionTarget = agentData.ClientAgentPosition;
2373  }
2374 
2375  int i = 0;
2376  bool DCFlagKeyPressed = false;
2377  Vector3 agent_control_v3 = Vector3.Zero;
2378 
2379  bool newFlying = false;
2380 
2381  if (ForceFly)
2382  newFlying = true;
2383  else if (FlyDisabled)
2384  newFlying = false;
2385  else
2386  newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
2387 
2388  if (actor.Flying != newFlying)
2389  {
2390  // Note: ScenePresence.Flying is actually fetched from the physical actor
2391  // so setting PhysActor.Flying here also sets the ScenePresence's value.
2392  actor.Flying = newFlying;
2393  update_movementflag = true;
2394  }
2395 
2396  if (ParentID == 0)
2397  {
2398  bool bAllowUpdateMoveToPosition = false;
2399 
2400  Vector3[] dirVectors;
2401 
2402  // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying
2403  // this prevents 'jumping' in inappropriate situations.
2404 // if (!Flying && (m_mouseLook || m_leftButtonDown))
2405 // dirVectors = GetWalkDirectionVectors();
2406 // else
2407  dirVectors = Dir_Vectors;
2408 
2409  // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction.
2410  foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
2411  {
2412  if (((uint)flags & (uint)DCF) != 0)
2413  {
2414  DCFlagKeyPressed = true;
2415 
2416  try
2417  {
2418  agent_control_v3 += Dir_Vectors[i];
2419  //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]);
2420  }
2421  catch (IndexOutOfRangeException)
2422  {
2423  // Why did I get this?
2424  }
2425 
2426  if (((MovementFlag & (uint)DCF) == 0))
2427  {
2428  //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
2429  MovementFlag |= (uint)DCF;
2430  update_movementflag = true;
2431  }
2432  }
2433  else
2434  {
2435  if ((MovementFlag & (uint)DCF) != 0)
2436  {
2437  //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
2438  MovementFlag &= (uint)~DCF;
2439  update_movementflag = true;
2440 
2441  /*
2442  if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
2443  && ((MovementFlag & (byte)nudgehack) == nudgehack))
2444  {
2445  m_log.Debug("Removed Hack flag");
2446  }
2447  */
2448  }
2449  else
2450  {
2451  bAllowUpdateMoveToPosition = true;
2452  }
2453  }
2454 
2455  i++;
2456  }
2457 
2458  // Detect AGENT_CONTROL_STOP state changes
2459  if (AgentControlStopActive != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0))
2460  {
2461  AgentControlStopActive = !AgentControlStopActive;
2462  update_movementflag = true;
2463  }
2464 
2465  if (MovingToTarget)
2466  {
2467  // If the user has pressed a key then we want to cancel any move to target.
2468  if (DCFlagKeyPressed)
2469  {
2470  ResetMoveToTarget();
2471  update_movementflag = true;
2472  }
2473  else if (bAllowUpdateMoveToPosition)
2474  {
2475  // The UseClientAgentPosition is set if parcel ban is forcing the avatar to move to a
2476  // certain position. It's only check for tolerance on returning to that position is 0.2
2477  // rather than 1, at which point it removes its force target.
2478  if (HandleMoveToTargetUpdate(agentData.UseClientAgentPosition ? 0.2f : 1f, ref agent_control_v3))
2479  update_movementflag = true;
2480  }
2481  }
2482  }
2483 
2484  // Cause the avatar to stop flying if it's colliding
2485  // with something with the down arrow pressed.
2486 
2487  // Only do this if we're flying
2488  if (Flying && !ForceFly)
2489  {
2490  // Need to stop in mid air if user holds down AGENT_CONTROL_STOP
2491  // if (AgentControlStopActive)
2492  // {
2493  // agent_control_v3 = Vector3.Zero;
2494  // }
2495  // else
2496  {
2497  // Landing detection code
2498 
2499  // Are the landing controls requirements filled?
2500  bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
2501  ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
2502 
2503  //m_log.Debug("[CONTROL]: " +flags);
2504  // Applies a satisfying roll effect to the avatar when flying.
2505  if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
2506  {
2507  ApplyFlyingRoll(
2508  FLY_ROLL_RADIANS_PER_UPDATE,
2509  (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2510  (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2511  }
2512  else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
2513  (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
2514  {
2515  ApplyFlyingRoll(
2516  -FLY_ROLL_RADIANS_PER_UPDATE,
2517  (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2518  (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2519  }
2520  else
2521  {
2522  if (m_AngularVelocity.Z != 0)
2523  m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
2524  }
2525 
2526  /*
2527  if (Flying && IsColliding && controlland)
2528  {
2529  // nesting this check because LengthSquared() is expensive and we don't
2530  // want to do it every step when flying.
2531  if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2532  StopFlying();
2533  }
2534  */
2535  }
2536  }
2537  else if (IsColliding && agent_control_v3.Z < 0f)
2538  agent_control_v3.Z = 0;
2539 // else if(AgentControlStopActive %% Velocity.Z <0.01f)
2540 
2541 
2542 // m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);
2543 
2544  // If the agent update does move the avatar, then calculate the force ready for the velocity update,
2545  // which occurs later in the main scene loop
2546  // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they
2547  // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update
2548  // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the
2549  // avatar location in place).
2550  if (update_movementflag
2551  || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
2552  {
2553 
2554  if (AgentControlStopActive)
2555  {
2556  // if (MovementFlag == 0 && Animator.Falling)
2557  if (MovementFlag == 0 && Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling)
2558  {
2559  AddNewMovement(agent_control_v3, AgentControlStopSlowVel, true);
2560  }
2561  else
2562  AddNewMovement(agent_control_v3, AgentControlStopSlowVel);
2563  }
2564  else
2565  {
2566  AddNewMovement(agent_control_v3);
2567  }
2568 
2569  }
2570 
2571  if (update_movementflag && ParentID == 0)
2572  {
2573 // m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name);
2574  Animator.UpdateMovementAnimations();
2575  }
2576 
2577  SendControlsToScripts(flagsForScripts);
2578  }
2579 
2580  // We need to send this back to the client in order to see the edit beams
2581  if ((State & (uint)AgentState.Editing) != 0)
2582  SendAgentTerseUpdate(this);
2583 
2584 // m_scene.EventManager.TriggerOnClientMovement(this);
2585  }
2586 
2587 
2591  private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
2592  {
2593  //m_log.DebugFormat(
2594  // "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}",
2595  // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
2596 
2597  if (IsChildAgent)
2598  {
2599  // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
2600  return;
2601  }
2602 
2603  ++m_movementUpdateCount;
2604  if (m_movementUpdateCount < 1)
2605  m_movementUpdateCount = 1;
2606 
2607 // AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
2608 
2609  // Camera location in world. We'll need to raytrace
2610  // from this location from time to time.
2611  CameraPosition = agentData.CameraCenter;
2612  // Use these three vectors to figure out what the agent is looking at
2613  // Convert it to a Matrix and/or Quaternion
2614  CameraAtAxis = agentData.CameraAtAxis;
2615  CameraLeftAxis = agentData.CameraLeftAxis;
2616  CameraUpAxis = agentData.CameraUpAxis;
2617 
2618  // The Agent's Draw distance setting
2619  // When we get to the point of re-computing neighbors everytime this
2620  // changes, then start using the agent's drawdistance rather than the
2621  // region's draw distance.
2622 
2623  DrawDistance = agentData.Far;
2624 
2625  // Check if Client has camera in 'follow cam' or 'build' mode.
2626  Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
2627 
2628  m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f)
2629  && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
2630 
2631 
2632  //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
2633  // Raycast from the avatar's head to the camera to see if there's anything blocking the view
2634  if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
2635  {
2636  if (m_followCamAuto)
2637  {
2638  Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
2639  m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
2640  }
2641  }
2642 
2643  TriggerScenePresenceUpdated();
2644  }
2645 
2654  public bool HandleMoveToTargetUpdate(float tolerance, ref Vector3 agent_control_v3)
2655  {
2656 // m_log.DebugFormat("[SCENE PRESENCE]: Called HandleMoveToTargetUpdate() for {0}", Name);
2657 
2658  bool updated = false;
2659 
2660  Vector3 LocalVectorToTarget3D = MoveToPositionTarget - AbsolutePosition;
2661 
2662 // m_log.DebugFormat(
2663 // "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}",
2664 // allowUpdate, m_moveToPositionInProgress, m_autopilotMoving);
2665 
2666  float distanceToTarget;
2667  if(Flying && !LandAtTarget)
2668  {
2669  distanceToTarget = LocalVectorToTarget3D.Length();
2670  }
2671  else
2672  {
2673  Vector3 hdist = LocalVectorToTarget3D;
2674  hdist.Z = 0;
2675  distanceToTarget = hdist.Length();
2676  }
2677 
2678  // m_log.DebugFormat(
2679  // "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}",
2680  // Name, AbsolutePosition, MoveToPositionTarget, distanceToTarget);
2681 
2682  // Check the error term of the current position in relation to the target position
2683  if (distanceToTarget <= tolerance)
2684  {
2685  // We are close enough to the target
2686  Velocity = Vector3.Zero;
2687  AbsolutePosition = MoveToPositionTarget;
2688  if (Flying)
2689  {
2690  if (LandAtTarget)
2691  Flying = false;
2692 
2693  // A horrible hack to stop the avatar dead in its tracks rather than having them overshoot
2694  // the target if flying.
2695  // We really need to be more subtle (slow the avatar as it approaches the target) or at
2696  // least be able to set collision status once, rather than 5 times to give it enough
2697  // weighting so that that PhysicsActor thinks it really is colliding.
2698  for (int i = 0; i < 5; i++)
2699  IsColliding = true;
2700  }
2701  ResetMoveToTarget();
2702  return false;
2703  }
2704  else
2705  {
2706  try
2707  {
2708  // move avatar in 3D at one meter/second towards target, in avatar coordinate frame.
2709  // This movement vector gets added to the velocity through AddNewMovement().
2710  // Theoretically we might need a more complex PID approach here if other
2711  // unknown forces are acting on the avatar and we need to adaptively respond
2712  // to such forces, but the following simple approach seems to works fine.
2713 
2714  LocalVectorToTarget3D = LocalVectorToTarget3D * Quaternion.Inverse(Rotation); // change to avatar coords
2715 
2716  LocalVectorToTarget3D.Normalize();
2717 
2718  // update avatar movement flags. the avatar coordinate system is as follows:
2719  //
2720  // +X (forward)
2721  //
2722  // ^
2723  // |
2724  // |
2725  // |
2726  // |
2727  // (left) +Y <--------o--------> -Y
2728  // avatar
2729  // |
2730  // |
2731  // |
2732  // |
2733  // v
2734  // -X
2735  //
2736 
2737  // based on the above avatar coordinate system, classify the movement into
2738  // one of left/right/back/forward.
2739 
2740  const uint noMovFlagsMask = (uint)(~(Dir_ControlFlags.DIR_CONTROL_FLAG_BACK |
2741  Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD | Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT |
2742  Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT | Dir_ControlFlags.DIR_CONTROL_FLAG_UP |
2743  Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN));
2744 
2745  MovementFlag &= noMovFlagsMask;
2746  AgentControlFlags &= noMovFlagsMask;
2747 
2748  if (LocalVectorToTarget3D.X < 0) //MoveBack
2749  {
2750  MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2751  AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2752  updated = true;
2753  }
2754  else if (LocalVectorToTarget3D.X > 0) //Move Forward
2755  {
2756  MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
2757  AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
2758  updated = true;
2759  }
2760 
2761  if (LocalVectorToTarget3D.Y > 0) //MoveLeft
2762  {
2763  MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
2764  AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
2765  updated = true;
2766  }
2767  else if (LocalVectorToTarget3D.Y < 0) //MoveRight
2768  {
2769  MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
2770  AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
2771  updated = true;
2772  }
2773 
2774  if (LocalVectorToTarget3D.Z > 0) //Up
2775  {
2776  // Don't set these flags for up or down - doing so will make the avatar crouch or
2777  // keep trying to jump even if walking along level ground
2778  //MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_UP;
2779  //AgentControlFlags
2780  //AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_UP;
2781  updated = true;
2782  }
2783  else if (LocalVectorToTarget3D.Z < 0) //Down
2784  {
2785  //MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN;
2786  //AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN;
2787  updated = true;
2788  }
2789 
2790 // m_log.DebugFormat(
2791 // "[SCENE PRESENCE]: HandleMoveToTargetUpdate adding {0} to move vector {1} for {2}",
2792 // LocalVectorToTarget3D, agent_control_v3, Name);
2793 
2794  agent_control_v3 += LocalVectorToTarget3D;
2795  }
2796  catch (Exception e)
2797  {
2798  //Avoid system crash, can be slower but...
2799  m_log.DebugFormat("Crash! {0}", e.ToString());
2800  }
2801  }
2802 
2803  return updated;
2804 // AddNewMovement(agent_control_v3);
2805  }
2806 
2819  public void MoveToTarget(Vector3 pos, bool noFly, bool landAtTarget)
2820  {
2821  if (SitGround)
2822  StandUp();
2823 
2824 // m_log.DebugFormat(
2825 // "[SCENE PRESENCE]: Avatar {0} received request to move to position {1} in {2}",
2826 // Name, pos, m_scene.RegionInfo.RegionName);
2827 
2828  // Allow move to another sub-region within a megaregion
2829  Vector2 regionSize;
2830  IRegionCombinerModule regionCombinerModule = m_scene.RequestModuleInterface<IRegionCombinerModule>();
2831  if (regionCombinerModule != null)
2832  regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
2833  else
2834  regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY);
2835 
2836  if (pos.X < 0 || pos.X >= regionSize.X
2837  || pos.Y < 0 || pos.Y >= regionSize.Y
2838  || pos.Z < 0)
2839  return;
2840 
2841  float terrainHeight;
2842  Scene targetScene = m_scene;
2843  // Get terrain height for sub-region in a megaregion if necessary
2844  if (regionCombinerModule != null)
2845  {
2846  int X = (int)((m_scene.RegionInfo.WorldLocX) + pos.X);
2847  int Y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y);
2848  GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y);
2849  // If X and Y is NaN, target_region will be null
2850  if (target_region == null)
2851  return;
2852  UUID target_regionID = target_region.RegionID;
2853  SceneManager.Instance.TryGetScene(target_region.RegionID, out targetScene);
2854  terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)];
2855  }
2856  else
2857  terrainHeight = m_scene.GetGroundHeight(pos.X, pos.Y);
2858 
2859  // dont try to land underground
2860  terrainHeight += Appearance.AvatarHeight * 0.5f + 0.2f;
2861 
2862  if(terrainHeight > pos.Z)
2863  pos.Z = terrainHeight;
2864 
2865 // m_log.DebugFormat(
2866 // "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
2867 // Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
2868 
2869  if (noFly)
2870  Flying = false;
2871  else if (pos.Z > terrainHeight || Flying)
2872  Flying = true;
2873 
2874  LandAtTarget = landAtTarget;
2875  MovingToTarget = true;
2876  MoveToPositionTarget = pos;
2877 
2878  // Rotate presence around the z-axis to point in same direction as movement.
2879  // Ignore z component of vector
2880  Vector3 localVectorToTarget3D = pos - AbsolutePosition;
2881  Vector3 localVectorToTarget2D = new Vector3((float)(localVectorToTarget3D.X), (float)(localVectorToTarget3D.Y), 0f);
2882 
2883 // m_log.DebugFormat("[SCENE PRESENCE]: Local vector to target is {0}", localVectorToTarget2D);
2884 
2885  // Calculate the yaw.
2886  Vector3 angle = new Vector3(0, 0, (float)(Math.Atan2(localVectorToTarget2D.Y, localVectorToTarget2D.X)));
2887 
2888 // m_log.DebugFormat("[SCENE PRESENCE]: Angle is {0}", angle);
2889 
2890  Rotation = Quaternion.CreateFromEulers(angle);
2891 // m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, Rotation);
2892 
2893  Vector3 control = Vector3.Zero;
2894  if(HandleMoveToTargetUpdate(1f, ref control))
2895  AddNewMovement(control);
2896  }
2897 
2901  public void ResetMoveToTarget()
2902  {
2903 // m_log.DebugFormat("[SCENE PRESENCE]: Resetting move to target for {0}", Name);
2904 
2905  MovingToTarget = false;
2906 // MoveToPositionTarget = Vector3.Zero;
2907  m_forceToApply = null; // cancel possible last action
2908 
2909  // We need to reset the control flag as the ScenePresenceAnimator uses this to determine the correct
2910  // resting animation (e.g. hover or stand). NPCs don't have a client that will quickly reset this flag.
2911  // However, the line is here rather than in the NPC module since it also appears necessary to stop a
2912  // viewer that uses "go here" from juddering on all subsequent avatar movements.
2913  AgentControlFlags = (uint)AgentManager.ControlFlags.NONE;
2914  }
2915 
2920  public void StandUp()
2921  {
2922 // m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
2923 
2924  bool satOnObject = IsSatOnObject;
2925  SceneObjectPart part = ParentPart;
2926  SitGround = false;
2927 
2928  if (satOnObject)
2929  {
2930  PrevSitOffset = m_pos; // Save sit offset
2931  UnRegisterSeatControls(part.ParentGroup.UUID);
2932 
2933  TaskInventoryDictionary taskIDict = part.TaskInventory;
2934  if (taskIDict != null)
2935  {
2936  lock (taskIDict)
2937  {
2938  foreach (UUID taskID in taskIDict.Keys)
2939  {
2940  UnRegisterControlEventsToScript(LocalId, taskID);
2941  taskIDict[taskID].PermsMask &= ~(
2942  2048 | //PERMISSION_CONTROL_CAMERA
2943  4); // PERMISSION_TAKE_CONTROLS
2944  }
2945  }
2946  }
2947 
2948 // part.ParentGroup.DeleteAvatar(UUID);
2949 
2950  Quaternion standRotation = part.ParentGroup.RootPart.RotationOffset;
2951  Vector3 sitPartWorldPosition = part.ParentGroup.AbsolutePosition + m_pos * standRotation;
2952  ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2953 
2954  ParentID = 0;
2955  ParentPart = null;
2956 
2957  if (part.SitTargetAvatar == UUID)
2958  standRotation = standRotation * part.SitTargetOrientation;
2959  else
2960  standRotation = standRotation * m_bodyRot;
2961 
2962  m_bodyRot = standRotation;
2963 
2964  Quaternion standRotationZ = new Quaternion(0,0,standRotation.Z,standRotation.W);
2965 
2966  float t = standRotationZ.W * standRotationZ.W + standRotationZ.Z * standRotationZ.Z;
2967  if (t > 0)
2968  {
2969  t = 1.0f / (float)Math.Sqrt(t);
2970  standRotationZ.W *= t;
2971  standRotationZ.Z *= t;
2972  }
2973  else
2974  {
2975  standRotationZ.W = 1.0f;
2976  standRotationZ.Z = 0f;
2977  }
2978 
2979  Vector3 adjustmentForSitPose = new Vector3(0.75f, 0, m_sitAvatarHeight + .3f) * standRotationZ;
2980 
2981  Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose;
2982  m_pos = standPos;
2983  }
2984 
2985  // We need to wait until we have calculated proper stand positions before sitting up the physical
2986  // avatar to avoid race conditions.
2987  if (PhysicsActor == null)
2988  AddToPhysicalScene(false);
2989 
2990  if (satOnObject)
2991  {
2992  m_requestedSitTargetID = 0;
2993  part.RemoveSittingAvatar(this);
2994  part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2995 
2996  SendAvatarDataToAllAgents();
2997  }
2998 
2999  // reset to default sitAnimation
3000  sitAnimation = "SIT";
3001 
3002 // Animator.TrySetMovementAnimation("STAND");
3003  Animator.SetMovementAnimations("STAND");
3004 
3005  TriggerScenePresenceUpdated();
3006  }
3007 
3008  private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
3009  {
3010  SceneObjectPart targetPart = m_scene.GetSceneObjectPart(targetID);
3011  if (targetPart == null)
3012  return null;
3013 
3014  // If the primitive the player clicked on has a sit target and that sit target is not full, that sit target is used.
3015  // If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used.
3016 
3017  // Get our own copy of the part array, and sort into the order we want to test
3018  SceneObjectPart[] partArray = targetPart.ParentGroup.Parts;
3019  Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2)
3020  {
3021  // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1)
3022  int linkNum1 = p1==targetPart ? -1 : p1.LinkNum;
3023  int linkNum2 = p2==targetPart ? -1 : p2.LinkNum;
3024  return linkNum1 - linkNum2;
3025  }
3026  );
3027 
3028  //look for prims with explicit sit targets that are available
3029  foreach (SceneObjectPart part in partArray)
3030  {
3031  if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
3032  {
3033  //switch the target to this prim
3034  return part;
3035  }
3036  }
3037 
3038  // no explicit sit target found - use original target
3039  return targetPart;
3040  }
3041 
3042  private void SendSitResponse(UUID targetID, Vector3 offset, Quaternion sitOrientation)
3043  {
3044  Vector3 cameraEyeOffset = Vector3.Zero;
3045  Vector3 cameraAtOffset = Vector3.Zero;
3046  bool forceMouselook = false;
3047 
3048  SceneObjectPart part = FindNextAvailableSitTarget(targetID);
3049  if (part == null)
3050  return;
3051 
3052 
3053  if (PhysicsActor != null)
3054  m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
3055 
3056  bool canSit = false;
3057 
3058  if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
3059  {
3060  offset = part.SitTargetPosition;
3061  sitOrientation = part.SitTargetOrientation;
3062 
3063  canSit = true;
3064  }
3065  else
3066  {
3067  if (PhysicsSit(part,offset)) // physics engine
3068  return;
3069 
3070  Vector3 pos = part.AbsolutePosition + offset;
3071 
3072  if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10)
3073  {
3074  AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
3075  canSit = true;
3076  }
3077  }
3078 
3079  if (canSit)
3080  {
3081 
3082  if (PhysicsActor != null)
3083  {
3084  // We can remove the physicsActor until they stand up.
3085  RemoveFromPhysicalScene();
3086  }
3087 
3088  if (MovingToTarget)
3089  ResetMoveToTarget();
3090 
3091  Velocity = Vector3.Zero;
3092 
3093  part.AddSittingAvatar(this);
3094 
3095  cameraAtOffset = part.GetCameraAtOffset();
3096  cameraEyeOffset = part.GetCameraEyeOffset();
3097 
3098  forceMouselook = part.GetForceMouselook();
3099 
3100  if (!part.IsRoot)
3101  {
3102  sitOrientation = part.RotationOffset * sitOrientation;
3103  offset = offset * part.RotationOffset;
3104  offset += part.OffsetPosition;
3105 
3106  if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
3107  {
3108  CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
3109  cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
3110  }
3111  else
3112  {
3113  cameraAtOffset = cameraAtOffset * part.RotationOffset;
3114  cameraAtOffset += part.OffsetPosition;
3115  cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
3116  cameraEyeOffset += part.OffsetPosition;
3117  }
3118  }
3119 
3120  ControllingClient.SendSitResponse(
3121  part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
3122 
3123  m_requestedSitTargetUUID = part.UUID;
3124 
3125  HandleAgentSit(ControllingClient, UUID);
3126 
3127  // Moved here to avoid a race with default sit anim
3128  // The script event needs to be raised after the default sit anim is set.
3129  part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
3130  }
3131  }
3132 
3133  public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset)
3134  {
3135  if (IsChildAgent)
3136  return;
3137 
3138  if (ParentID != 0)
3139  {
3140  if (ParentPart.UUID == targetID)
3141  return; // already sitting here, ignore
3142 
3143  StandUp();
3144  }
3145 
3146  SceneObjectPart part = FindNextAvailableSitTarget(targetID);
3147 
3148  if (part != null)
3149  {
3150  m_requestedSitTargetID = part.LocalId;
3151  m_requestedSitTargetUUID = part.UUID;
3152  }
3153  else
3154  {
3155  m_log.Warn("Sit requested on unknown object: " + targetID.ToString());
3156  }
3157 
3158  SendSitResponse(targetID, offset, Quaternion.Identity);
3159  }
3160 
3161  // returns false if does not suport so older sit can be tried
3162  public bool PhysicsSit(SceneObjectPart part, Vector3 offset)
3163  {
3164  if (part == null || part.ParentGroup.IsAttachment)
3165  return true;
3166 
3167  if ( m_scene.PhysicsScene == null)
3168  return false;
3169 
3170  if (part.PhysActor == null)
3171  {
3172  // none physcis shape
3173  if (part.PhysicsShapeType == (byte)PhysicsShapeType.None)
3174  ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot.");
3175  else
3176  { // non physical phantom TODO
3177 // ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot.");
3178  return false;
3179  }
3180  return true;
3181  }
3182 
3183  if (m_scene.PhysicsScene.SitAvatar(part.PhysActor, AbsolutePosition, CameraPosition, offset, new Vector3(0.35f, 0, 0.65f), PhysicsSitResponse) != 0)
3184  {
3185  return true;
3186  }
3187 
3188  return false;
3189  }
3190 
3191 
3192  private bool CanEnterLandPosition(Vector3 testPos)
3193  {
3194  ILandObject land = m_scene.LandChannel.GetLandObject(testPos.X, testPos.Y);
3195 
3196  if (land == null || land.LandData.Name == "NO_LAND")
3197  return true;
3198 
3199  return land.CanBeOnThisLand(UUID,testPos.Z);
3200  }
3201 
3202  // status
3203  // < 0 ignore
3204  // 0 bad sit spot
3205  public void PhysicsSitResponse(int status, uint partID, Vector3 offset, Quaternion Orientation)
3206  {
3207  if (status < 0)
3208  return;
3209 
3210  if (status == 0)
3211  {
3212  ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot.");
3213  return;
3214  }
3215 
3216  SceneObjectPart part = m_scene.GetSceneObjectPart(partID);
3217  if (part == null)
3218  return;
3219 
3220  Vector3 targetPos = part.GetWorldPosition() + offset * part.GetWorldRotation();
3221  if(!CanEnterLandPosition(targetPos))
3222  {
3223  ControllingClient.SendAlertMessage(" Sit position on restricted land, try another spot");
3224  return;
3225  }
3226 
3227  RemoveFromPhysicalScene();
3228 
3229  if (MovingToTarget)
3230  ResetMoveToTarget();
3231 
3232  Velocity = Vector3.Zero;
3233  m_AngularVelocity = Vector3.Zero;
3234 
3235  Vector3 cameraAtOffset = part.GetCameraAtOffset();
3236  Vector3 cameraEyeOffset = part.GetCameraEyeOffset();
3237  bool forceMouselook = part.GetForceMouselook();
3238 
3239  m_bodyRot = Orientation;
3240 
3241  if (!part.IsRoot)
3242  {
3243  Orientation = part.RotationOffset * Orientation;
3244  offset = offset * part.RotationOffset;
3245  offset += part.OffsetPosition;
3246 
3247  if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
3248  {
3249  CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
3250  cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
3251  }
3252  else
3253  {
3254  cameraAtOffset = cameraAtOffset * part.RotationOffset;
3255  cameraAtOffset += part.OffsetPosition;
3256  cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
3257  cameraEyeOffset += part.OffsetPosition;
3258  }
3259  }
3260 
3261  m_pos = offset;
3262 
3263  ControllingClient.SendSitResponse(
3264  part.ParentGroup.UUID, offset, Orientation, true, cameraAtOffset, cameraEyeOffset, forceMouselook);
3265 
3266 
3267  m_requestedSitTargetID = 0;
3268  part.AddSittingAvatar(this);
3269 
3270  ParentPart = part;
3271  ParentID = part.LocalId;
3272 
3273  SendAvatarDataToAllAgents();
3274 
3275  if (status == 3)
3276  sitAnimation = "SIT_GROUND";
3277  else
3278  sitAnimation = "SIT";
3279 
3280  Animator.SetMovementAnimations("SIT");
3281  part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
3282  }
3283 
3284  public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
3285  {
3286  if (IsChildAgent)
3287  return;
3288 
3289  SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
3290 
3291  if (part != null)
3292  {
3293  if (part.ParentGroup.IsAttachment)
3294  {
3295  m_log.WarnFormat(
3296  "[SCENE PRESENCE]: Avatar {0} tried to sit on part {1} from object {2} in {3} but this is an attachment for avatar id {4}",
3297  Name, part.Name, part.ParentGroup.Name, Scene.Name, part.ParentGroup.AttachedAvatar);
3298 
3299  return;
3300  }
3301 
3302  if (part.SitTargetAvatar == UUID)
3303  {
3304  Vector3 sitTargetPos = part.SitTargetPosition;
3305  Quaternion sitTargetOrient = part.SitTargetOrientation;
3306 
3307 // m_log.DebugFormat(
3308 // "[SCENE PRESENCE]: Sitting {0} at sit target {1}, {2} on {3} {4}",
3309 // Name, sitTargetPos, sitTargetOrient, part.Name, part.LocalId);
3310 
3311  double x, y, z, m;
3312  Vector3 sitOffset;
3313  Quaternion r = sitTargetOrient;
3314 
3315  if(LegacySitOffsets)
3316  {
3317  double m1,m2;
3318 
3319  m1 = r.X * r.X + r.Y * r.Y;
3320  m2 = r.Z * r.Z + r.W * r.W;
3321 
3322  // Rotate the vector <0, 0, 1>
3323  x = 2 * (r.X * r.Z + r.Y * r.W);
3324  y = 2 * (-r.X * r.W + r.Y * r.Z);
3325  z = m2 - m1;
3326 
3327  // Set m to be the square of the norm of r.
3328  m = m1 + m2;
3329 
3330  // This constant is emperically determined to be what is used in SL.
3331  // See also http://opensimulator.org/mantis/view.php?id=7096
3332  double offset = 0.05;
3333 
3334  // Normally m will be ~ 1, but if someone passed a handcrafted quaternion
3335  // to llSitTarget with values so small that squaring them is rounded off
3336  // to zero, then m could be zero. The result of this floating point
3337  // round off error (causing us to skip this impossible normalization)
3338  // is only 5 cm.
3339  if (m > 0.000001)
3340  {
3341  offset /= m;
3342  }
3343 
3344  Vector3 up = new Vector3((float)x, (float)y, (float)z);
3345  sitOffset = up * (float)offset;
3346  }
3347  else
3348  {
3349  m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
3350 
3351  if (Math.Abs(1.0 - m) > 0.000001)
3352  {
3353  if(m != 0)
3354  {
3355  m = 1.0 / Math.Sqrt(m);
3356  r.X *= (float)m;
3357  r.Y *= (float)m;
3358  r.Z *= (float)m;
3359  r.W *= (float)m;
3360  }
3361  else
3362  {
3363  r.X = 0.0f;
3364  r.Y = 0.0f;
3365  r.Z = 0.0f;
3366  r.W = 1.0f;
3367  m = 1.0f;
3368  }
3369  }
3370 
3371  x = 2 * (r.X * r.Z + r.Y * r.W);
3372  y = 2 * (-r.X * r.W + r.Y * r.Z);
3373  z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
3374  Vector3 up = new Vector3((float)x, (float)y, (float)z);
3375  sitOffset = up * Appearance.AvatarHeight * 0.02638f;
3376  }
3377 
3378  Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
3379  Quaternion newRot;
3380 
3381  if (part.IsRoot)
3382  {
3383  newRot = sitTargetOrient;
3384  }
3385  else
3386  {
3387  newPos = newPos * part.RotationOffset;
3388  newRot = part.RotationOffset * sitTargetOrient;
3389  }
3390 
3391  newPos += part.OffsetPosition;
3392 
3393  m_pos = newPos;
3394  Rotation = newRot;
3395 
3396 // ParentPosition = part.AbsolutePosition;
3397  }
3398  else
3399  {
3400  // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
3401  // being sat upon.
3402  m_pos -= part.GroupPosition;
3403 
3404 // ParentPosition = part.AbsolutePosition;
3405 
3406 // m_log.DebugFormat(
3407 // "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
3408 // Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
3409  }
3410 
3411  part.AddSittingAvatar(this);
3412  ParentPart = part;
3413  ParentID = m_requestedSitTargetID;
3414  m_AngularVelocity = Vector3.Zero;
3415  Velocity = Vector3.Zero;
3416  RemoveFromPhysicalScene();
3417 
3418  m_requestedSitTargetID = 0;
3419 
3420  SendAvatarDataToAllAgents();
3421 
3422  sitAnimation = "SIT";
3423  if (!String.IsNullOrEmpty(part.SitAnimation))
3424  {
3425  sitAnimation = part.SitAnimation;
3426  }
3427 // Animator.TrySetMovementAnimation(sitAnimation);
3428  Animator.SetMovementAnimations("SIT");
3429  TriggerScenePresenceUpdated();
3430  }
3431  }
3432 
3433  public void HandleAgentSitOnGround()
3434  {
3435  if (IsChildAgent)
3436  return;
3437 
3438 // m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
3439  m_AngularVelocity = Vector3.Zero;
3440  sitAnimation = "SIT_GROUND_CONSTRAINED";
3441 // Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
3442 // TriggerScenePresenceUpdated();
3443  SitGround = true;
3444  RemoveFromPhysicalScene();
3445 
3446  Animator.SetMovementAnimations("SITGROUND");
3447  TriggerScenePresenceUpdated();
3448  }
3449 
3454  public void HandleSetAlwaysRun(IClientAPI remoteClient, bool pSetAlwaysRun)
3455  {
3456  SetAlwaysRun = pSetAlwaysRun;
3457  }
3458 
3459  public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
3460  {
3461  Animator.AddAnimation(animID, UUID.Zero);
3462  TriggerScenePresenceUpdated();
3463  }
3464 
3465  public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
3466  {
3467  Animator.RemoveAnimation(animID, false);
3468  TriggerScenePresenceUpdated();
3469  }
3470 
3471  public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
3472  {
3473  Animator.avnChangeAnim(animID, addRemove, sendPack);
3474  }
3475 
3476 
3477 
3484  public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1, bool breaking = false)
3485  {
3486  // m_log.DebugFormat(
3487  // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
3488  // vec, Rotation, thisAddSpeedModifier, Name);
3489 
3490  // rotate from avatar coord space to world
3491  // for now all controls assume this is only a rotation around Z
3492  // if not all checks below need to be done before this rotation
3493  Vector3 direc = vec * Rotation;
3494  direc.Normalize();
3495 
3496  // mouse look situation ?
3497  if ((vec.Z == 0f) && !Flying)
3498  direc.Z = 0f; // Prevent camera WASD up.
3499 
3500  // odd rescalings
3501  direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier;
3502 
3503  // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
3504 
3505  if (Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling
3506  && (PhysicsActor == null || !PhysicsActor.PIDHoverActive))
3507  {
3508  if (breaking)
3509  direc.Z = -9999f; //hack to tell physics to stop on Z
3510  else
3511  direc = Vector3.Zero;
3512  }
3513  else if (Flying)
3514  {
3515  if (IsColliding && direc.Z < 0)
3516  // landing situation, prevent avatar moving or it may fail to land
3517  // animator will handle this condition and do the land
3518  direc = Vector3.Zero;
3519  else
3520  direc *= 4.0f;
3521  }
3522  else if (IsColliding)
3523  {
3524  if (direc.Z > 2.0f) // reinforce jumps
3525  {
3526  direc.Z *= 2.6f;
3527  }
3528  else if (direc.Z < 0) // on a surface moving down (pg down) only changes animation
3529  direc.Z = 0;
3530  }
3531 
3532  // m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name);
3533 
3534  m_forceToApply = direc;
3535  Animator.UpdateMovementAnimations();
3536  }
3537 
3538  #endregion
3539 
3540  #region Overridden Methods
3541 
3542  const float ROTATION_TOLERANCE = 0.01f;
3543  const float VELOCITY_TOLERANCE = 0.1f;
3544  const float LOWVELOCITYSQ = 0.1f;
3545  const float POSITION_LARGETOLERANCE = 5f;
3546  const float POSITION_SMALLTOLERANCE = 0.05f;
3547 
3548  public override void Update()
3549  {
3550  if(IsChildAgent || IsDeleted)
3551  return;
3552 
3553  CheckForBorderCrossing();
3554 
3555  if (IsInTransit || IsLoggingIn)
3556  return;
3557 
3558  if(MovingToTarget)
3559  {
3560  Vector3 control = Vector3.Zero;
3561  if(HandleMoveToTargetUpdate(1f, ref control))
3562  AddNewMovement(control);
3563  }
3564 
3565  if (Appearance.AvatarSize != m_lastSize)
3566  SendAvatarDataToAllAgents();
3567 
3568  // Send terse position update if not sitting and position, velocity, or rotation
3569  // has changed significantly from last sent update
3570  if (!IsSatOnObject && (
3571  !Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)
3572  || !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE)
3573  || !m_pos.ApproxEquals(m_lastPosition, POSITION_LARGETOLERANCE)
3574  // if velocity is zero and it wasn't zero last time, send the update
3575  || (Velocity == Vector3.Zero && m_lastVelocity != Vector3.Zero)
3576  // if position has moved just a little and velocity is very low, send the update
3577  || (!m_pos.ApproxEquals(m_lastPosition, POSITION_SMALLTOLERANCE) && Velocity.LengthSquared() < LOWVELOCITYSQ )
3578  ) )
3579  {
3580 /*
3581  if (!IsSatOnObject)
3582  {
3583  // this does need to be more complex later
3584  Vector3 vel = Velocity;
3585  Vector3 dpos = m_pos - m_lastPosition;
3586  if( Math.Abs(vel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE ||
3587  Math.Abs(vel.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE ||
3588  Math.Abs(vel.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE ||
3589 
3590  Math.Abs(m_bodyRot.X - m_lastRotation.X) > ROTATION_TOLERANCE ||
3591  Math.Abs(m_bodyRot.Y - m_lastRotation.Y) > ROTATION_TOLERANCE ||
3592  Math.Abs(m_bodyRot.Z - m_lastRotation.Z) > ROTATION_TOLERANCE ||
3593 
3594  Math.Abs(dpos.X) > POSITION_LARGETOLERANCE ||
3595  Math.Abs(dpos.Y) > POSITION_LARGETOLERANCE ||
3596  Math.Abs(dpos.Z) > POSITION_LARGETOLERANCE ||
3597 
3598  ( (Math.Abs(dpos.X) > POSITION_SMALLTOLERANCE ||
3599  Math.Abs(dpos.Y) > POSITION_SMALLTOLERANCE ||
3600  Math.Abs(dpos.Z) > POSITION_SMALLTOLERANCE)
3601  && vel.LengthSquared() < LOWVELOCITYSQ
3602  ))
3603  {
3604 */
3605  SendTerseUpdateToAllClients();
3606 // }
3607  }
3608  CheckForSignificantMovement();
3609  }
3610 
3611  #endregion
3612 
3613  #region Update Client(s)
3614 
3615  public void SendUpdateToAgent(ScenePresence p)
3616  {
3617  IClientAPI remoteClient = p.ControllingClient;
3618 
3619  if (remoteClient.IsActive)
3620  {
3621  //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3622  remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3623  m_scene.StatsReporter.AddAgentUpdates(1);
3624  }
3625  }
3626 
3627  public void SendFullUpdateToClient(IClientAPI remoteClient)
3628  {
3629  if (remoteClient.IsActive)
3630  {
3631  //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3632  remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3633  m_scene.StatsReporter.AddAgentUpdates(1);
3634  }
3635  }
3636 
3637  // this is diferente from SendTerseUpdateToClient
3638  // this sends bypassing entities updates
3639  public void SendAgentTerseUpdate(ISceneEntity p)
3640  {
3641  ControllingClient.SendAgentTerseUpdate(p);
3642  }
3643 
3649  public void SendTerseUpdateToClient(IClientAPI remoteClient)
3650  {
3651  // If the client is inactive, it's getting its updates from another
3652  // server.
3653  if (remoteClient.IsActive)
3654  {
3655  //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3656  remoteClient.SendEntityUpdate(
3657  this,
3658  PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3659  | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3660 
3661  m_scene.StatsReporter.AddAgentUpdates(1);
3662  }
3663  }
3664 
3665  public void SendTerseUpdateToAgent(ScenePresence p)
3666  {
3667  IClientAPI remoteClient = p.ControllingClient;
3668 
3669  if (!remoteClient.IsActive)
3670  return;
3671 
3672  if (ParcelHideThisAvatar && p.currentParcelUUID != currentParcelUUID && p.GodLevel < 200)
3673  return;
3674 
3675  //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3676  remoteClient.SendEntityUpdate(
3677  this,
3678  PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3679  | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3680 
3681  m_scene.StatsReporter.AddAgentUpdates(1);
3682  }
3683 
3684  public void SendTerseUpdateToAgentNF(ScenePresence p)
3685  {
3686  IClientAPI remoteClient = p.ControllingClient;
3687  if (remoteClient.IsActive)
3688  {
3689  //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3690  remoteClient.SendEntityUpdate(this,
3691  PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3692  | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3693  m_scene.StatsReporter.AddAgentUpdates(1);
3694  }
3695  }
3696 
3700  public void SendTerseUpdateToAllClients()
3701  {
3702  m_scene.ForEachScenePresence(SendTerseUpdateToAgent);
3703  // Update the "last" values
3704  m_lastPosition = m_pos;
3705  m_lastRotation = m_bodyRot;
3706  m_lastVelocity = Velocity;
3707  TriggerScenePresenceUpdated();
3708  }
3709 
3710  public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
3711  {
3712  SendCoarseLocationsMethod d = m_sendCoarseLocationsMethod;
3713  if (d != null)
3714  {
3715  d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs);
3716  }
3717  }
3718 
3719  public void SetSendCoarseLocationMethod(SendCoarseLocationsMethod d)
3720  {
3721  if (d != null)
3722  m_sendCoarseLocationsMethod = d;
3723  }
3724 
3725  public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
3726  {
3727  ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations);
3728  }
3729 
3730  public void SendInitialDataToMe()
3731  {
3732  // Send all scene object to the new client
3733  Util.FireAndForget(delegate
3734  {
3735  // we created a new ScenePresence (a new child agent) in a fresh region.
3736  // Request info about all the (root) agents in this region
3737  // Note: This won't send data *to* other clients in that region (children don't send)
3738  if (m_teleportFlags <= 0)
3739  {
3740  Scene.SendLayerData(ControllingClient);
3741 
3742  ILandChannel landch = m_scene.LandChannel;
3743  if (landch != null)
3744  {
3745  landch.sendClientInitialLandInfo(ControllingClient);
3746  }
3747  }
3748 
3749  SendOtherAgentsAvatarFullToMe();
3750  EntityBase[] entities = Scene.Entities.GetEntities();
3751  foreach (EntityBase e in entities)
3752  {
3753  if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment)
3754  ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
3755  }
3756  });
3757  }
3758 
3763  public void SendOtherAgentsAvatarFullToMe()
3764  {
3765  int count = 0;
3766  m_scene.ForEachRootScenePresence(delegate(ScenePresence p)
3767  {
3768  // only send information about other root agents
3769  if (p.UUID == UUID)
3770  return;
3771 
3772  // get the avatar, then a kill if can't see it
3773  p.SendInitialAvatarDataToAgent(this);
3774 
3775  if (p.ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && GodLevel < 200)
3776  return;
3777 
3778  p.SendAppearanceToAgentNF(this);
3779  p.SendAnimPackToAgentNF(this);
3780  p.SendAttachmentsToAgentNF(this);
3781  count++;
3782  });
3783 
3784  m_scene.StatsReporter.AddAgentUpdates(count);
3785  }
3786 
3791  public void SendAvatarDataToAllAgents()
3792  {
3793  //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID);
3794  // only send update from root agents to other clients; children are only "listening posts"
3795  if (IsChildAgent)
3796  {
3797  m_log.WarnFormat(
3798  "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}",
3799  Name, Scene.RegionInfo.RegionName);
3800  return;
3801  }
3802 
3803  m_lastSize = Appearance.AvatarSize;
3804  int count = 0;
3805 
3806  m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3807  {
3808  SendAvatarDataToAgent(scenePresence);
3809  count++;
3810  });
3811 
3812  m_scene.StatsReporter.AddAgentUpdates(count);
3813  }
3814  // sends avatar object to all clients so they cross it into region
3815  // then sends kills to hide
3816  public void SendInitialAvatarDataToAllAgents(List<ScenePresence> presences)
3817  {
3818  m_lastSize = Appearance.AvatarSize;
3819  int count = 0;
3820  foreach (ScenePresence p in presences)
3821  {
3822  p.ControllingClient.SendAvatarDataImmediate(this);
3823  if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3824  // either just kill the object
3825  // p.ControllingClient.SendKillObject(new List<uint> {LocalId});
3826  // or also attachments viewer may still know about
3827  SendKillTo(p);
3828  count++;
3829  }
3830  m_scene.StatsReporter.AddAgentUpdates(count);
3831  }
3832 
3833  public void SendInitialAvatarDataToAgent(ScenePresence p)
3834  {
3835  p.ControllingClient.SendAvatarDataImmediate(this);
3836  if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3837  // either just kill the object
3838  // p.ControllingClient.SendKillObject(new List<uint> {LocalId});
3839  // or also attachments viewer may still know about
3840  SendKillTo(p);
3841  }
3842 
3847  public void SendAvatarDataToAgent(ScenePresence avatar)
3848  {
3849  //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
3850  if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3851  return;
3852  avatar.ControllingClient.SendAvatarDataImmediate(this);
3853  }
3854 
3855  public void SendAvatarDataToAgentNF(ScenePresence avatar)
3856  {
3857  avatar.ControllingClient.SendAvatarDataImmediate(this);
3858  }
3859 
3864  public void SendAppearanceToAllOtherAgents()
3865  {
3866  // m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID);
3867 
3868  // only send update from root agents to other clients; children are only "listening posts"
3869  if (IsChildAgent)
3870  {
3871  m_log.WarnFormat(
3872  "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}",
3873  Name, Scene.RegionInfo.RegionName);
3874 
3875  return;
3876  }
3877 
3878  int count = 0;
3879  m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3880  {
3881  // only send information to other root agents
3882  if (scenePresence.UUID == UUID)
3883  return;
3884 
3885  SendAppearanceToAgent(scenePresence);
3886  count++;
3887  });
3888  m_scene.StatsReporter.AddAgentUpdates(count);
3889  }
3890 
3891  public void SendAppearanceToAgent(ScenePresence avatar)
3892  {
3893  // m_log.DebugFormat(
3894  // "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID);
3895  if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3896  return;
3897  SendAppearanceToAgentNF(avatar);
3898  }
3899 
3900  public void SendAppearanceToAgentNF(ScenePresence avatar)
3901  {
3902  avatar.ControllingClient.SendAppearance(
3903  UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
3904  }
3905 
3906  public void SendAnimPackToAgent(ScenePresence p)
3907  {
3908  if (IsChildAgent || Animator == null)
3909  return;
3910 
3911  if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3912  return;
3913 
3914  Animator.SendAnimPackToClient(p.ControllingClient);
3915  }
3916 
3917  public void SendAnimPackToAgent(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs)
3918  {
3919  if (IsChildAgent)
3920  return;
3921 
3922  if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3923  return;
3924 
3925  p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3926  }
3927 
3928  public void SendAnimPackToAgentNF(ScenePresence p)
3929  {
3930  if (IsChildAgent || Animator == null)
3931  return;
3932  Animator.SendAnimPackToClient(p.ControllingClient);
3933  }
3934 
3935  public void SendAnimPackToAgentNF(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs)
3936  {
3937  p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3938  }
3939 
3940  public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
3941  {
3942  if (IsChildAgent)
3943  return;
3944 
3945  m_scene.ForEachScenePresence(delegate(ScenePresence p)
3946  {
3947  if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3948  return;
3949  p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3950  });
3951  }
3952 
3953  #endregion
3954 
3955  #region Significant Movement Method
3956 
3957  private void checkRePrioritization()
3958  {
3959  if(IsDeleted || !ControllingClient.IsActive)
3960  return;
3961 
3962  if(m_reprioritizationBusy)
3963  return;
3964 
3965  int tdiff = Util.EnvironmentTickCountSubtract(m_reprioritizationLastTime);
3966  if(tdiff < Scene.ReprioritizationInterval)
3967  return;
3968  // priority uses avatar position
3969  Vector3 pos = AbsolutePosition;
3970  Vector3 diff = pos - m_reprioritizationLastPosition;
3971  float limit;
3972  if(IsChildAgent)
3973  limit = (float)Scene.ChildReprioritizationDistance;
3974  else
3975  limit = (float)Scene.RootReprioritizationDistance;
3976 
3977  limit *= limit;
3978  if (diff.LengthSquared() < limit)
3979  return;
3980 
3981  m_reprioritizationBusy = true;
3982  m_reprioritizationLastPosition = pos;
3983 
3984  Util.FireAndForget(
3985  o =>
3986  {
3987  ControllingClient.ReprioritizeUpdates();
3988  m_reprioritizationLastTime = Util.EnvironmentTickCount();
3989  m_reprioritizationBusy = false;
3990  }, null, "ScenePresence.Reprioritization");
3991  }
3995  protected void CheckForSignificantMovement()
3996  {
3997  Vector3 pos = AbsolutePosition;
3998 
3999  Vector3 diff = pos - posLastMove;
4000  if (diff.LengthSquared() > MOVEMENT)
4001  {
4002  posLastMove = pos;
4003  m_scene.EventManager.TriggerOnClientMovement(this);
4004  }
4005 
4006  diff = pos - posLastSignificantMove;
4007  if (diff.LengthSquared() > SIGNIFICANT_MOVEMENT)
4008  {
4009  posLastSignificantMove = pos;
4010  m_scene.EventManager.TriggerSignificantClientMovement(this);
4011  }
4012 
4013  // updates priority recalc
4014  checkRePrioritization();
4015 
4016  if(childUpdatesBusy)
4017  return;
4018 
4019  //possible KnownRegionHandles always contains current region and this check is not needed
4020  int minhandles = 0;
4021  if(KnownRegionHandles.Contains(RegionHandle))
4022  minhandles++;
4023 
4024  if(KnownRegionHandles.Count > minhandles)
4025  {
4026  int tdiff = Util.EnvironmentTickCountSubtract(lastChildUpdatesTime);
4027  if(tdiff > CHILDUPDATES_TIME)
4028  {
4029  diff = pos - m_lastChildAgentUpdatePosition;
4030  if (diff.LengthSquared() > CHILDUPDATES_MOVEMENT)
4031  {
4032  childUpdatesBusy = true;
4033  m_lastChildAgentUpdatePosition = pos;
4034 // m_lastChildAgentUpdateCamPosition = CameraPosition;
4035 
4036  AgentPosition agentpos = new AgentPosition();
4037  agentpos.AgentID = new UUID(UUID.Guid);
4038  agentpos.SessionID = ControllingClient.SessionId;
4039  agentpos.Size = Appearance.AvatarSize;
4040  agentpos.Center = CameraPosition;
4041  agentpos.Far = DrawDistance;
4042  agentpos.Position = AbsolutePosition;
4043  agentpos.Velocity = Velocity;
4044  agentpos.RegionHandle = RegionHandle;
4045  agentpos.Throttles = ControllingClient.GetThrottlesPacked(1);
4046 
4047  // Let's get this out of the update loop
4048  Util.FireAndForget(
4049  o =>
4050  {
4051  m_scene.SendOutChildAgentUpdates(agentpos, this);
4052  lastChildUpdatesTime = Util.EnvironmentTickCount();
4053  childUpdatesBusy = false;
4054  }, null, "ScenePresence.SendOutChildAgentUpdates");
4055  }
4056  }
4057  }
4058  }
4059 
4060  #endregion
4061 
4062  #region Border Crossing Methods
4063 
4070  protected void CheckForBorderCrossing()
4071  {
4072  // Check that we we are not a child
4073  if (IsChildAgent || IsInTransit)
4074  return;
4075 
4076  // If we don't have a PhysActor, we can't cross anyway
4077  // Also don't do this while sat, sitting avatars cross with the
4078  // object they sit on. ParentUUID denoted a pending sit, don't
4079  // interfere with it.
4080  if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero)
4081  return;
4082 
4083  Vector3 pos2 = AbsolutePosition;
4084  Vector3 vel = Velocity;
4085 
4086  float timeStep = 0.1f;
4087  pos2.X += vel.X * timeStep;
4088  pos2.Y += vel.Y * timeStep;
4089  pos2.Z += vel.Z * timeStep;
4090 
4091 // m_log.DebugFormat(
4092 // "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
4093 // pos2, Name, Scene.Name);
4094 
4095  if (Scene.PositionIsInCurrentRegion(pos2))
4096  return;
4097 
4098  if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
4099  {
4100  // we don't have entity transfer module
4101  Vector3 pos = AbsolutePosition;
4102  float px = pos.X;
4103  if (px < 0)
4104  pos.X += Velocity.X * 2;
4105  else if (px > m_scene.RegionInfo.RegionSizeX)
4106  pos.X -= Velocity.X * 2;
4107 
4108  float py = pos.Y;
4109  if (py < 0)
4110  pos.Y += Velocity.Y * 2;
4111  else if (py > m_scene.RegionInfo.RegionSizeY)
4112  pos.Y -= Velocity.Y * 2;
4113 
4114  Velocity = Vector3.Zero;
4115  AbsolutePosition = pos;
4116  }
4117  }
4118 
4119  public void CrossToNewRegionFail()
4120  {
4121  if (m_requestedSitTargetUUID == UUID.Zero)
4122  {
4123  bool isFlying = Flying;
4124  RemoveFromPhysicalScene();
4125 
4126  Vector3 pos = AbsolutePosition;
4127  float px = pos.X;
4128  if (px < 0)
4129  pos.X += Velocity.X * 2;
4130  else if (px > m_scene.RegionInfo.RegionSizeX)
4131  pos.X -= Velocity.X * 2;
4132 
4133  float py = pos.Y;
4134  if (py < 0)
4135  pos.Y += Velocity.Y * 2;
4136  else if (py > m_scene.RegionInfo.RegionSizeY)
4137  pos.Y -= Velocity.Y * 2;
4138 
4139  Velocity = Vector3.Zero;
4140  AbsolutePosition = pos;
4141 
4142  AddToPhysicalScene(isFlying);
4143  }
4144  }
4145 
4152  protected bool CrossToNewRegion()
4153  {
4154  bool result = false;
4155 // parcelRegionCross(false);
4156  try
4157  {
4158  result = m_scene.CrossAgentToNewRegion(this, Flying);
4159  }
4160  catch
4161  {
4162 // result = m_scene.CrossAgentToNewRegion(this, false);
4163  return false;
4164  }
4165  // if(!result)
4166  // parcelRegionCross(true);
4167 
4168  return result;
4169 
4170  }
4171 
4172  /* useless. Either use MakeChild or delete the presence
4173  public void Reset()
4174  {
4175  // m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
4176 
4177  // Put the child agent back at the center
4178  AbsolutePosition
4179  = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
4180 
4181  Animator.ResetAnimations();
4182  }
4183  */
4191  public void CloseChildAgents(bool logout, ulong newRegionHandle, int newRegionSizeX, int newRegionSizeY)
4192  {
4193  uint newRegionX, newRegionY;
4194  List<ulong> byebyeRegions = new List<ulong>();
4195  List<ulong> knownRegions = KnownRegionHandles;
4196  m_log.DebugFormat(
4197  "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}",
4198  knownRegions.Count, Scene.RegionInfo.RegionName);
4199  //DumpKnownRegions();
4200 
4201  Util.RegionHandleToRegionLoc(newRegionHandle, out newRegionX, out newRegionY);
4202 
4203  uint x, y;
4204  spRegionSizeInfo regInfo;
4205 
4206  // this should not be here
4207  IEventQueue eventQueue = Scene.RequestModuleInterface<IEventQueue>();
4208 
4209  foreach (ulong handle in knownRegions)
4210  {
4211  // Don't close the agent on this region yet
4212  if (handle != Scene.RegionInfo.RegionHandle)
4213  {
4214  if (logout)
4215  byebyeRegions.Add(handle);
4216  else
4217  {
4218  Util.RegionHandleToRegionLoc(handle, out x, out y);
4219  if (m_knownChildRegionsSizeInfo.TryGetValue(handle, out regInfo))
4220  {
4221 
4222  // m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
4223  // m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
4224  if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY,
4225  regInfo.sizeX, regInfo.sizeY, newRegionSizeX, newRegionSizeY))
4226  {
4227  byebyeRegions.Add(handle);
4228  // this should not be here
4229 // if(eventQueue != null)
4231  }
4232  }
4233  else
4234  {
4235  if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY,
4236  (int)Constants.RegionSize, (int)Constants.RegionSize, newRegionSizeX, newRegionSizeY))
4237  {
4238  byebyeRegions.Add(handle);
4239  // this should not be here
4240 // if(eventQueue != null)
4241 // eventQueue.DisableSimulator(handle,UUID);
4242  }
4243  }
4244  }
4245  }
4246  }
4247 
4248  if (byebyeRegions.Count > 0)
4249  {
4250  m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
4251 
4252  AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID);
4253  string auth = string.Empty;
4254  if (acd != null)
4255  auth = acd.SessionID.ToString();
4256  m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
4257  }
4258 
4259  foreach (ulong handle in byebyeRegions)
4260  {
4261  RemoveNeighbourRegion(handle);
4262  Scene.CapsModule.DropChildSeed(UUID, handle);
4263  }
4264  }
4265 
4266  #endregion
4267 
4272  public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
4273  {
4274  int oldgodlevel = GodLevel;
4275 
4276  if (godStatus)
4277  {
4278  // For now, assign god level 200 to anyone
4279  // who is granted god powers, but has no god level set.
4280  //
4281  UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, agentID);
4282  if (account != null)
4283  {
4284  if (account.UserLevel > 0)
4285  GodLevel = account.UserLevel;
4286  else
4287  GodLevel = 200;
4288  }
4289  }
4290  else
4291  {
4292  GodLevel = 0;
4293  }
4294 
4295  ControllingClient.SendAdminResponse(token, (uint)GodLevel);
4296 
4297  if(oldgodlevel != GodLevel)
4298  parcelGodCheck(m_currentParcelUUID, GodLevel >= 200);
4299  }
4300 
4301  #region Child Agent Updates
4302 
4303  public void UpdateChildAgent(AgentData cAgentData)
4304  {
4305 // m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
4306  if (!IsChildAgent)
4307  return;
4308 
4309  CopyFrom(cAgentData);
4310 
4311  }
4312 
4313  private static Vector3 marker = new Vector3(-1f, -1f, -1f);
4314 
4315  private void RaiseUpdateThrottles()
4316  {
4317  m_scene.EventManager.TriggerThrottleUpdate(this);
4318  }
4319 
4324  public void UpdateChildAgent(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
4325  {
4326  if (!IsChildAgent)
4327  return;
4328 
4329  RegionHandle = cAgentData.RegionHandle;
4330 
4331  //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
4332  int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize;
4333  int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize;
4334 
4335  Vector3 offset = new Vector3(shiftx, shifty, 0f);
4336 
4337  DrawDistance = cAgentData.Far;
4338 
4339  if (cAgentData.Position != marker) // UGH!!
4340  m_pos = cAgentData.Position + offset;
4341 
4342  CameraPosition = cAgentData.Center + offset;
4343 
4344  if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0)
4345  {
4346  // some scaling factor
4347  float x = m_pos.X;
4348  if (x > m_scene.RegionInfo.RegionSizeX)
4349  x -= m_scene.RegionInfo.RegionSizeX;
4350  float y = m_pos.Y;
4351  if (y > m_scene.RegionInfo.RegionSizeY)
4352  y -= m_scene.RegionInfo.RegionSizeY;
4353 
4354  x = x * x + y * y;
4355 
4356  const float distScale = 0.4f / Constants.RegionSize / Constants.RegionSize;
4357  float factor = 1.0f - distScale * x;
4358  if (factor < 0.2f)
4359  factor = 0.2f;
4360 
4361  ControllingClient.SetChildAgentThrottle(cAgentData.Throttles,factor);
4362  }
4363 
4364  if(cAgentData.ChildrenCapSeeds != null && cAgentData.ChildrenCapSeeds.Count >0)
4365  {
4366  if (Scene.CapsModule != null)
4367  {
4368  Scene.CapsModule.SetChildrenSeed(UUID, cAgentData.ChildrenCapSeeds);
4369  }
4370 
4371  KnownRegions = cAgentData.ChildrenCapSeeds;
4372  }
4373 
4374  //cAgentData.AVHeight;
4375  //m_velocity = cAgentData.Velocity;
4376  checkRePrioritization();
4377  }
4378 
4379  public void CopyTo(AgentData cAgent)
4380  {
4381  cAgent.CallbackURI = m_callbackURI;
4382 
4383  cAgent.AgentID = UUID;
4384  cAgent.RegionID = Scene.RegionInfo.RegionID;
4385  cAgent.SessionID = ControllingClient.SessionId;
4386 
4387  cAgent.Position = AbsolutePosition;
4388  cAgent.Velocity = m_velocity;
4389  cAgent.Center = CameraPosition;
4390  cAgent.AtAxis = CameraAtAxis;
4391  cAgent.LeftAxis = CameraLeftAxis;
4392  cAgent.UpAxis = CameraUpAxis;
4393 
4394  cAgent.Far = DrawDistance;
4395 
4396  // Throttles
4397  cAgent.Throttles = ControllingClient.GetThrottlesPacked(1);
4398 
4399  cAgent.HeadRotation = m_headrotation;
4400  cAgent.BodyRotation = Rotation;
4401  cAgent.ControlFlags = (uint)m_AgentControlFlags;
4402 
4403  if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
4404  cAgent.GodLevel = (byte)GodLevel;
4405  else
4406  cAgent.GodLevel = (byte) 0;
4407 
4408  cAgent.AlwaysRun = SetAlwaysRun;
4409 
4410  // make clear we want the all thing
4411  cAgent.Appearance = new AvatarAppearance(Appearance,true,true);
4412 
4413  cAgent.ParentPart = ParentUUID;
4414  cAgent.SitOffset = PrevSitOffset;
4415 
4416  lock (scriptedcontrols)
4417  {
4418  ControllerData[] controls = new ControllerData[scriptedcontrols.Count];
4419  int i = 0;
4420 
4421  foreach (ScriptControllers c in scriptedcontrols.Values)
4422  {
4423  controls[i++] = new ControllerData(c.objectID, c.itemID, (uint)c.ignoreControls, (uint)c.eventControls);
4424  }
4425  cAgent.Controllers = controls;
4426  }
4427 
4428  // Animations
4429  try
4430  {
4431  cAgent.Anims = Animator.Animations.ToArray();
4432  }
4433  catch { }
4434  cAgent.DefaultAnim = Animator.Animations.DefaultAnimation;
4435  cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation;
4436 
4437  cAgent.MovementAnimationOverRides = Overrides.CloneAOPairs();
4438 
4439  cAgent.MotionState = (byte)Animator.currentControlState;
4440 
4441  if (Scene.AttachmentsModule != null)
4442  Scene.AttachmentsModule.CopyAttachments(this, cAgent);
4443  }
4444 
4445  private void CopyFrom(AgentData cAgent)
4446  {
4447  m_callbackURI = cAgent.CallbackURI;
4448 // m_log.DebugFormat(
4449 // "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()",
4450 // Name, m_scene.RegionInfo.RegionName, m_callbackURI);
4451 
4452  m_pos = cAgent.Position;
4453  m_velocity = cAgent.Velocity;
4454  CameraPosition = cAgent.Center;
4455  CameraAtAxis = cAgent.AtAxis;
4456  CameraLeftAxis = cAgent.LeftAxis;
4457  CameraUpAxis = cAgent.UpAxis;
4458  ParentUUID = cAgent.ParentPart;
4459  PrevSitOffset = cAgent.SitOffset;
4460 
4461  // When we get to the point of re-computing neighbors everytime this
4462  // changes, then start using the agent's drawdistance rather than the
4463  // region's draw distance.
4464  DrawDistance = cAgent.Far;
4465  //DrawDistance = Scene.DefaultDrawDistance;
4466 
4467  if (cAgent.ChildrenCapSeeds != null && cAgent.ChildrenCapSeeds.Count > 0)
4468  {
4469  if (Scene.CapsModule != null)
4470  {
4471  Scene.CapsModule.SetChildrenSeed(UUID, cAgent.ChildrenCapSeeds);
4472  }
4473  KnownRegions = cAgent.ChildrenCapSeeds;
4474  }
4475 
4476  if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
4477  ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
4478 
4479  m_headrotation = cAgent.HeadRotation;
4480  Rotation = cAgent.BodyRotation;
4481  m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags;
4482 
4483  if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
4484  GodLevel = cAgent.GodLevel;
4485  SetAlwaysRun = cAgent.AlwaysRun;
4486 
4487 
4488  Appearance = new AvatarAppearance(cAgent.Appearance);
4489 /*
4490  bool isFlying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
4491 
4492  if (PhysicsActor != null)
4493  {
4494  RemoveFromPhysicalScene();
4495  AddToPhysicalScene(isFlying);
4496  }
4497 */
4498  try
4499  {
4500  lock (scriptedcontrols)
4501  {
4502  if (cAgent.Controllers != null)
4503  {
4504  scriptedcontrols.Clear();
4505 
4506  foreach (ControllerData c in cAgent.Controllers)
4507  {
4508  ScriptControllers sc = new ScriptControllers();
4509  sc.objectID = c.ObjectID;
4510  sc.itemID = c.ItemID;
4511  sc.ignoreControls = (ScriptControlled)c.IgnoreControls;
4512  sc.eventControls = (ScriptControlled)c.EventControls;
4513 
4514  scriptedcontrols[sc.itemID] = sc;
4515  }
4516  }
4517  }
4518  }
4519  catch { }
4520 
4521  Animator.ResetAnimations();
4522 
4523  Overrides.CopyAOPairsFrom(cAgent.MovementAnimationOverRides);
4524 
4525  // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object?
4526  if (cAgent.DefaultAnim != null)
4527  Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
4528  if (cAgent.AnimState != null)
4529  Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero);
4530  if (cAgent.Anims != null)
4531  Animator.Animations.FromArray(cAgent.Anims);
4532  if (cAgent.MotionState != 0)
4533  Animator.currentControlState = (ScenePresenceAnimator.motionControlStates) cAgent.MotionState;
4534 
4535  if (Scene.AttachmentsModule != null)
4536  Scene.AttachmentsModule.CopyAttachments(cAgent, this);
4537 
4538  lock (m_originRegionIDAccessLock)
4539  m_originRegionID = cAgent.RegionID;
4540  }
4541 
4542  public bool CopyAgent(out IAgentData agent)
4543  {
4544  agent = new CompleteAgentData();
4545  CopyTo((AgentData)agent);
4546  return true;
4547  }
4548 
4549  #endregion Child Agent Updates
4550 
4554  public void UpdateMovement()
4555  {
4556  if (IsInTransit)
4557  return;
4558  if (m_forceToApply.HasValue)
4559  {
4560  Vector3 force = m_forceToApply.Value;
4561 
4562  Velocity = force;
4563 
4564  m_forceToApply = null;
4565  TriggerScenePresenceUpdated();
4566  }
4567  }
4568 
4572  public void AddToPhysicalScene(bool isFlying)
4573  {
4574 // m_log.DebugFormat(
4575 // "[SCENE PRESENCE]: Adding physics actor for {0}, ifFlying = {1} in {2}",
4576 // Name, isFlying, Scene.RegionInfo.RegionName);
4577 
4578  if (PhysicsActor != null)
4579  {
4580  m_log.ErrorFormat(
4581  "[SCENE PRESENCE]: Adding physics actor for {0} to {1} but this scene presence already has a physics actor",
4582  Name, Scene.RegionInfo.RegionName);
4583  }
4584 
4585  if (Appearance.AvatarHeight == 0)
4586 // Appearance.SetHeight();
4587  Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f));
4588 
4589  PhysicsScene scene = m_scene.PhysicsScene;
4590  Vector3 pVec = AbsolutePosition;
4591 
4592  PhysicsActor = scene.AddAvatar(
4593  LocalId, Firstname + "." + Lastname, pVec,
4594  Appearance.AvatarBoxSize,Appearance.AvatarFeetOffset, isFlying);
4595  PhysicsActor.Orientation = m_bodyRot;
4596  //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
4597  PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
4598  PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
4599  PhysicsActor.SubscribeEvents(100);
4600  PhysicsActor.LocalID = LocalId;
4601  }
4602 
4603  private void OutOfBoundsCall(Vector3 pos)
4604  {
4605  //bool flying = Flying;
4606  //RemoveFromPhysicalScene();
4607 
4608  //AddToPhysicalScene(flying);
4609  if (ControllingClient != null)
4610  ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true);
4611  }
4612 
4613 
4625  public void PhysicsCollisionUpdate(EventArgs e)
4626  {
4627  if (IsChildAgent || Animator == null)
4628  return;
4629 
4630  if(IsInTransit)
4631  return;
4632  //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
4633  // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
4634  // as of this comment the interval is set in AddToPhysicalScene
4635 
4636 // if (m_updateCount > 0)
4637 // {
4638  if (Animator.UpdateMovementAnimations())
4639  TriggerScenePresenceUpdated();
4640 // m_updateCount--;
4641 // }
4642 
4643  CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
4644  Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
4645 
4646 
4647 // // No collisions at all means we may be flying. Update always
4648 // // to make falling work
4649 // if (m_lastColCount != coldata.Count || coldata.Count == 0)
4650 // {
4651 // m_updateCount = UPDATE_COUNT;
4652 // m_lastColCount = coldata.Count;
4653 // }
4654 
4655  if (coldata.Count != 0)
4656  {
4657 /*
4658  switch (Animator.CurrentMovementAnimation)
4659  {
4660  case "STAND":
4661  case "WALK":
4662  case "RUN":
4663  case "CROUCH":
4664  case "CROUCHWALK":
4665  {
4666  */
4667  ContactPoint lowest;
4668  lowest.SurfaceNormal = Vector3.Zero;
4669  lowest.Position = Vector3.Zero;
4670  lowest.Position.Z = float.MaxValue;
4671 
4672  foreach (ContactPoint contact in coldata.Values)
4673  {
4674 
4675  if (contact.CharacterFeet && contact.Position.Z < lowest.Position.Z)
4676  {
4677  lowest = contact;
4678  }
4679  }
4680 
4681  if (lowest.Position.Z != float.MaxValue)
4682  {
4683  lowest.SurfaceNormal = -lowest.SurfaceNormal;
4684  CollisionPlane = new Vector4(lowest.SurfaceNormal, Vector3.Dot(lowest.Position, lowest.SurfaceNormal));
4685  }
4686  else
4687  CollisionPlane = Vector4.UnitW;
4688 /*
4689  }
4690  break;
4691  }
4692 */
4693  }
4694  else
4695  CollisionPlane = Vector4.UnitW;
4696 
4697  RaiseCollisionScriptEvents(coldata);
4698 
4699  // Gods do not take damage and Invulnerable is set depending on parcel/region flags
4700  if (Invulnerable || GodLevel > 0)
4701  return;
4702 
4703  // The following may be better in the ICombatModule
4704  // probably tweaking of the values for ground and normal prim collisions will be needed
4705  float starthealth = Health;
4706  uint killerObj = 0;
4707  SceneObjectPart part = null;
4708  foreach (uint localid in coldata.Keys)
4709  {
4710  if (localid == 0)
4711  {
4712  part = null;
4713  }
4714  else
4715  {
4716  part = Scene.GetSceneObjectPart(localid);
4717  }
4718  if (part != null)
4719  {
4720  // Ignore if it has been deleted or volume detect
4721  if (!part.ParentGroup.IsDeleted && !part.ParentGroup.IsVolumeDetect)
4722  {
4723  if (part.ParentGroup.Damage > 0.0f)
4724  {
4725  // Something with damage...
4726  Health -= part.ParentGroup.Damage;
4727  part.ParentGroup.Scene.DeleteSceneObject(part.ParentGroup, false);
4728  }
4729  else
4730  {
4731  // An ordinary prim
4732  if (coldata[localid].PenetrationDepth >= 0.10f)
4733  Health -= coldata[localid].PenetrationDepth * 5.0f;
4734  }
4735  }
4736  }
4737  else
4738  {
4739  // 0 is the ground
4740  // what about collisions with other avatars?
4741  if (localid == 0 && coldata[localid].PenetrationDepth >= 0.10f)
4742  Health -= coldata[localid].PenetrationDepth * 5.0f;
4743  }
4744 
4745 
4746  if (Health <= 0.0f)
4747  {
4748  if (localid != 0)
4749  killerObj = localid;
4750  }
4751  //m_log.Debug("[AVATAR]: Collision with localid: " + localid.ToString() + " at depth: " + coldata[localid].ToString());
4752  }
4753  //Health = 100;
4754  if (!Invulnerable)
4755  {
4756  if (starthealth != Health)
4757  {
4758  ControllingClient.SendHealth(Health);
4759  }
4760  if (Health <= 0)
4761  {
4762  m_scene.EventManager.TriggerAvatarKill(killerObj, this);
4763  }
4764  if (starthealth == Health && Health < 100.0f)
4765  {
4766  Health += 0.03f;
4767  if (Health > 100.0f)
4768  Health = 100.0f;
4769  ControllingClient.SendHealth(Health);
4770  }
4771  }
4772  }
4773 
4774  public void setHealthWithUpdate(float health)
4775  {
4776  Health = health;
4777  ControllingClient.SendHealth(Health);
4778  }
4779 
4780  protected internal void Close()
4781  {
4782  // Clear known regions
4783  KnownRegions = new Dictionary<ulong, string>();
4784 
4785  // I don't get it but mono crashes when you try to dispose of this timer,
4786  // unsetting the elapsed callback should be enough to allow for cleanup however.
4787  // m_reprioritizationTimer.Dispose();
4788 
4789  RemoveFromPhysicalScene();
4790 
4791  m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
4792 
4793 // if (Animator != null)
4794 // Animator.Close();
4795  Animator = null;
4796 
4797  LifecycleState = ScenePresenceState.Removed;
4798  }
4799 
4800  public void AddAttachment(SceneObjectGroup gobj)
4801  {
4802  lock (m_attachments)
4803  {
4804  // This may be true when the attachment comes back
4805  // from serialization after login. Clear it.
4806  gobj.IsDeleted = false;
4807 
4808  m_attachments.Add(gobj);
4809  }
4810 
4811  IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
4812  if (bakedModule != null)
4813  bakedModule.UpdateMeshAvatar(m_uuid);
4814  }
4815 
4820  public List<SceneObjectGroup> GetAttachments()
4821  {
4822  lock (m_attachments)
4823  return new List<SceneObjectGroup>(m_attachments);
4824  }
4825 
4831  public List<SceneObjectGroup> GetAttachments(uint attachmentPoint)
4832  {
4833  List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
4834 
4835  if (attachmentPoint >= 0)
4836  {
4837  lock (m_attachments)
4838  {
4839  foreach (SceneObjectGroup so in m_attachments)
4840  {
4841  if (attachmentPoint == so.AttachmentPoint)
4842  attachments.Add(so);
4843  }
4844  }
4845  }
4846 
4847  return attachments;
4848  }
4849 
4850  public bool HasAttachments()
4851  {
4852  lock (m_attachments)
4853  return m_attachments.Count > 0;
4854  }
4855 
4859  public int ScriptCount()
4860  {
4861  int count = 0;
4862  lock (m_attachments)
4863  {
4864  foreach (SceneObjectGroup gobj in m_attachments)
4865  {
4866  if (gobj != null)
4867  {
4868  count += gobj.ScriptCount();
4869  }
4870  }
4871  }
4872  return count;
4873  }
4874 
4878  public float ScriptExecutionTime()
4879  {
4880  float time = 0.0f;
4881  lock (m_attachments)
4882  {
4883  foreach (SceneObjectGroup gobj in m_attachments)
4884  {
4885  if (gobj != null)
4886  {
4887  time += gobj.ScriptExecutionTime();
4888  }
4889  }
4890  }
4891  return time;
4892  }
4893 
4897  public int RunningScriptCount()
4898  {
4899  int count = 0;
4900  lock (m_attachments)
4901  {
4902  foreach (SceneObjectGroup gobj in m_attachments)
4903  {
4904  if (gobj != null)
4905  {
4906  count += gobj.RunningScriptCount();
4907  }
4908  }
4909  }
4910  return count;
4911  }
4912 
4913  public bool HasScriptedAttachments()
4914  {
4915  lock (m_attachments)
4916  {
4917  foreach (SceneObjectGroup gobj in m_attachments)
4918  {
4919  if (gobj != null)
4920  {
4921  if (gobj.RootPart.Inventory.ContainsScripts())
4922  return true;
4923  }
4924  }
4925  }
4926  return false;
4927  }
4928 
4929  public void RemoveAttachment(SceneObjectGroup gobj)
4930  {
4931  lock (m_attachments)
4932  m_attachments.Remove(gobj);
4933  }
4934 
4938  public void ClearAttachments()
4939  {
4940  lock (m_attachments)
4941  m_attachments.Clear();
4942  }
4943 
4947  public bool ValidateAttachments()
4948  {
4949  bool validated = true;
4950 
4951  lock (m_attachments)
4952  {
4953  // Validate
4954  foreach (SceneObjectGroup gobj in m_attachments)
4955  {
4956  if (gobj == null)
4957  {
4958  m_log.WarnFormat(
4959  "[SCENE PRESENCE]: Failed to validate an attachment for {0} since it was null. Continuing", Name);
4960 
4961  validated = false;
4962  }
4963  else if (gobj.IsDeleted)
4964  {
4965  m_log.WarnFormat(
4966  "[SCENE PRESENCE]: Failed to validate attachment {0} {1} for {2} since it had been deleted. Continuing",
4967  gobj.Name, gobj.UUID, Name);
4968 
4969  validated = false;
4970  }
4971  }
4972  }
4973 
4974  return validated;
4975  }
4976 
4977  public void SendAttachmentsToAllAgents()
4978  {
4979  lock (m_attachments)
4980  {
4981  foreach (SceneObjectGroup sog in m_attachments)
4982  {
4983  m_scene.ForEachScenePresence(delegate(ScenePresence p)
4984  {
4985  if (p != this && sog.HasPrivateAttachmentPoint)
4986  return;
4987 
4988  if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4989  return;
4990 
4991  SendTerseUpdateToAgentNF(p);
4992  SendAttachmentFullUpdateToAgentNF(sog, p);
4993  });
4994  }
4995  }
4996  }
4997 
4998  // send attachments to a client without filters except for huds
4999  // for now they are checked in several places down the line...
5000  public void SendAttachmentsToAgentNF(ScenePresence p)
5001  {
5002  SendTerseUpdateToAgentNF(p);
5003 // SendAvatarDataToAgentNF(this);
5004  lock (m_attachments)
5005  {
5006  foreach (SceneObjectGroup sog in m_attachments)
5007  {
5008  SendAttachmentFullUpdateToAgentNF(sog, p);
5009  }
5010  }
5011  }
5012 
5013  public void SendAttachmentFullUpdateToAgentNF(SceneObjectGroup sog, ScenePresence p)
5014  {
5015  if (p != this && sog.HasPrivateAttachmentPoint)
5016  return;
5017 
5018  SceneObjectPart[] parts = sog.Parts;
5019  SceneObjectPart rootpart = sog.RootPart;
5020 
5021  p.ControllingClient.SendEntityUpdate(rootpart, PrimUpdateFlags.FullUpdate);
5022 
5023  for (int i = 0; i < parts.Length; i++)
5024  {
5025  SceneObjectPart part = parts[i];
5026  if (part == rootpart)
5027  continue;
5028  p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate);
5029  }
5030  }
5031 
5032  public void SendAttachmentScheduleUpdate(SceneObjectGroup sog)
5033  {
5034  if (IsChildAgent || IsInTransit)
5035  return;
5036 
5037  SceneObjectPart[] origparts = sog.Parts;
5038  SceneObjectPart[] parts = new SceneObjectPart[origparts.Length];
5039  PrimUpdateFlags[] flags = new PrimUpdateFlags[origparts.Length];
5040 
5041  SceneObjectPart rootpart = sog.RootPart;
5042  UpdateRequired rootreq = sog.RootPart.UpdateFlag;
5043 
5044  int j = 0;
5045  bool allterse = true;
5046  for (int i = 0; i < origparts.Length; i++)
5047  {
5048  if (origparts[i] != rootpart)
5049  {
5050  switch (origparts[i].UpdateFlag)
5051  {
5052  case UpdateRequired.NONE:
5053  break;
5054 
5055  case UpdateRequired.TERSE:
5056  flags[j] = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5057  | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5058  parts[j] = origparts[i];
5059  j++;
5060  break;
5061 
5062  case UpdateRequired.FULL:
5063  flags[j] = PrimUpdateFlags.FullUpdate;
5064  allterse = false;
5065  parts[j] = origparts[i];
5066  j++;
5067  break;
5068  }
5069  }
5070  origparts[i].UpdateFlag = 0;
5071  }
5072 
5073  if (j == 0 && rootreq == UpdateRequired.NONE)
5074  return;
5075 
5076  PrimUpdateFlags rootflag = PrimUpdateFlags.FullUpdate;
5077 
5078  if (rootreq != UpdateRequired.FULL && allterse)
5079  {
5080  rootflag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5081  | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5082  }
5083 
5084  int nparts = j;
5085 
5086  ControllingClient.SendEntityUpdate(rootpart, rootflag);
5087 
5088  for (int i = 0; i < nparts; i++)
5089  {
5090  ControllingClient.SendEntityUpdate(parts[i], flags[i]);
5091  }
5092 
5093  if (sog.HasPrivateAttachmentPoint)
5094  return;
5095 
5096  List<ScenePresence> allPresences = m_scene.GetScenePresences();
5097  foreach (ScenePresence p in allPresences)
5098  {
5099  if (p == this)
5100  continue;
5101 
5102  if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5103  continue;
5104 
5105  p.ControllingClient.SendEntityUpdate(rootpart, rootflag);
5106 
5107  for (int i = 0; i < nparts; i++)
5108  {
5109  p.ControllingClient.SendEntityUpdate(parts[i], flags[i]);
5110  }
5111  }
5112  }
5113 
5114  public void SendAttachmentUpdate(SceneObjectGroup sog, UpdateRequired UpdateFlag)
5115  {
5116  if (IsChildAgent || IsInTransit)
5117  return;
5118 
5119  PrimUpdateFlags flag;
5120  switch (UpdateFlag)
5121  {
5122  case UpdateRequired.TERSE:
5123  flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5124  | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5125  break;
5126 
5127  case UpdateRequired.FULL:
5128  flag = PrimUpdateFlags.FullUpdate;
5129  break;
5130 
5131  default:
5132  return;
5133  }
5134 
5135  SceneObjectPart[] parts = sog.Parts;
5136  SceneObjectPart rootpart = sog.RootPart;
5137 
5138 // rootpart.UpdateFlag = 0;
5139 
5140  ControllingClient.SendEntityUpdate(rootpart, flag);
5141 
5142  for (int i = 0; i < parts.Length; i++)
5143  {
5144  SceneObjectPart part = parts[i];
5145  if (part == rootpart)
5146  continue;
5147  ControllingClient.SendEntityUpdate(part, flag);
5148 // part.UpdateFlag = 0;
5149  }
5150 
5151  if (sog.HasPrivateAttachmentPoint)
5152  return;
5153 
5154 
5155  List<ScenePresence> allPresences = m_scene.GetScenePresences();
5156  foreach (ScenePresence p in allPresences)
5157  {
5158  if (p == this)
5159  continue;
5160 
5161  if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5162  continue;
5163 
5164  p.ControllingClient.SendEntityUpdate(rootpart, flag);
5165 
5166  for (int i = 0; i < parts.Length; i++)
5167  {
5168  SceneObjectPart part = parts[i];
5169  if (part == rootpart)
5170  continue;
5171  p.ControllingClient.SendEntityUpdate(part, flag);
5172  }
5173  }
5174  }
5175 
5176  public void SendAttachmentScheduleUpdate(SceneObjectPart part)
5177  {
5178  if (IsChildAgent || IsInTransit)
5179  return;
5180 
5181 
5182  PrimUpdateFlags flag;
5183  switch (part.UpdateFlag)
5184  {
5185  case UpdateRequired.TERSE:
5186  flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5187  | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5188  break;
5189 
5190  case UpdateRequired.FULL:
5191  flag = PrimUpdateFlags.FullUpdate;
5192  break;
5193 
5194  default:
5195  return;
5196  }
5197 
5198  part.UpdateFlag = 0;
5199 
5200  ControllingClient.SendEntityUpdate(part, flag);
5201 
5202  if (part.ParentGroup.HasPrivateAttachmentPoint)
5203  return;
5204 
5205  List<ScenePresence> allPresences = m_scene.GetScenePresences();
5206  foreach (ScenePresence p in allPresences)
5207  {
5208  if (p == this)
5209  continue;
5210 
5211  if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5212  continue;
5213 
5214  p.ControllingClient.SendEntityUpdate(part, flag);
5215  }
5216  }
5217 
5218 
5219  public void SendAttachmentUpdate(SceneObjectPart part, UpdateRequired UpdateFlag)
5220  {
5221  if (IsChildAgent || IsInTransit)
5222  return;
5223 
5224  PrimUpdateFlags flag;
5225  switch (UpdateFlag)
5226  {
5227  case UpdateRequired.TERSE:
5228  flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5229  | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5230  break;
5231 
5232  case UpdateRequired.FULL:
5233  flag = PrimUpdateFlags.FullUpdate;
5234  break;
5235 
5236  default:
5237  return;
5238  }
5239 
5240 // part.UpdateFlag = 0;
5241 
5242  ControllingClient.SendEntityUpdate(part, flag);
5243 
5244  if (part.ParentGroup.HasPrivateAttachmentPoint)
5245  return;
5246 
5247  List<ScenePresence> allPresences = m_scene.GetScenePresences();
5248  foreach (ScenePresence p in allPresences)
5249  {
5250  if (p == this)
5251  continue;
5252  if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5253  continue;
5254 
5255  p.ControllingClient.SendEntityUpdate(part, flag);
5256  }
5257  }
5258 
5264  public void SendScriptEventToAttachments(string eventName, Object[] args)
5265  {
5266  Util.FireAndForget(delegate(object x)
5267  {
5268  if (m_scriptEngines.Length == 0)
5269  return;
5270 
5271  lock (m_attachments)
5272  {
5273  foreach (SceneObjectGroup grp in m_attachments)
5274  {
5275  // 16384 is CHANGED_ANIMATION
5276  //
5277  // Send this to all attachment root prims
5278  //
5279  foreach (IScriptModule m in m_scriptEngines)
5280  {
5281  if (m == null) // No script engine loaded
5282  continue;
5283 
5284  m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION });
5285  }
5286  }
5287  }
5288  }, null, "ScenePresence.SendScriptEventToAttachments");
5289  }
5290 
5297  public float GetMass()
5298  {
5299  PhysicsActor pa = PhysicsActor;
5300 
5301  if (pa != null)
5302  return pa.Mass;
5303  else
5304  return 0;
5305  }
5306 
5307  internal void PushForce(Vector3 impulse)
5308  {
5309  if (PhysicsActor != null)
5310  {
5311  PhysicsActor.AddForce(impulse,true);
5312  }
5313  }
5314 
5315  public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID)
5316  {
5317  SceneObjectPart p = m_scene.GetSceneObjectPart(Obj_localID);
5318  if (p == null)
5319  return;
5320 
5321  ControllingClient.SendTakeControls(controls, false, false);
5322  ControllingClient.SendTakeControls(controls, true, false);
5323 
5324  ScriptControllers obj = new ScriptControllers();
5325  obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
5326  obj.eventControls = ScriptControlled.CONTROL_ZERO;
5327 
5328  obj.objectID = p.ParentGroup.UUID;
5329  obj.itemID = Script_item_UUID;
5330  if (pass_on == 0 && accept == 0)
5331  {
5332  IgnoredControls |= (ScriptControlled)controls;
5333  obj.ignoreControls = (ScriptControlled)controls;
5334  }
5335 
5336  if (pass_on == 0 && accept == 1)
5337  {
5338  IgnoredControls |= (ScriptControlled)controls;
5339  obj.ignoreControls = (ScriptControlled)controls;
5340  obj.eventControls = (ScriptControlled)controls;
5341  }
5342 
5343  if (pass_on == 1 && accept == 1)
5344  {
5345  IgnoredControls = ScriptControlled.CONTROL_ZERO;
5346  obj.eventControls = (ScriptControlled)controls;
5347  obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
5348  }
5349 
5350  lock (scriptedcontrols)
5351  {
5352  if (pass_on == 1 && accept == 0)
5353  {
5354  IgnoredControls &= ~(ScriptControlled)controls;
5355  if (scriptedcontrols.ContainsKey(Script_item_UUID))
5356  scriptedcontrols.Remove(Script_item_UUID);
5357  }
5358  else
5359  {
5360  scriptedcontrols[Script_item_UUID] = obj;
5361  }
5362  }
5363 
5364  ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true);
5365  }
5366 
5367  public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID)
5368  {
5369  IgnoredControls = ScriptControlled.CONTROL_ZERO;
5370  lock (scriptedcontrols)
5371  {
5372  scriptedcontrols.Clear();
5373  }
5374  ControllingClient.SendTakeControls(int.MaxValue, false, false);
5375  }
5376 
5377  public void ClearControls()
5378  {
5379  IgnoredControls = ScriptControlled.CONTROL_ZERO;
5380  lock (scriptedcontrols)
5381  {
5382  scriptedcontrols.Clear();
5383  }
5384  }
5385 
5386  public void UnRegisterSeatControls(UUID obj)
5387  {
5388  List<UUID> takers = new List<UUID>();
5389 
5390  foreach (ScriptControllers c in scriptedcontrols.Values)
5391  {
5392  if (c.objectID == obj)
5393  takers.Add(c.itemID);
5394  }
5395  foreach (UUID t in takers)
5396  {
5397  UnRegisterControlEventsToScript(0, t);
5398  }
5399  }
5400 
5401  public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID)
5402  {
5403  ScriptControllers takecontrols;
5404 
5405  lock (scriptedcontrols)
5406  {
5407  if (scriptedcontrols.TryGetValue(Script_item_UUID, out takecontrols))
5408  {
5409  ScriptControlled sctc = takecontrols.eventControls;
5410 
5411  ControllingClient.SendTakeControls((int)sctc, false, false);
5412  ControllingClient.SendTakeControls((int)sctc, true, false);
5413 
5414  scriptedcontrols.Remove(Script_item_UUID);
5415  IgnoredControls = ScriptControlled.CONTROL_ZERO;
5416  foreach (ScriptControllers scData in scriptedcontrols.Values)
5417  {
5418  IgnoredControls |= scData.ignoreControls;
5419  }
5420  }
5421  }
5422  }
5423 
5424  private void SendControlsToScripts(uint flags)
5425  {
5426  // Notify the scripts only after calling UpdateMovementAnimations(), so that if a script
5427  // (e.g., a walking script) checks which animation is active it will be the correct animation.
5428  lock (scriptedcontrols)
5429  {
5430  if (scriptedcontrols.Count <= 0)
5431  return;
5432 
5433  ScriptControlled allflags = ScriptControlled.CONTROL_ZERO;
5434 
5435  if (MouseDown)
5436  {
5437  allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON);
5438  if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0)
5439  {
5440  allflags = ScriptControlled.CONTROL_ZERO;
5441  MouseDown = true;
5442  }
5443  }
5444 
5445  if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0)
5446  {
5447  allflags |= ScriptControlled.CONTROL_ML_LBUTTON;
5448  MouseDown = true;
5449  }
5450 
5451  if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0)
5452  {
5453  allflags |= ScriptControlled.CONTROL_LBUTTON;
5454  MouseDown = true;
5455  }
5456 
5457  // find all activated controls, whether the scripts are interested in them or not
5458  if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0)
5459  {
5460  allflags |= ScriptControlled.CONTROL_FWD;
5461  }
5462 
5463  if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0)
5464  {
5465  allflags |= ScriptControlled.CONTROL_BACK;
5466  }
5467 
5468  if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0)
5469  {
5470  allflags |= ScriptControlled.CONTROL_UP;
5471  }
5472 
5473  if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)
5474  {
5475  allflags |= ScriptControlled.CONTROL_DOWN;
5476  }
5477 
5478  if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) != 0)
5479  {
5480  allflags |= ScriptControlled.CONTROL_LEFT;
5481  }
5482 
5483  if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0)
5484  {
5485  allflags |= ScriptControlled.CONTROL_RIGHT;
5486  }
5487 
5488  if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
5489  {
5490  allflags |= ScriptControlled.CONTROL_ROT_RIGHT;
5491  }
5492 
5493  if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
5494  {
5495  allflags |= ScriptControlled.CONTROL_ROT_LEFT;
5496  }
5497 
5498  // optimization; we have to check per script, but if nothing is pressed and nothing changed, we can skip that
5499  if (allflags != ScriptControlled.CONTROL_ZERO || allflags != LastCommands)
5500  {
5501  foreach (KeyValuePair<UUID, ScriptControllers> kvp in scriptedcontrols)
5502  {
5503  UUID scriptUUID = kvp.Key;
5504  ScriptControllers scriptControlData = kvp.Value;
5505 
5506  ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us
5507  ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle
5508  ScriptControlled localChange = localHeld ^ localLast; // the changed bits
5509 
5510  if (localHeld != ScriptControlled.CONTROL_ZERO || localChange != ScriptControlled.CONTROL_ZERO)
5511  {
5512  // only send if still pressed or just changed
5513  m_scene.EventManager.TriggerControlEvent(scriptUUID, UUID, (uint)localHeld, (uint)localChange);
5514  }
5515  }
5516  }
5517 
5518  LastCommands = allflags;
5519  }
5520  }
5521 
5522  internal static AgentManager.ControlFlags RemoveIgnoredControls(AgentManager.ControlFlags flags, ScriptControlled ignored)
5523  {
5524  if (ignored == ScriptControlled.CONTROL_ZERO)
5525  return flags;
5526 
5527  if ((ignored & ScriptControlled.CONTROL_BACK) != 0)
5528  flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG);
5529  if ((ignored & ScriptControlled.CONTROL_FWD) != 0)
5530  flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_AT_POS);
5531  if ((ignored & ScriptControlled.CONTROL_DOWN) != 0)
5532  flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG);
5533  if ((ignored & ScriptControlled.CONTROL_UP) != 0)
5534  flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_UP_POS);
5535  if ((ignored & ScriptControlled.CONTROL_LEFT) != 0)
5536  flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS);
5537  if ((ignored & ScriptControlled.CONTROL_RIGHT) != 0)
5538  flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG);
5539  if ((ignored & ScriptControlled.CONTROL_ROT_LEFT) != 0)
5540  flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG);
5541  if ((ignored & ScriptControlled.CONTROL_ROT_RIGHT) != 0)
5542  flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS);
5543  if ((ignored & ScriptControlled.CONTROL_ML_LBUTTON) != 0)
5544  flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN);
5545  if ((ignored & ScriptControlled.CONTROL_LBUTTON) != 0)
5546  flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP | AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN);
5547 
5548  //DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
5549  //DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
5550  //DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
5551  //DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
5552  //DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
5553  //DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
5554  //DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
5555 
5556  return flags;
5557  }
5558 
5559  // returns true it local teleport allowed and sets the destiny position into pos
5560 
5561  private bool CheckLocalTPLandingPoint(ref Vector3 pos)
5562  {
5563  // Never constrain lures
5564  if ((TeleportFlags & TeleportFlags.ViaLure) != 0)
5565  return true;
5566 
5567  if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
5568  return true;
5569 
5570  // do not constrain gods and estate managers
5571  if(m_scene.Permissions.IsGod(m_uuid) ||
5572  m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid))
5573  return true;
5574 
5575  // will teleport to a telehub spawn point or landpoint if that results in getting closer to target
5576  // if not the local teleport fails.
5577 
5578  float currDistanceSQ = Vector3.DistanceSquared(AbsolutePosition, pos);
5579 
5580  // first check telehub
5581 
5582  UUID TelehubObjectID = m_scene.RegionInfo.RegionSettings.TelehubObject;
5583  if ( TelehubObjectID != UUID.Zero)
5584  {
5585  SceneObjectGroup telehubSOG = m_scene.GetSceneObjectGroup(TelehubObjectID);
5586  if(telehubSOG != null)
5587  {
5588  Vector3 spawnPos;
5589  float spawnDistSQ;
5590 
5591  SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray();
5592  if(spawnPoints.Length == 0)
5593  {
5594  spawnPos = new Vector3(128.0f, 128.0f, pos.Z);
5595  spawnDistSQ = Vector3.DistanceSquared(spawnPos, pos);
5596  }
5597  else
5598  {
5599  Vector3 hubPos = telehubSOG.AbsolutePosition;
5600  Quaternion hubRot = telehubSOG.GroupRotation;
5601 
5602  spawnPos = spawnPoints[0].GetLocation(hubPos, hubRot);
5603  spawnDistSQ = Vector3.DistanceSquared(spawnPos, pos);
5604 
5605  float testDistSQ;
5606  Vector3 testSpawnPos;
5607  for(int i = 1; i< spawnPoints.Length; i++)
5608  {
5609  testSpawnPos = spawnPoints[i].GetLocation(hubPos, hubRot);
5610  testDistSQ = Vector3.DistanceSquared(testSpawnPos, pos);
5611 
5612  if(testDistSQ < spawnDistSQ)
5613  {
5614  spawnPos = testSpawnPos;
5615  spawnDistSQ = testDistSQ;
5616  }
5617  }
5618  }
5619  if (currDistanceSQ < spawnDistSQ)
5620  {
5621  // we are already close
5622  ControllingClient.SendAlertMessage("Can't teleport closer to destination");
5623  return false;
5624  }
5625  else
5626  {
5627  pos = spawnPos;
5628  return true;
5629  }
5630  }
5631  }
5632 
5633  ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
5634 
5635  if (land.LandData.LandingType != (byte)LandingType.LandingPoint
5636  || land.LandData.OwnerID == m_uuid)
5637  return true;
5638 
5639  Vector3 landLocation = land.LandData.UserLocation;
5640  if(landLocation == Vector3.Zero)
5641  return true;
5642 
5643  if (currDistanceSQ < Vector3.DistanceSquared(landLocation, pos))
5644  {
5645  ControllingClient.SendAlertMessage("Can't teleport closer to destination");
5646  return false;
5647  }
5648 
5649  pos = land.LandData.UserLocation;
5650  return true;
5651  }
5652 
5653  const TeleportFlags TeleHubTPFlags = TeleportFlags.ViaLogin
5654  | TeleportFlags.ViaHGLogin | TeleportFlags.ViaLocation;
5655 
5656  private bool CheckAndAdjustTelehub(SceneObjectGroup telehub, ref Vector3 pos, ref bool positionChanged)
5657  {
5658  // forcing telehubs on any tp that reachs this
5659  if ((m_teleportFlags & TeleHubTPFlags) != 0 ||
5660  (m_scene.TelehubAllowLandmarks == true ? false : ((m_teleportFlags & TeleportFlags.ViaLandmark) != 0 )))
5661  {
5662  ILandObject land;
5663  Vector3 teleHubPosition = telehub.AbsolutePosition;
5664 
5665  SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray();
5666  if(spawnPoints.Length == 0)
5667  {
5668  land = m_scene.LandChannel.GetLandObject(teleHubPosition.X,teleHubPosition.Y);
5669  if(land != null)
5670  {
5671  pos = teleHubPosition;
5672  if(land.IsEitherBannedOrRestricted(UUID))
5673  return false;
5674  positionChanged = true;
5675  return true;
5676  }
5677  else
5678  return false;
5679  }
5680 
5681  int index;
5682  int tries;
5683  bool selected = false;
5684  bool validhub = false;
5685  Vector3 spawnPosition;
5686 
5687  Quaternion teleHubRotation = telehub.GroupRotation;
5688 
5689  switch(m_scene.SpawnPointRouting)
5690  {
5691  case "random":
5692  tries = spawnPoints.Length;
5693  if(tries < 3) // no much sense in random with a few points when there same can have bans
5694  goto case "sequence";
5695  do
5696  {
5697  index = Util.RandomClass.Next(spawnPoints.Length - 1);
5698 
5699  spawnPosition = spawnPoints[index].GetLocation(teleHubPosition, teleHubRotation);
5700  land = m_scene.LandChannel.GetLandObject(spawnPosition.X,spawnPosition.Y);
5701  if(land != null && !land.IsEitherBannedOrRestricted(UUID))
5702  selected = true;
5703 
5704  } while(selected == false && --tries > 0 );
5705 
5706  if(tries <= 0)
5707  goto case "sequence";
5708 
5709  pos = spawnPosition;
5710  return true;
5711 
5712  case "sequence":
5713  tries = spawnPoints.Length;
5714  selected = false;
5715  validhub = false;
5716  do
5717  {
5718  index = m_scene.SpawnPoint();
5719  spawnPosition = spawnPoints[index].GetLocation(teleHubPosition, teleHubRotation);
5720  land = m_scene.LandChannel.GetLandObject(spawnPosition.X,spawnPosition.Y);
5721  if(land != null)
5722  {
5723  validhub = true;
5724  if(land.IsEitherBannedOrRestricted(UUID))
5725  selected = false;
5726  else
5727  selected = true;
5728  }
5729 
5730  } while(selected == false && --tries > 0);
5731 
5732  if(!validhub)
5733  return false;
5734 
5735  pos = spawnPosition;
5736 
5737  if(!selected)
5738  return false;
5739  positionChanged = true;
5740  return true;
5741 
5742  default:
5743  case "closest":
5744  float distancesq = float.MaxValue;
5745  int closest = -1;
5746  validhub = false;
5747 
5748  for(int i = 0; i < spawnPoints.Length; i++)
5749  {
5750  spawnPosition = spawnPoints[i].GetLocation(teleHubPosition, teleHubRotation);
5751  Vector3 offset = spawnPosition - pos;
5752  float dsq = offset.LengthSquared();
5753  land = m_scene.LandChannel.GetLandObject(spawnPosition.X,spawnPosition.Y);
5754  if(land == null)
5755  continue;
5756 
5757  validhub = true;
5758  if(land.IsEitherBannedOrRestricted(UUID))
5759  continue;
5760 
5761  if(dsq >= distancesq)
5762  continue;
5763  distancesq = dsq;
5764  closest = i;
5765  }
5766 
5767  if(!validhub)
5768  return false;
5769 
5770  if(closest < 0)
5771  {
5772  pos = spawnPoints[0].GetLocation(teleHubPosition, teleHubRotation);
5773  positionChanged = true;
5774  return false;
5775  }
5776 
5777  pos = spawnPoints[closest].GetLocation(teleHubPosition, teleHubRotation);
5778  positionChanged = true;
5779  return true;
5780  }
5781  }
5782  return false;
5783  }
5784 
5785  const TeleportFlags adicionalLandPointFlags = TeleportFlags.ViaLandmark |
5786  TeleportFlags.ViaLocation | TeleportFlags.ViaHGLogin;
5787 
5788  // Modify landing point based on telehubs or parcel restrictions.
5789  private bool CheckAndAdjustLandingPoint(ref Vector3 pos, ref Vector3 lookat, ref bool positionChanged)
5790  {
5791  string reason;
5792 
5793  // dont mess with gods
5794  if(GodLevel >= 200 || m_scene.Permissions.IsGod(m_uuid))
5795  return true;
5796 
5797  // respect region owner and managers
5798 // if(m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid))
5799 // return true;
5800 
5801  if (!m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
5802  {
5803  SceneObjectGroup telehub = null;
5804  if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
5805  {
5806  if(CheckAndAdjustTelehub(telehub, ref pos, ref positionChanged))
5807  return true;
5808  }
5809  }
5810 
5811  // Honor bans, actually we don't honour them
5812  if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
5813  return false;
5814 
5815  ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
5816  if (land != null)
5817  {
5818  if (Scene.DebugTeleporting)
5819  TeleportFlagsDebug();
5820 
5821  // If we come in via login, landmark or map, we want to
5822  // honor landing points. If we come in via Lure, we want
5823  // to ignore them.
5824  if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) ==
5825  (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)
5826  || (m_teleportFlags & adicionalLandPointFlags) != 0)
5827  {
5828  if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
5829  land.LandData.UserLocation != Vector3.Zero )
5830  // &&
5831  // land.LandData.OwnerID != m_uuid )
5832  {
5833  pos = land.LandData.UserLocation;
5834  if(land.LandData.UserLookAt != Vector3.Zero)
5835  lookat = land.LandData.UserLookAt;
5836  positionChanged = true;
5837  }
5838  }
5839  }
5840  return true;
5841  }
5842 
5843  private DetectedObject CreateDetObject(SceneObjectPart obj)
5844  {
5845  DetectedObject detobj = new DetectedObject();
5846  detobj.keyUUID = obj.UUID;
5847  detobj.nameStr = obj.Name;
5848  detobj.ownerUUID = obj.OwnerID;
5849  detobj.posVector = obj.AbsolutePosition;
5850  detobj.rotQuat = obj.GetWorldRotation();
5851  detobj.velVector = obj.Velocity;
5852  detobj.colliderType = 0;
5853  detobj.groupUUID = obj.GroupID;
5854  detobj.linkNumber = 0;
5855 
5856  return detobj;
5857  }
5858 
5859  private DetectedObject CreateDetObject(ScenePresence av)
5860  {
5861  DetectedObject detobj = new DetectedObject();
5862  detobj.keyUUID = av.UUID;
5863  detobj.nameStr = av.ControllingClient.Name;
5864  detobj.ownerUUID = av.UUID;
5865  detobj.posVector = av.AbsolutePosition;
5866  detobj.rotQuat = av.Rotation;
5867  detobj.velVector = av.Velocity;
5868  detobj.colliderType = 0;
5869  detobj.groupUUID = av.ControllingClient.ActiveGroupId;
5870  detobj.linkNumber = 0;
5871 
5872  return detobj;
5873  }
5874 
5875  private DetectedObject CreateDetObjectForGround()
5876  {
5877  DetectedObject detobj = new DetectedObject();
5878  detobj.keyUUID = UUID.Zero;
5879  detobj.nameStr = "";
5880  detobj.ownerUUID = UUID.Zero;
5881  detobj.posVector = AbsolutePosition;
5882  detobj.rotQuat = Quaternion.Identity;
5883  detobj.velVector = Vector3.Zero;
5884  detobj.colliderType = 0;
5885  detobj.groupUUID = UUID.Zero;
5886  detobj.linkNumber = 0;
5887  return detobj;
5888  }
5889 
5890  private ColliderArgs CreateColliderArgs(SceneObjectPart dest, List<uint> colliders)
5891  {
5892  ColliderArgs colliderArgs = new ColliderArgs();
5893  List<DetectedObject> colliding = new List<DetectedObject>();
5894  foreach (uint localId in colliders)
5895  {
5896  if (localId == 0)
5897  continue;
5898 
5899  SceneObjectPart obj = m_scene.GetSceneObjectPart(localId);
5900  if (obj != null)
5901  {
5902  if (!dest.CollisionFilteredOut(obj.UUID, obj.Name))
5903  colliding.Add(CreateDetObject(obj));
5904  }
5905  else
5906  {
5907  ScenePresence av = m_scene.GetScenePresence(localId);
5908  if (av != null && (!av.IsChildAgent))
5909  {
5910  if (!dest.CollisionFilteredOut(av.UUID, av.Name))
5911  colliding.Add(CreateDetObject(av));
5912  }
5913  }
5914  }
5915 
5916  colliderArgs.Colliders = colliding;
5917 
5918  return colliderArgs;
5919  }
5920 
5921  private delegate void ScriptCollidingNotification(uint localID, ColliderArgs message);
5922 
5923  private void SendCollisionEvent(SceneObjectGroup dest, scriptEvents ev, List<uint> colliders, ScriptCollidingNotification notify)
5924  {
5925  ColliderArgs CollidingMessage;
5926 
5927  if (colliders.Count > 0)
5928  {
5929  if ((dest.RootPart.ScriptEvents & ev) != 0)
5930  {
5931  CollidingMessage = CreateColliderArgs(dest.RootPart, colliders);
5932 
5933  if (CollidingMessage.Colliders.Count > 0)
5934  notify(dest.RootPart.LocalId, CollidingMessage);
5935  }
5936  }
5937  }
5938 
5939  private void SendLandCollisionEvent(SceneObjectGroup dest, scriptEvents ev, ScriptCollidingNotification notify)
5940  {
5941  if ((dest.RootPart.ScriptEvents & ev) != 0)
5942  {
5943  ColliderArgs LandCollidingMessage = new ColliderArgs();
5944  List<DetectedObject> colliding = new List<DetectedObject>();
5945 
5946  colliding.Add(CreateDetObjectForGround());
5947  LandCollidingMessage.Colliders = colliding;
5948 
5949  notify(dest.RootPart.LocalId, LandCollidingMessage);
5950  }
5951  }
5952 
5953  private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
5954  {
5955  try
5956  {
5957  List<uint> thisHitColliders = new List<uint>();
5958  List<uint> endedColliders = new List<uint>();
5959  List<uint> startedColliders = new List<uint>();
5960  List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
5961  CollisionForSoundInfo soundinfo;
5962  ContactPoint curcontact;
5963 
5964  if (coldata.Count == 0)
5965  {
5966  if (m_lastColliders.Count == 0)
5967  return; // nothing to do
5968 
5969  foreach (uint localID in m_lastColliders)
5970  {
5971  endedColliders.Add(localID);
5972  }
5973  m_lastColliders.Clear();
5974  }
5975 
5976  else
5977  {
5978  bool candoparcelSound = ParcelAllowThisAvatarSounds;
5979 
5980  foreach (uint id in coldata.Keys)
5981  {
5982  thisHitColliders.Add(id);
5983  if (!m_lastColliders.Contains(id))
5984  {
5985  startedColliders.Add(id);
5986  curcontact = coldata[id];
5987  if (candoparcelSound && Math.Abs(curcontact.RelativeSpeed) > 0.2)
5988  {
5989  soundinfo = new CollisionForSoundInfo();
5990  soundinfo.colliderID = id;
5991  soundinfo.position = curcontact.Position;
5992  soundinfo.relativeVel = curcontact.RelativeSpeed;
5993  soundinfolist.Add(soundinfo);
5994  }
5995  }
5996  //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
5997  }
5998 
5999  // calculate things that ended colliding
6000  foreach (uint localID in m_lastColliders)
6001  {
6002  if (!thisHitColliders.Contains(localID))
6003  {
6004  endedColliders.Add(localID);
6005  }
6006  }
6007  //add the items that started colliding this time to the last colliders list.
6008  foreach (uint localID in startedColliders)
6009  {
6010  m_lastColliders.Add(localID);
6011  }
6012  // remove things that ended colliding from the last colliders list
6013  foreach (uint localID in endedColliders)
6014  {
6015  m_lastColliders.Remove(localID);
6016  }
6017 
6018  if (soundinfolist.Count > 0)
6019  CollisionSounds.AvatarCollisionSound(this, soundinfolist);
6020  }
6021 
6022  foreach (SceneObjectGroup att in GetAttachments())
6023  {
6024  SendCollisionEvent(att, scriptEvents.collision_start, startedColliders, m_scene.EventManager.TriggerScriptCollidingStart);
6025  SendCollisionEvent(att, scriptEvents.collision , m_lastColliders , m_scene.EventManager.TriggerScriptColliding);
6026  SendCollisionEvent(att, scriptEvents.collision_end , endedColliders , m_scene.EventManager.TriggerScriptCollidingEnd);
6027 
6028  if (startedColliders.Contains(0))
6029  SendLandCollisionEvent(att, scriptEvents.land_collision_start, m_scene.EventManager.TriggerScriptLandCollidingStart);
6030  if (m_lastColliders.Contains(0))
6031  SendLandCollisionEvent(att, scriptEvents.land_collision, m_scene.EventManager.TriggerScriptLandColliding);
6032  if (endedColliders.Contains(0))
6033  SendLandCollisionEvent(att, scriptEvents.land_collision_end, m_scene.EventManager.TriggerScriptLandCollidingEnd);
6034  }
6035  }
6036  catch { }
6037 // finally
6038 // {
6039 // m_collisionEventFlag = false;
6040 // }
6041  }
6042 
6043  private void TeleportFlagsDebug() {
6044 
6045  // Some temporary debugging help to show all the TeleportFlags we have...
6046  bool HG = false;
6047  if((m_teleportFlags & TeleportFlags.ViaHGLogin) == TeleportFlags.ViaHGLogin)
6048  HG = true;
6049 
6050  m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
6051 
6052  uint i = 0u;
6053  for (int x = 0; x <= 30 ; x++, i = 1u << x)
6054  {
6055  i = 1u << x;
6056 
6057  if((m_teleportFlags & (TeleportFlags)i) == (TeleportFlags)i)
6058  if (HG == false)
6059  m_log.InfoFormat("[SCENE PRESENCE]: Teleport Flags include {0}", ((TeleportFlags) i).ToString());
6060  else
6061  m_log.InfoFormat("[SCENE PRESENCE]: HG Teleport Flags include {0}", ((TeleportFlags)i).ToString());
6062  }
6063 
6064  m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
6065 
6066  }
6067 
6068  private void parcelGodCheck(UUID currentParcelID, bool isGod)
6069  {
6070  List<ScenePresence> allpresences = m_scene.GetScenePresences();
6071 
6072  foreach (ScenePresence p in allpresences)
6073  {
6074  if (p.IsDeleted || p.IsChildAgent || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6075  continue;
6076 
6077  if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID)
6078  {
6079  if (isGod)
6080  p.SendViewTo(this);
6081  else
6082  p.SendKillTo(this);
6083  }
6084  }
6085  }
6086 
6087  private void ParcelCrossCheck(UUID currentParcelID,UUID previusParcelID,
6088  bool currentParcelHide, bool previusParcelHide, bool oldhide,bool check)
6089  {
6090  List<ScenePresence> killsToSendto = new List<ScenePresence>();
6091  List<ScenePresence> killsToSendme = new List<ScenePresence>();
6092  List<ScenePresence> viewsToSendto = new List<ScenePresence>();
6093  List<ScenePresence> viewsToSendme = new List<ScenePresence>();
6094  List<ScenePresence> allpresences = null;
6095 
6096  if (IsInTransit || IsChildAgent)
6097  return;
6098 
6099  if (check)
6100  {
6101  // check is relative to current parcel only
6102  if (currentParcelUUID == null || oldhide == currentParcelHide)
6103  return;
6104 
6105  allpresences = m_scene.GetScenePresences();
6106 
6107  if (oldhide)
6108  { // where private
6109  foreach (ScenePresence p in allpresences)
6110  {
6111  if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6112  continue;
6113 
6114  // those on not on parcel see me
6115  if (currentParcelID != p.currentParcelUUID)
6116  {
6117  viewsToSendto.Add(p); // they see me
6118  }
6119  }
6120  } // where private end
6121 
6122  else
6123  { // where public
6124  foreach (ScenePresence p in allpresences)
6125  {
6126  if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6127  continue;
6128 
6129  // those not on parcel dont see me
6130  if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
6131  {
6132  killsToSendto.Add(p); // they dont see me
6133  }
6134  }
6135  } // where public end
6136 
6137  allpresences.Clear();
6138  }
6139  else
6140  {
6141  if (currentParcelHide)
6142  {
6143  // now on a private parcel
6144  allpresences = m_scene.GetScenePresences();
6145 
6146  if (previusParcelHide && previusParcelID != UUID.Zero)
6147  {
6148  foreach (ScenePresence p in allpresences)
6149  {
6150  if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6151  continue;
6152 
6153  // only those on previus parcel need receive kills
6154  if (previusParcelID == p.currentParcelUUID)
6155  {
6156  if(p.GodLevel < 200)
6157  killsToSendto.Add(p); // they dont see me
6158  if(GodLevel < 200)
6159  killsToSendme.Add(p); // i dont see them
6160  }
6161  // only those on new parcel need see
6162  if (currentParcelID == p.currentParcelUUID)
6163  {
6164  viewsToSendto.Add(p); // they see me
6165  viewsToSendme.Add(p); // i see them
6166  }
6167  }
6168  }
6169  else
6170  {
6171  //was on a public area
6172  allpresences = m_scene.GetScenePresences();
6173 
6174  foreach (ScenePresence p in allpresences)
6175  {
6176  if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6177  continue;
6178 
6179  // those not on new parcel dont see me
6180  if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
6181  {
6182  killsToSendto.Add(p); // they dont see me
6183  }
6184  else
6185  {
6186  viewsToSendme.Add(p); // i see those on it
6187  }
6188  }
6189  }
6190  allpresences.Clear();
6191  } // now on a private parcel end
6192 
6193  else
6194  {
6195  // now on public parcel
6196  if (previusParcelHide && previusParcelID != UUID.Zero)
6197  {
6198  // was on private area
6199  allpresences = m_scene.GetScenePresences();
6200 
6201  foreach (ScenePresence p in allpresences)
6202  {
6203  if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6204  continue;
6205  // only those old parcel need kills
6206  if (previusParcelID == p.currentParcelUUID && GodLevel < 200)
6207  {
6208  killsToSendme.Add(p); // i dont see them
6209  }
6210  else
6211  {
6212  viewsToSendto.Add(p); // they see me
6213  }
6214  }
6215  }
6216  else
6217  return; // was on a public area also
6218  } // now on public parcel end
6219  }
6220 
6221  // send the things
6222 
6223  if (killsToSendto.Count > 0)
6224  {
6225  foreach (ScenePresence p in killsToSendto)
6226  {
6227 // m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname);
6228  SendKillTo(p);
6229  }
6230  }
6231 
6232  if (killsToSendme.Count > 0)
6233  {
6234  foreach (ScenePresence p in killsToSendme)
6235  {
6236 // m_log.Debug("[AVATAR]: killToMe: " + Lastname + " " + p.Lastname);
6237  p.SendKillTo(this);
6238  }
6239  }
6240 
6241  if (viewsToSendto.Count > 0)
6242  {
6243  foreach (ScenePresence p in viewsToSendto)
6244  {
6245  SendViewTo(p);
6246  }
6247  }
6248 
6249  if (viewsToSendme.Count > 0 )
6250  {
6251  foreach (ScenePresence p in viewsToSendme)
6252  {
6253  if (p.IsChildAgent)
6254  continue;
6255 // m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname);
6256  p.SendViewTo(this);
6257  }
6258  }
6259  }
6260 
6261  public void HasMovedAway(bool nearRegion)
6262  {
6263 
6264  if (nearRegion)
6265  {
6266  if (Scene.AttachmentsModule != null)
6267  Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
6268 
6269  if (!ParcelHideThisAvatar || GodLevel >= 200)
6270  return;
6271 
6272  List<ScenePresence> allpresences = m_scene.GetScenePresences();
6273  foreach (ScenePresence p in allpresences)
6274  {
6275  if (p.IsDeleted || p == this || p.IsChildAgent || p.ControllingClient == null || !p.ControllingClient.IsActive)
6276  continue;
6277 
6278  if (p.currentParcelUUID == m_currentParcelUUID)
6279  {
6280  p.SendKillTo(this);
6281  }
6282  }
6283  }
6284  else
6285  {
6286  List<ScenePresence> allpresences = m_scene.GetScenePresences();
6287  foreach (ScenePresence p in allpresences)
6288  {
6289  if (p == this)
6290  continue;
6291  SendKillTo(p);
6292  if (!p.IsChildAgent)
6293  p.SendKillTo(this);
6294  }
6295 
6296  if (Scene.AttachmentsModule != null)
6297  Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
6298  }
6299  }
6300 
6301 
6302 // kill with attachs root kills
6303  public void SendKillTo(ScenePresence p)
6304  {
6305  List<uint> ids = new List<uint>(m_attachments.Count + 1);
6306  foreach (SceneObjectGroup sog in m_attachments)
6307  {
6308  ids.Add(sog.RootPart.LocalId);
6309  }
6310 
6311  ids.Add(LocalId);
6312  p.ControllingClient.SendKillObject(ids);
6313  }
6314 
6315 /*
6316 // kill with hack
6317  public void SendKillTo(ScenePresence p)
6318  {
6319  foreach (SceneObjectGroup sog in m_attachments)
6320  p.ControllingClient.SendPartFullUpdate(sog.RootPart, LocalId + 1);
6321  p.ControllingClient.SendKillObject(new List<uint> { LocalId });
6322  }
6323 */
6324  public void SendViewTo(ScenePresence p)
6325  {
6326  SendAvatarDataToAgentNF(p);
6327  SendAppearanceToAgent(p);
6328  if (Animator != null)
6329  Animator.SendAnimPackToClient(p.ControllingClient);
6330  SendAttachmentsToAgentNF(p);
6331  }
6332 
6333  public void SetAnimationOverride(string animState, UUID animID)
6334  {
6335  Overrides.SetOverride(animState, animID);
6336 // Animator.SendAnimPack();
6337  Animator.ForceUpdateMovementAnimations();
6338  }
6339 
6340  public UUID GetAnimationOverride(string animState)
6341  {
6342  return Overrides.GetOverriddenAnimation(animState);
6343  }
6344  }
6345 }
int GetStateSource()
Force viewers to show the avatar's current name.
void TeleportWithMomentum(Vector3 pos, Vector3?v)
OpenSim.Framework.Constants.TeleportFlags TeleportFlags
void RemoveFromPhysicalScene()
Removes physics plugin scene representation of this agent if it exists.
OpenSim.Framework.Constants.TeleportFlags TeleportFlags
void DropOldNeighbours(List< ulong > oldRegions)
ScenePresence(IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
Contains the Avatar's Appearance and methods to manipulate the appearance.
delegate void SendCoarseLocationsMethod(UUID scene, ScenePresence presence, List< Vector3 > coarseLocations, List< UUID > avatarUUIDs)
ScenePresenceState
The possible states that a scene presence can be in. This is currently orthagonal to whether a scene ...
delegate void SetAlwaysRun(IClientAPI remoteClient, bool SetAlwaysRun)
void avnLocalTeleport(Vector3 newpos, Vector3?newvel, bool rotateToVelXY)
Handle all animation duties for a scene presence
System.Timers.Timer Timer
PresenceType
Indicate the type of ScenePresence.
Definition: PresenceType.cs:34
System.Timers.Timer Timer
void Teleport(Vector3 pos)
Do not call this directly. Call Scene.RequestTeleportLocation() instead.
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion rotation
Definition: ICM_Api.cs:32
Circuit data for an agent. Connection information shared between regions that accept UDP connections ...
ICapabilitiesModule CapsModule
Definition: Scene.cs:782
void MakeChildAgent(ulong newRegionHandle)
This turns a root agent into a child agent
Vector3 GetWorldVelocity()
Get velocity relative to the world.
void SetNeighbourRegionSizeInfo(List< GridRegion > regionsList)
OpenSim.Framework.Animation Animation
void SetSize(Vector3 size, float feetoffset)
Quaternion GetWorldRotation()
Gets the world rotation of this presence.
uint teleportFlags
How this agent got here
void AddNeighbourRegionSizeInfo(GridRegion region)
OpenSim.Services.Interfaces.GridRegion GridRegion
void SetHeight(float height)
Sets avatar height in the physics plugin
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3 vector
Definition: ICM_Api.cs:33