/OpenSim/Region/Framework/Scenes/ScenePresence.cs
C# | 3751 lines | 2378 code | 522 blank | 851 comment | 532 complexity | 7f20658cddec888950a40227101fff65 MD5 | raw file
Possible License(s): BSD-3-Clause
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- using System;
- using System.Collections.Generic;
- using System.Reflection;
- using System.Timers;
- using OpenMetaverse;
- using log4net;
- using OpenSim.Framework;
- using OpenSim.Framework.Client;
- using OpenSim.Region.Framework.Interfaces;
- using OpenSim.Region.Framework.Scenes.Animation;
- using OpenSim.Region.Framework.Scenes.Types;
- using OpenSim.Region.Physics.Manager;
- using GridRegion = OpenSim.Services.Interfaces.GridRegion;
- using OpenSim.Services.Interfaces;
- namespace OpenSim.Region.Framework.Scenes
- {
- enum ScriptControlled : uint
- {
- CONTROL_ZERO = 0,
- CONTROL_FWD = 1,
- CONTROL_BACK = 2,
- CONTROL_LEFT = 4,
- CONTROL_RIGHT = 8,
- CONTROL_UP = 16,
- CONTROL_DOWN = 32,
- CONTROL_ROT_LEFT = 256,
- CONTROL_ROT_RIGHT = 512,
- CONTROL_LBUTTON = 268435456,
- CONTROL_ML_LBUTTON = 1073741824
- }
- struct ScriptControllers
- {
- public UUID itemID;
- public ScriptControlled ignoreControls;
- public ScriptControlled eventControls;
- }
- public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs);
- public class ScenePresence : EntityBase, ISceneEntity
- {
- // ~ScenePresence()
- // {
- // m_log.Debug("[ScenePresence] Destructor called");
- // }
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- // private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
- private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
- private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
-
- /// <summary>
- /// Experimentally determined "fudge factor" to make sit-target positions
- /// the same as in SecondLife. Fudge factor was tested for 36 different
- /// test cases including prims of type box, sphere, cylinder, and torus,
- /// with varying parameters for sit target location, prim size, prim
- /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
- /// issue #1716
- /// </summary>
- private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
- public UUID currentParcelUUID = UUID.Zero;
- private ISceneViewer m_sceneViewer;
- /// <value>
- /// The animator for this avatar
- /// </value>
- public ScenePresenceAnimator Animator
- {
- get { return m_animator; }
- }
- protected ScenePresenceAnimator m_animator;
- /// <value>
- /// The scene objects attached to this avatar. Do not change this list directly - use methods such as
- /// AddAttachment() and RemoveAttachment(). Lock this list when performing any read operations upon it.
- /// </value>
- public List<SceneObjectGroup> Attachments
- {
- get { return m_attachments; }
- }
- protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
- private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
- private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
- private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
- private bool MouseDown = false;
- private SceneObjectGroup proxyObjectGroup;
- //private SceneObjectPart proxyObjectPart = null;
- public Vector3 lastKnownAllowedPosition;
- public bool sentMessageAboutRestrictedParcelFlyingDown;
- public Vector4 CollisionPlane = Vector4.UnitW;
- private Vector3 m_lastPosition;
- private Quaternion m_lastRotation;
- private Vector3 m_lastVelocity;
- //private int m_lastTerseSent;
- private bool m_updateflag;
- private byte m_movementflag;
- private Vector3? m_forceToApply;
- private uint m_requestedSitTargetID;
- private UUID m_requestedSitTargetUUID;
- public bool SitGround = false;
- private SendCourseLocationsMethod m_sendCourseLocationsMethod;
- //private Vector3 m_requestedSitOffset = new Vector3();
- private Vector3 m_LastFinitePos;
- private float m_sitAvatarHeight = 2.0f;
- private int m_godLevel;
- private int m_userLevel;
- private bool m_invulnerable = true;
- private Vector3 m_lastChildAgentUpdatePosition;
- private Vector3 m_lastChildAgentUpdateCamPosition;
- private int m_perfMonMS;
- private bool m_setAlwaysRun;
-
- private bool m_forceFly;
- private bool m_flyDisabled;
- private float m_speedModifier = 1.0f;
- private Quaternion m_bodyRot= Quaternion.Identity;
- private Quaternion m_bodyRotPrevious = Quaternion.Identity;
- private const int LAND_VELOCITYMAG_MAX = 12;
- public bool IsRestrictedToRegion;
- public string JID = String.Empty;
- private float m_health = 100f;
- protected RegionInfo m_regionInfo;
- protected ulong crossingFromRegion;
- private readonly Vector3[] Dir_Vectors = new Vector3[9];
- // Position of agent's camera in world (region cordinates)
- protected Vector3 m_CameraCenter;
- protected Vector3 m_lastCameraCenter;
- protected Timer m_reprioritization_timer;
- protected bool m_reprioritizing;
- protected bool m_reprioritization_called;
- // Use these three vectors to figure out what the agent is looking at
- // Convert it to a Matrix and/or Quaternion
- protected Vector3 m_CameraAtAxis;
- protected Vector3 m_CameraLeftAxis;
- protected Vector3 m_CameraUpAxis;
- private AgentManager.ControlFlags m_AgentControlFlags;
- private Quaternion m_headrotation = Quaternion.Identity;
- private byte m_state;
- //Reuse the Vector3 instead of creating a new one on the UpdateMovement method
- // private Vector3 movementvector;
- private bool m_autopilotMoving;
- private Vector3 m_autoPilotTarget;
- private bool m_sitAtAutoTarget;
- private string m_nextSitAnimation = String.Empty;
- //PauPaw:Proper PID Controler for autopilot************
- private bool m_moveToPositionInProgress;
- private Vector3 m_moveToPositionTarget;
- private bool m_followCamAuto;
- private int m_movementUpdateCount;
- private const int NumMovementsBetweenRayCast = 5;
- private bool CameraConstraintActive;
- //private int m_moveToPositionStateStatus;
- //*****************************************************
- // Agent's Draw distance.
- protected float m_DrawDistance;
- protected AvatarAppearance m_appearance;
- // neighbouring regions we have enabled a child agent in
- // holds the seed cap for the child agent in that region
- private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>();
- /// <summary>
- /// Implemented Control Flags
- /// </summary>
- private enum Dir_ControlFlags
- {
- DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
- DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
- DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
- DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
- DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
- DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
- DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
- DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
- DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
- }
-
- /// <summary>
- /// Position at which a significant movement was made
- /// </summary>
- private Vector3 posLastSignificantMove;
- // For teleports and crossings callbacks
- string m_callbackURI;
- UUID m_originRegionID;
- ulong m_rootRegionHandle;
- /// <value>
- /// Script engines present in the scene
- /// </value>
- private IScriptModule[] m_scriptEngines;
- #region Properties
- /// <summary>
- /// Physical scene representation of this Avatar.
- /// </summary>
- public PhysicsActor PhysicsActor
- {
- set { m_physicsActor = value; }
- get { return m_physicsActor; }
- }
- public byte MovementFlag
- {
- set { m_movementflag = value; }
- get { return m_movementflag; }
- }
- public bool Updated
- {
- set { m_updateflag = value; }
- get { return m_updateflag; }
- }
- public bool Invulnerable
- {
- set { m_invulnerable = value; }
- get { return m_invulnerable; }
- }
- public int UserLevel
- {
- get { return m_userLevel; }
- }
- public int GodLevel
- {
- get { return m_godLevel; }
- }
- public ulong RegionHandle
- {
- get { return m_rootRegionHandle; }
- }
- public Vector3 CameraPosition
- {
- get { return m_CameraCenter; }
- }
- public Quaternion CameraRotation
- {
- get { return Util.Axes2Rot(m_CameraAtAxis, m_CameraLeftAxis, m_CameraUpAxis); }
- }
- public Vector3 CameraAtAxis
- {
- get { return m_CameraAtAxis; }
- }
- public Vector3 CameraLeftAxis
- {
- get { return m_CameraLeftAxis; }
- }
- public Vector3 CameraUpAxis
- {
- get { return m_CameraUpAxis; }
- }
- public Vector3 Lookat
- {
- get
- {
- Vector3 a = new Vector3(m_CameraAtAxis.X, m_CameraAtAxis.Y, 0);
- if (a == Vector3.Zero)
- return a;
- return Util.GetNormalizedVector(a);
- }
- }
- private readonly string m_firstname;
- public string Firstname
- {
- get { return m_firstname; }
- }
- private readonly string m_lastname;
- public string Lastname
- {
- get { return m_lastname; }
- }
- private string m_grouptitle;
- public string Grouptitle
- {
- get { return m_grouptitle; }
- set { m_grouptitle = value; }
- }
- public float DrawDistance
- {
- get { return m_DrawDistance; }
- }
- protected bool m_allowMovement = true;
- public bool AllowMovement
- {
- get { return m_allowMovement; }
- set { m_allowMovement = value; }
- }
- public bool SetAlwaysRun
- {
- get
- {
- if (PhysicsActor != null)
- {
- return PhysicsActor.SetAlwaysRun;
- }
- else
- {
- return m_setAlwaysRun;
- }
- }
- set
- {
- m_setAlwaysRun = value;
- if (PhysicsActor != null)
- {
- PhysicsActor.SetAlwaysRun = value;
- }
- }
- }
- public byte State
- {
- get { return m_state; }
- set { m_state = value; }
- }
- public uint AgentControlFlags
- {
- get { return (uint)m_AgentControlFlags; }
- set { m_AgentControlFlags = (AgentManager.ControlFlags)value; }
- }
- /// <summary>
- /// This works out to be the ClientView object associated with this avatar, or it's client connection manager
- /// </summary>
- private IClientAPI m_controllingClient;
- protected PhysicsActor m_physicsActor;
- /// <value>
- /// The client controlling this presence
- /// </value>
- public IClientAPI ControllingClient
- {
- get { return m_controllingClient; }
- }
- public IClientCore ClientView
- {
- get { return (IClientCore) m_controllingClient; }
- }
- protected Vector3 m_parentPosition;
- public Vector3 ParentPosition
- {
- get { return m_parentPosition; }
- set { m_parentPosition = value; }
- }
- /// <summary>
- /// Position of this avatar relative to the region the avatar is in
- /// </summary>
- public override Vector3 AbsolutePosition
- {
- get
- {
- PhysicsActor actor = m_physicsActor;
- if (actor != null)
- m_pos = actor.Position;
- return m_parentPosition + m_pos;
- }
- set
- {
- PhysicsActor actor = m_physicsActor;
- if (actor != null)
- {
- try
- {
- lock (m_scene.SyncRoot)
- m_physicsActor.Position = value;
- }
- catch (Exception e)
- {
- m_log.Error("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message);
- }
- }
- m_pos = value;
- m_parentPosition = Vector3.Zero;
- }
- }
- public Vector3 OffsetPosition
- {
- get { return m_pos; }
- set { m_pos = value; }
- }
- /// <summary>
- /// Current velocity of the avatar.
- /// </summary>
- public override Vector3 Velocity
- {
- get
- {
- PhysicsActor actor = m_physicsActor;
- if (actor != null)
- m_velocity = actor.Velocity;
- return m_velocity;
- }
- set
- {
- PhysicsActor actor = m_physicsActor;
- if (actor != null)
- {
- try
- {
- lock (m_scene.SyncRoot)
- actor.Velocity = value;
- }
- catch (Exception e)
- {
- m_log.Error("[SCENEPRESENCE]: VELOCITY " + e.Message);
- }
- }
- m_velocity = value;
- }
- }
- public Quaternion Rotation
- {
- get { return m_bodyRot; }
- set { m_bodyRot = value; }
- }
- public Quaternion PreviousRotation
- {
- get { return m_bodyRotPrevious; }
- set { m_bodyRotPrevious = value; }
- }
- /// <summary>
- /// If this is true, agent doesn't have a representation in this scene.
- /// this is an agent 'looking into' this scene from a nearby scene(region)
- ///
- /// if False, this agent has a representation in this scene
- /// </summary>
- private bool m_isChildAgent = true;
- public bool IsChildAgent
- {
- get { return m_isChildAgent; }
- set { m_isChildAgent = value; }
- }
- private uint m_parentID;
- public uint ParentID
- {
- get { return m_parentID; }
- set { m_parentID = value; }
- }
- public float Health
- {
- get { return m_health; }
- set { m_health = value; }
- }
- /// <summary>
- /// These are the region handles known by the avatar.
- /// </summary>
- public List<ulong> KnownChildRegionHandles
- {
- get
- {
- if (m_knownChildRegions.Count == 0)
- return new List<ulong>();
- else
- return new List<ulong>(m_knownChildRegions.Keys);
- }
- }
- public Dictionary<ulong, string> KnownRegions
- {
- get { return m_knownChildRegions; }
- set
- {
- m_knownChildRegions = value;
- }
- }
- public ISceneViewer SceneViewer
- {
- get { return m_sceneViewer; }
- }
- public void AdjustKnownSeeds()
- {
- Dictionary<ulong, string> seeds;
- if (Scene.CapsModule != null)
- seeds = Scene.CapsModule.GetChildrenSeeds(UUID);
- else
- seeds = new Dictionary<ulong, string>();
- List<ulong> old = new List<ulong>();
- foreach (ulong handle in seeds.Keys)
- {
- uint x, y;
- Utils.LongToUInts(handle, out x, out y);
- x = x / Constants.RegionSize;
- y = y / Constants.RegionSize;
- if (Util.IsOutsideView(x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
- {
- old.Add(handle);
- }
- }
- DropOldNeighbours(old);
-
- if (Scene.CapsModule != null)
- Scene.CapsModule.SetChildrenSeed(UUID, seeds);
-
- KnownRegions = seeds;
- //m_log.Debug(" ++++++++++AFTER+++++++++++++ ");
- //DumpKnownRegions();
- }
- public void DumpKnownRegions()
- {
- m_log.Info("================ KnownRegions "+Scene.RegionInfo.RegionName+" ================");
- foreach (KeyValuePair<ulong, string> kvp in KnownRegions)
- {
- uint x, y;
- Utils.LongToUInts(kvp.Key, out x, out y);
- x = x / Constants.RegionSize;
- y = y / Constants.RegionSize;
- m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
- }
- }
- private bool m_inTransit;
- private bool m_mouseLook;
- private bool m_leftButtonDown;
- public bool IsInTransit
- {
- get { return m_inTransit; }
- set { m_inTransit = value; }
- }
- public float SpeedModifier
- {
- get { return m_speedModifier; }
- set { m_speedModifier = value; }
- }
- public bool ForceFly
- {
- get { return m_forceFly; }
- set { m_forceFly = value; }
- }
- public bool FlyDisabled
- {
- get { return m_flyDisabled; }
- set { m_flyDisabled = value; }
- }
- public string Viewer
- {
- get { return m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode).Viewer; }
- }
- #endregion
- #region Constructor(s)
-
- public ScenePresence()
- {
- m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
- CreateSceneViewer();
- m_animator = new ScenePresenceAnimator(this);
- }
-
- private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
- {
- m_rootRegionHandle = reginfo.RegionHandle;
- m_controllingClient = client;
- m_firstname = m_controllingClient.FirstName;
- m_lastname = m_controllingClient.LastName;
- m_name = String.Format("{0} {1}", m_firstname, m_lastname);
- m_scene = world;
- m_uuid = client.AgentId;
- m_regionInfo = reginfo;
- m_localId = m_scene.AllocateLocalId();
- UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
- if (account != null)
- m_userLevel = account.UserLevel;
- IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
- if (gm != null)
- m_grouptitle = gm.GetGroupTitle(m_uuid);
- m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>();
-
- AbsolutePosition = posLastSignificantMove = m_CameraCenter =
- m_lastCameraCenter = m_controllingClient.StartPos;
- m_reprioritization_timer = new Timer(world.ReprioritizationInterval);
- m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize);
- m_reprioritization_timer.AutoReset = false;
- AdjustKnownSeeds();
- // TODO: I think, this won't send anything, as we are still a child here...
- Animator.TrySetMovementAnimation("STAND");
- // we created a new ScenePresence (a new child agent) in a fresh region.
- // Request info about all the (root) agents in this region
- // Note: This won't send data *to* other clients in that region (children don't send)
- // MIC: This gets called again in CompleteMovement
- SendInitialFullUpdateToAllClients();
- RegisterToEvents();
- SetDirectionVectors();
- }
- public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance)
- : this(client, world, reginfo)
- {
- m_appearance = appearance;
- }
- private void CreateSceneViewer()
- {
- m_sceneViewer = new SceneViewer(this);
- }
- public void RegisterToEvents()
- {
- m_controllingClient.OnCompleteMovementToRegion += CompleteMovement;
- //m_controllingClient.OnCompleteMovementToRegion += SendInitialData;
- m_controllingClient.OnAgentUpdate += HandleAgentUpdate;
- m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit;
- m_controllingClient.OnAgentSit += HandleAgentSit;
- m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
- m_controllingClient.OnStartAnim += HandleStartAnim;
- m_controllingClient.OnStopAnim += HandleStopAnim;
- m_controllingClient.OnForceReleaseControls += HandleForceReleaseControls;
- m_controllingClient.OnAutoPilotGo += DoAutoPilot;
- m_controllingClient.AddGenericPacketHandler("autopilot", DoMoveToPosition);
- // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
- // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
- }
- private void SetDirectionVectors()
- {
- Dir_Vectors[0] = Vector3.UnitX; //FORWARD
- Dir_Vectors[1] = -Vector3.UnitX; //BACK
- Dir_Vectors[2] = Vector3.UnitY; //LEFT
- Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
- Dir_Vectors[4] = Vector3.UnitZ; //UP
- Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
- Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
- Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD
- Dir_Vectors[7] = -Vector3.UnitX; //BACK
- }
- private Vector3[] GetWalkDirectionVectors()
- {
- Vector3[] vector = new Vector3[9];
- vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
- vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
- vector[2] = Vector3.UnitY; //LEFT
- vector[3] = -Vector3.UnitY; //RIGHT
- vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
- vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
- vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge
- vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge
- vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge
- return vector;
- }
- #endregion
- public uint GenerateClientFlags(UUID ObjectID)
- {
- return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID);
- }
- /// <summary>
- /// Send updates to the client about prims which have been placed on the update queue. We don't
- /// necessarily send updates for all the parts on the queue, e.g. if an updates with a more recent
- /// timestamp has already been sent.
- /// </summary>
- public void SendPrimUpdates()
- {
- m_perfMonMS = Util.EnvironmentTickCount();
- m_sceneViewer.SendPrimUpdates();
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- }
- #region Status Methods
- /// <summary>
- /// This turns a child agent, into a root agent
- /// This is called when an agent teleports into a region, or if an
- /// agent crosses into this region from a neighbor over the border
- /// </summary>
- public void MakeRootAgent(Vector3 pos, bool isFlying)
- {
- m_log.DebugFormat(
- "[SCENE]: Upgrading child to root agent for {0} in {1}",
- Name, m_scene.RegionInfo.RegionName);
- //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
- IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
- if (gm != null)
- m_grouptitle = gm.GetGroupTitle(m_uuid);
- m_rootRegionHandle = m_scene.RegionInfo.RegionHandle;
- m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
- // Moved this from SendInitialData to ensure that m_appearance is initialized
- // before the inventory is processed in MakeRootAgent. This fixes a race condition
- // related to the handling of attachments
- //m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
- if (m_scene.TestBorderCross(pos, Cardinals.E))
- {
- Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
- pos.X = crossedBorder.BorderLine.Z - 1;
- }
- if (m_scene.TestBorderCross(pos, Cardinals.N))
- {
- Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
- pos.Y = crossedBorder.BorderLine.Z - 1;
- }
- if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
- {
- m_log.WarnFormat(
- "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
- pos, Name, UUID);
- if (pos.X < 0f) pos.X = 0f;
- if (pos.Y < 0f) pos.Y = 0f;
- if (pos.Z < 0f) pos.Z = 0f;
- }
- float localAVHeight = 1.56f;
- if (m_appearance != null)
- {
- if (m_appearance.AvatarHeight > 0)
- localAVHeight = m_appearance.AvatarHeight;
- }
- {
- if(m_scene.Voxels.IsInsideTerrain(pos))
- {
- Vector3 newPos=m_scene.Voxels.FindNearestAirVoxel(pos,true);
- newPos.Z+=localAVHeight / 2;
- pos=newPos;
- }
- }
- float posZLimit = 0;
-
- AbsolutePosition = pos;
- if (m_appearance != null)
- {
- if (m_appearance.AvatarHeight > 0)
- SetHeight(m_appearance.AvatarHeight);
- }
- else
- {
- m_log.ErrorFormat("[SCENE PRESENCE]: null appearance in MakeRoot in {0}", Scene.RegionInfo.RegionName);
- // emergency; this really shouldn't happen
- m_appearance = new AvatarAppearance(UUID);
- }
-
- AddToPhysicalScene(isFlying);
- if (m_appearance != null)
- {
- if (m_appearance.AvatarHeight > 0)
- SetHeight(m_appearance.AvatarHeight);
- }
- if (m_forceFly)
- {
- m_physicsActor.Flying = true;
- }
- else if (m_flyDisabled)
- {
- m_physicsActor.Flying = false;
- }
- // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
- // avatar to return to the standing position in mid-air. On login it looks like this is being sent
- // elsewhere anyway
- // Animator.SendAnimPack();
- m_scene.SwapRootAgentCount(false);
-
- //CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid);
- //if (userInfo != null)
- // userInfo.FetchInventory();
- //else
- // m_log.ErrorFormat("[SCENE]: Could not find user info for {0} when making it a root agent", m_uuid);
-
- // On the next prim update, all objects will be sent
- //
- m_sceneViewer.Reset();
- m_isChildAgent = false;
- // send the animations of the other presences to me
- m_scene.ForEachScenePresence(delegate(ScenePresence presence)
- {
- if (presence != this)
- presence.Animator.SendAnimPackToClient(ControllingClient);
- });
- m_scene.EventManager.TriggerOnMakeRootAgent(this);
- }
- /// <summary>
- /// This turns a root agent into a child agent
- /// when an agent departs this region for a neighbor, this gets called.
- ///
- /// It doesn't get called for a teleport. Reason being, an agent that
- /// teleports out may not end up anywhere near this region
- /// </summary>
- public void MakeChildAgent()
- {
- // It looks like m_animator is set to null somewhere, and MakeChild
- // is called after that. Probably in aborted teleports.
- if (m_animator == null)
- m_animator = new ScenePresenceAnimator(this);
- else
- Animator.ResetAnimations();
- // m_log.DebugFormat(
- // "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
- // Name, UUID, m_scene.RegionInfo.RegionName);
- // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing,
- // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated.
- //Velocity = new Vector3(0, 0, 0);
-
- m_isChildAgent = true;
- m_scene.SwapRootAgentCount(true);
- RemoveFromPhysicalScene();
- // FIXME: Set m_rootRegionHandle to the region handle of the scene this agent is moving into
-
- m_scene.EventManager.TriggerOnMakeChildAgent(this);
- }
- /// <summary>
- /// Removes physics plugin scene representation of this agent if it exists.
- /// </summary>
- private void RemoveFromPhysicalScene()
- {
- if (PhysicsActor != null)
- {
- m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
- m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
- m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
- m_physicsActor.UnSubscribeEvents();
- m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
- PhysicsActor = null;
- }
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="pos"></param>
- public void Teleport(Vector3 pos)
- {
- bool isFlying = false;
- if (m_physicsActor != null)
- isFlying = m_physicsActor.Flying;
-
- RemoveFromPhysicalScene();
- Velocity = Vector3.Zero;
- AbsolutePosition = pos;
- AddToPhysicalScene(isFlying);
- if (m_appearance != null)
- {
- if (m_appearance.AvatarHeight > 0)
- SetHeight(m_appearance.AvatarHeight);
- }
- SendTerseUpdateToAllClients();
- }
- public void TeleportWithMomentum(Vector3 pos)
- {
- bool isFlying = false;
- if (m_physicsActor != null)
- isFlying = m_physicsActor.Flying;
- RemoveFromPhysicalScene();
- AbsolutePosition = pos;
- AddToPhysicalScene(isFlying);
- if (m_appearance != null)
- {
- if (m_appearance.AvatarHeight > 0)
- SetHeight(m_appearance.AvatarHeight);
- }
- SendTerseUpdateToAllClients();
- }
- /// <summary>
- ///
- /// </summary>
- public void StopMovement()
- {
- }
- public void StopFlying()
- {
- ControllingClient.StopFlying(this);
- }
- public void AddNeighbourRegion(ulong regionHandle, string cap)
- {
- lock (m_knownChildRegions)
- {
- if (!m_knownChildRegions.ContainsKey(regionHandle))
- {
- uint x, y;
- Utils.LongToUInts(regionHandle, out x, out y);
- m_knownChildRegions.Add(regionHandle, cap);
- }
- }
- }
- public void RemoveNeighbourRegion(ulong regionHandle)
- {
- lock (m_knownChildRegions)
- {
- if (m_knownChildRegions.ContainsKey(regionHandle))
- {
- m_knownChildRegions.Remove(regionHandle);
- //m_log.Debug(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count);
- }
- }
- }
- public void DropOldNeighbours(List<ulong> oldRegions)
- {
- foreach (ulong handle in oldRegions)
- {
- RemoveNeighbourRegion(handle);
- Scene.CapsModule.DropChildSeed(UUID, handle);
- }
- }
- public List<ulong> GetKnownRegionList()
- {
- return new List<ulong>(m_knownChildRegions.Keys);
- }
- #endregion
- #region Event Handlers
- /// <summary>
- /// Sets avatar height in the phyiscs plugin
- /// </summary>
- public void SetHeight(float height)
- {
- if (PhysicsActor != null && !IsChildAgent)
- {
- Vector3 SetSize = new Vector3(0.45f, 0.6f, height);
- PhysicsActor.Size = SetSize;
- }
- }
- /// <summary>
- /// Complete Avatar's movement into the region.
- /// This is called upon a very important packet sent from the client,
- /// so it's client-controlled. Never call this method directly.
- /// </summary>
- public void CompleteMovement(IClientAPI client)
- {
- DateTime startTime = DateTime.Now;
-
- m_log.DebugFormat(
- "[SCENE PRESENCE]: Completing movement of {0} into region {1}",
- client.Name, Scene.RegionInfo.RegionName);
- Vector3 look = Velocity;
- if ((look.X == 0) && (look.Y == 0) && (look.Z == 0))
- {
- look = new Vector3(0.99f, 0.042f, 0);
- }
- // Prevent teleporting to an underground location
- // (may crash client otherwise)
- //
- Vector3 pos = AbsolutePosition;
- float ground = m_scene.GetGroundHeight(pos.X, pos.Y);
- if (pos.Z < ground + 1.5f)
- {
- pos.Z = ground + 1.5f;
- AbsolutePosition = pos;
- }
- m_isChildAgent = false;
- bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
- MakeRootAgent(AbsolutePosition, m_flying);
- if ((m_callbackURI != null) && !m_callbackURI.Equals(""))
- {
- m_log.DebugFormat("[SCENE PRESENCE]: Releasing agent in URI {0}", m_callbackURI);
- Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI);
- m_callbackURI = null;
- }
- //m_log.DebugFormat("Completed movement");
- m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look);
- SendInitialData();
- // Create child agents in neighbouring regions
- if (!m_isChildAgent)
- {
- IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
- if (m_agentTransfer != null)
- m_agentTransfer.EnableChildAgents(this);
- else
- m_log.DebugFormat("[SCENE PRESENCE]: Unable to create child agents in neighbours, because AgentTransferModule is not active");
- IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
- if (friendsModule != null)
- friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
- }
- m_log.DebugFormat(
- "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
- client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds);
- }
- /// <summary>
- /// Callback for the Camera view block check. Gets called with the results of the camera view block test
- /// hitYN is true when there's something in the way.
- /// </summary>
- /// <param name="hitYN"></param>
- /// <param name="collisionPoint"></param>
- /// <param name="localid"></param>
- /// <param name="distance"></param>
- public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal)
- {
- const float POSITION_TOLERANCE = 0.02f;
- const float VELOCITY_TOLERANCE = 0.02f;
- const float ROTATION_TOLERANCE = 0.02f;
- if (m_followCamAuto)
- {
- if (hitYN)
- {
- CameraConstraintActive = true;
- //m_log.DebugFormat("[RAYCASTRESULT]: {0}, {1}, {2}, {3}", hitYN, collisionPoint, localid, distance);
-
- Vector3 normal = Vector3.Normalize(new Vector3(0f, 0f, collisionPoint.Z) - collisionPoint);
- ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint)));
- }
- else
- {
- if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
- !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
- !m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE))
- {
- if (CameraConstraintActive)
- {
- ControllingClient.SendCameraConstraint(new Vector4(0f, 0.5f, 0.9f, -3000f));
- CameraConstraintActive = false;
- }
- }
- }
- }
- }
- /// <summary>
- /// This is the event handler for client movement. If a client is moving, this event is triggering.
- /// </summary>
- public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
- {
- //if (m_isChildAgent)
- //{
- // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
- // return;
- //}
- m_perfMonMS = Util.EnvironmentTickCount();
- ++m_movementUpdateCount;
- if (m_movementUpdateCount < 1)
- m_movementUpdateCount = 1;
- #region Sanity Checking
- // This is irritating. Really.
- if (!AbsolutePosition.IsFinite())
- {
- RemoveFromPhysicalScene();
- m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
- m_pos = m_LastFinitePos;
- if (!m_pos.IsFinite())
- {
- m_pos.X = 127f;
- m_pos.Y = 127f;
- m_pos.Z = 127f;
- m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903");
- }
- AddToPhysicalScene(false);
- }
- else
- {
- m_LastFinitePos = m_pos;
- }
- #endregion Sanity Checking
- #region Inputs
- AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
- Quaternion bodyRotation = agentData.BodyRotation;
- // Camera location in world. We'll need to raytrace
- // from this location from time to time.
- m_CameraCenter = agentData.CameraCenter;
- if (Vector3.Distance(m_lastCameraCenter, m_CameraCenter) >= Scene.RootReprioritizationDistance)
- {
- ReprioritizeUpdates();
- m_lastCameraCenter = m_CameraCenter;
- }
- // Use these three vectors to figure out what the agent is looking at
- // Convert it to a Matrix and/or Quaternion
- m_CameraAtAxis = agentData.CameraAtAxis;
- m_CameraLeftAxis = agentData.CameraLeftAxis;
- m_CameraUpAxis = agentData.CameraUpAxis;
- // The Agent's Draw distance setting
- m_DrawDistance = agentData.Far;
- // Check if Client has camera in 'follow cam' or 'build' mode.
- Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation);
- m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f)
- && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
- m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
- m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
- #endregion Inputs
- if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
- {
- StandUp();
- }
- //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
- // Raycast from the avatar's head to the camera to see if there's anything blocking the view
- if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
- {
- if (m_followCamAuto)
- {
- Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
- m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
- }
- }
- lock (scriptedcontrols)
- {
- if (scriptedcontrols.Count > 0)
- {
- SendControlToScripts((uint)flags);
- flags = RemoveIgnoredControls(flags, IgnoredControls);
- }
- }
- if (m_autopilotMoving)
- CheckAtSitTarget();
- if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
- {
- // TODO: This doesn't prevent the user from walking yet.
- // Setting parent ID would fix this, if we knew what value
- // to use. Or we could add a m_isSitting variable.
- //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
- SitGround = true;
- }
- // In the future, these values might need to go global.
- // Here's where you get them.
- m_AgentControlFlags = flags;
- m_headrotation = agentData.HeadRotation;
- m_state = agentData.State;
- PhysicsActor actor = PhysicsActor;
- if (actor == null)
- {
- return;
- }
-
- bool update_movementflag = false;
- if (m_allowMovement && !SitGround)
- {
- if (agentData.UseClientAgentPosition)
- {
- m_moveToPositionInProgress = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
- m_moveToPositionTarget = agentData.ClientAgentPosition;
- }
- int i = 0;
-
- bool update_rotation = false;
- bool DCFlagKeyPressed = false;
- Vector3 agent_control_v3 = Vector3.Zero;
- Quaternion q = bodyRotation;
- bool oldflying = PhysicsActor.Flying;
- if (m_forceFly)
- actor.Flying = true;
- else if (m_flyDisabled)
- actor.Flying = false;
- else
- actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
- if (actor.Flying != oldflying)
- update_movementflag = true;
- if (q != m_bodyRot)
- {
- m_bodyRot = q;
- update_rotation = true;
- }
- if (m_parentID == 0)
- {
- bool bAllowUpdateMoveToPosition = false;
- bool bResetMoveToPosition = false;
- Vector3[] dirVectors;
- // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying
- // this prevents 'jumping' in inappropriate situations.
- if ((m_mouseLook && !m_physicsActor.Flying) || (m_leftButtonDown && !m_physicsActor.Flying))
- dirVectors = GetWalkDirectionVectors();
- else
- dirVectors = Dir_Vectors;
- // The fact that m_movementflag is a byte needs to be fixed
- // it really should be a uint
- uint nudgehack = 250;
- foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
- {
- if (((uint)flags & (uint)DCF) != 0)
- {
- bResetMoveToPosition = true;
- DCFlagKeyPressed = true;
- try
- {
- agent_control_v3 += dirVectors[i];
- //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]);
- }
- catch (IndexOutOfRangeException)
- {
- // Why did I get this?
- }
- if ((m_movementflag & (byte)(uint)DCF) == 0)
- {
- if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
- {
- m_movementflag |= (byte)nudgehack;
- }
- m_movementflag += (byte)(uint)DCF;
- update_movementflag = true;
- }
- }
- else
- {
- if ((m_movementflag & (byte)(uint)DCF) != 0 ||
- ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
- && ((m_movementflag & (byte)nudgehack) == nudgehack))
- ) // This or is for Nudge forward
- {
- m_movementflag -= ((byte)(uint)DCF);
- update_movementflag = true;
- …
Large files files are truncated, but you can click here to view the full file