Client provided parameters for avatar movement
Наследование: EventArgs
        public void TestCrossOnSameSimulator()
        {
            TestHelpers.InMethod();
//            TestHelpers.EnableLogging();

            UUID userId = TestHelpers.ParseTail(0x1);

//            TestEventQueueGetModule eqmA = new TestEventQueueGetModule();
            EntityTransferModule etmA = new EntityTransferModule();
            EntityTransferModule etmB = new EntityTransferModule();
            LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();

            IConfigSource config = new IniConfigSource();
            IConfig modulesConfig = config.AddConfig("Modules");
            modulesConfig.Set("EntityTransferModule", etmA.Name);
            modulesConfig.Set("SimulationServices", lscm.Name);
//            IConfig entityTransferConfig = config.AddConfig("EntityTransfer");

            // In order to run a single threaded regression test we do not want the entity transfer module waiting
            // for a callback from the destination scene before removing its avatar data.
//            entityTransferConfig.Set("wait_for_callback", false);

            SceneHelpers sh = new SceneHelpers();
            TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
            TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999);

            SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
            SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
//            SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA, eqmA);
            SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);

            AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
            TestClient tc = new TestClient(acd, sceneA);
            List<TestClient> destinationTestClients = new List<TestClient>();
            EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);

            ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
            originalSp.AbsolutePosition = new Vector3(128, 32, 10);

//            originalSp.Flying = true;

//            Console.WriteLine("First pos {0}", originalSp.AbsolutePosition);

//            eqmA.ClearEvents();

            AgentUpdateArgs moveArgs = new AgentUpdateArgs();
            //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero);
            moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2)));
            moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
            moveArgs.SessionID = acd.SessionID;

            originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs);

            sceneA.Update(1);

//            Console.WriteLine("Second pos {0}", originalSp.AbsolutePosition);

            // FIXME: This is a sufficient number of updates to for the presence to reach the northern border.
            // But really we want to do this in a more robust way.
            for (int i = 0; i < 100; i++)
            {
                sceneA.Update(1);
//                Console.WriteLine("Pos {0}", originalSp.AbsolutePosition);
            }

            // Need to sort processing of EnableSimulator message on adding scene presences before we can test eqm
            // messages
//            Dictionary<UUID, List<TestEventQueueGetModule.Event>> eqmEvents = eqmA.Events;
//
//            Assert.That(eqmEvents.Count, Is.EqualTo(1));
//            Assert.That(eqmEvents.ContainsKey(originalSp.UUID), Is.True);
//
//            List<TestEventQueueGetModule.Event> spEqmEvents = eqmEvents[originalSp.UUID];
//
//            Assert.That(spEqmEvents.Count, Is.EqualTo(1));
//            Assert.That(spEqmEvents[0].Name, Is.EqualTo("CrossRegion"));

            // sceneA should now only have a child agent
            ScenePresence spAfterCrossSceneA = sceneA.GetScenePresence(originalSp.UUID);
            Assert.That(spAfterCrossSceneA.IsChildAgent, Is.True);

            ScenePresence spAfterCrossSceneB = sceneB.GetScenePresence(originalSp.UUID);

            // Agent remains a child until the client triggers complete movement
            Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);

            TestClient sceneBTc = ((TestClient)spAfterCrossSceneB.ControllingClient);

            int agentMovementCompleteReceived = 0;
            sceneBTc.OnReceivedMoveAgentIntoRegion += (ri, pos, look) => agentMovementCompleteReceived++;

            sceneBTc.CompleteMovement();

            Assert.That(agentMovementCompleteReceived, Is.EqualTo(1));
            Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False);
        }
Пример #2
0
        /// <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)
        {
            bool recoverPhysActor = false;
            if (m_isChildAgent)
            {
                //m_log.Warn("[CROSSING]: HandleAgentUpdate from child agent ignored "+agentData.AgentID.ToString());
                return;
            }
            if (IsInTransit)
            {
                // m_log.Error("[CROSSING]: AgentUpdate called during transit! Ignored.");
                return;
            }

            SceneObjectPart part = m_posInfo.Parent;
            EntityBase.PositionInfo posInfo = GetPosInfo();
            if (part != null)
            {   // sitting on a prim
                if (part.ParentGroup.InTransit)
                {
                    // m_log.Warn("[CROSSING]: AgentUpdate called during prim transit! Ignored.");
                    return;
                }
            }

            if (!posInfo.Position.IsFinite())
            {
                RemoveFromPhysicalScene();
                m_log.Error("[SCENE PRESENCE]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error# 9999902");

                if (m_LastFinitePos.IsFinite())
                {
                    SetAgentPositionInfo(false, m_LastFinitePos, posInfo.Parent, Vector3.Zero, Vector3.Zero);
                }
                else
                {
                    Vector3 emergencyPos = new Vector3(127.0f, 127.0f, 127.0f);
                    SetAgentPositionInfo(false, emergencyPos, posInfo.Parent, Vector3.Zero, Vector3.Zero);
                    m_log.Error("[SCENE PRESENCE]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error# 9999903");
                }

                AddToPhysicalScene(false);
            }
            else
            {
                m_LastFinitePos = m_posInfo.Position;
            }

            m_perfMonMS = Environment.TickCount;

            uint flags = agentData.ControlFlags;
            Quaternion bodyRotation = agentData.BodyRotation;

            // Camera location in world.  We'll need to raytrace
            // from this location from time to time.

            bool doCullingCheck = false;
            bool update_rotation = false;
            if (m_sceneView != null && m_sceneView.UseCulling)
            {
                if (!m_sceneView.NeedsFullSceneUpdate && (Environment.TickCount - m_lastCullCheckMS) > 0 &&
                    Vector3.DistanceSquared(agentData.CameraCenter, m_lastCameraCenter) > m_sceneView.DistanceBeforeCullingRequired * m_sceneView.DistanceBeforeCullingRequired)
                {
                    //Check for new entities that we may now be able to see with this camera movement
                    m_lastCameraCenter = agentData.CameraCenter;
                    doCullingCheck = true;
                }
                else if (!m_sceneView.NeedsFullSceneUpdate && agentData.Far > m_DrawDistance)
                {
                    //Check to see if the draw distance has gone up
                    doCullingCheck = true;
                }
                //Do a culling check, if required
                if (doCullingCheck)
                {
                    m_sceneView.CheckForDistantEntitiesToShow();
                    //Also tell all child regions about the change
                    SendChildAgentUpdate();
                    m_lastCullCheckMS = Environment.TickCount + 1000;//Only do the camera check at the most once a sec
                }
            }



            m_CameraCenter = agentData.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;


            // check if the Agent's Draw distance setting has changed
            if (m_DrawDistance != agentData.Far)
            {
                m_DrawDistance = agentData.Far;
                m_remotePresences.HandleDrawDistanceChanged((uint)agentData.Far);
            }

            if ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
            {
                StandUp(false, true);
                bodyRotation = m_bodyRot;   // if standing, preserve the current rotation
                update_rotation = true;
            }

            m_mouseLook = (flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;

            m_leftButtonDown = (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;

            lock (m_scriptedcontrols)
            {
                if (m_scriptedcontrols.Count > 0)
                {
                    SendControlToScripts(flags);
                    flags = RemoveIgnoredControls(flags, IgnoredControls);
                }
            }

            PhysicsActor physActor = PhysicsActor;

            m_AgentControlFlags = flags;
            m_headrotation = agentData.HeadRotation;
            m_state = (AgentState)agentData.State;

            if (physActor == null)
            {
                Velocity = Vector3.Zero;
                return;
            }

            if (m_autopilotMoving)
                CheckAtSitTarget();

            if ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
            {
                m_animPersistUntil = 0;    // abort any timed animation
                TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
                m_sittingGround = true;
            }
            // In the future, these values might need to go global.
            // Here's where you get them.

            if (m_allowMovement)
            {
                bool update_movementflag = false;
                bool DCFlagKeyPressed = false;
                Vector3 agent_control_v3 = Vector3.Zero;

                // Update the physactor's rotation. This communicates the rotation to the character controller.
                physActor.Rotation = bodyRotation;

                bool oldflying = physActor.Flying;

                if (m_forceFly)
                    physActor.Flying = true;
                else if (m_flyDisabled)
                    physActor.Flying = false;
                else
                    physActor.Flying = ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);

                if (physActor.Flying != oldflying)
                {
                    update_movementflag = true;

                    if (physActor.Flying && physActor.CollidingGround)
                    {
                        physActor.AddForce(new Vector3(0f, 0f, FLY_LAUNCH_FORCE) * physActor.Mass, ForceType.GlobalLinearImpulse);
                    }
                }

                if (bodyRotation != m_bodyRot)
                {
                    m_bodyRot = bodyRotation;
                    update_rotation = true;
                }

                if (m_posInfo.Parent != null)
                {
                    // abort any automated movement
                    m_moveToPositionTarget = Vector3.Zero;
                    m_moveToPositionInProgress = false;
                    update_movementflag = true;
                }
                else
                {
                
                    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_leftButtonDown) && !physActor.Flying)
                        dirVectors = GetWalkDirectionVectors();
                    else
                        dirVectors = Dir_Vectors;

                    bool nudgeStarted = false;
                    for (int i=0; i<Dir_Flags.Length; ++i)
                    {
                        Dir_ControlFlags DCF = Dir_Flags[i];

                        if ((flags & (uint) DCF) != 0)
                        {
                            bResetMoveToPosition = true;
                            DCFlagKeyPressed = true;
                            agent_control_v3 += dirVectors[i];
                            
                            if ((m_movementflag & (uint) DCF) == 0)
                            {
                                m_movementflag += (uint)DCF & PrimaryMovements;   // This is an abomination.
                                update_movementflag = true;

                                // The viewers do not send up or down nudges.
                                if ((DCF & Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE) != 0 ||
                                    (DCF & Dir_ControlFlags.DIR_CONTROL_FLAG_REVERSE_NUDGE) != 0 ||
                                    (DCF & Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN_NUDGE) != 0 ||
                                    (DCF & Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE) != 0 ||
                                    (DCF & Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE) != 0
                                   )
                                {
                                    //when we start a nudge, we let it run for a period of time and then cancel the force
                                    _nudgeStart = (uint)Environment.TickCount;
                                    if ((DCF & Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE) != 0 ||
                                        (DCF & Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE) != 0)
                                        _nudgeDuration = NUDGE_DURATION_LR;
                                    else
                                        _nudgeDuration = NUDGE_DURATION_AT;

                                    nudgeStarted = true;
                                }
                                else
                                {
                                    if (!nudgeStarted) _nudgeStart = 0;
                                }

                                if (((DCF & Dir_ControlFlags.DIR_CONTROL_FLAG_UP) != 0) && physActor.CollidingGround && !physActor.Flying)
                                {
                                    //begin a jump
                                    physActor.AddForce(new Vector3(0.0f, 0.0f, JUMP_FORCE) * physActor.Mass, ForceType.LocalLinearImpulse);
                                }
                            }
                        }
                        else
                        {
                            if ((m_movementflag & (uint) DCF) != 0)
                            {
                                m_movementflag -= (uint) DCF & PrimaryMovements;  // This is an abomination.
                                update_movementflag = true;
                                if (!nudgeStarted) _nudgeStart = 0;
                            }
                            else
                            {
                                bAllowUpdateMoveToPosition = true;
                            }
                        }
                    }

                    //Paupaw:Do Proper PID for Autopilot here
                    if (bResetMoveToPosition)
                    {
                        m_moveToPositionTarget = Vector3.Zero;
                        m_moveToPositionInProgress = false;
                        update_movementflag = true;
                        bAllowUpdateMoveToPosition = false;
                    }

                    if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
                    {
                        //Check the error term of the current position in relation to the target position
                        if (IsAtTarget(m_moveToPositionTarget))
                        {
                            // we are close enough to the target
                            m_moveToPositionTarget = Vector3.Zero;
                            m_moveToPositionInProgress = false;
                            update_movementflag = true;
                        }
                        else
                        {
                            try
                            {
                                // move avatar in 3D at one meter/second towards target, in avatar coordinate frame.
                                // This movement vector gets added to the velocity through AddNewMovement().
                                // Theoretically we might need a more complex PID approach here if other 
                                // unknown forces are acting on the avatar and we need to adaptively respond
                                // to such forces, but the following simple approach seems to works fine.
                                Vector3 LocalVectorToTarget =
                                    (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
                                    * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
                                LocalVectorToTarget.Normalize();
                                agent_control_v3 += LocalVectorToTarget;

                                Vector3 movementPush = (m_moveToPositionTarget - AbsolutePosition);
                                movementPush.Normalize();
                                movementPush.Z *= physActor.Mass;
                                if (physActor.IsColliding)
                                    movementPush.Z *= FLY_LAUNCH_FORCE;
                                physActor.AddForce(movementPush, ForceType.GlobalLinearImpulse);

                                // update avatar movement flags. the avatar coordinate system is as follows:
                                //
                                //                        +X (forward)
                                //
                                //                        ^
                                //                        |
                                //                        |
                                //                        |
                                //                        |
                                //     (left) +Y <--------o--------> -Y
                                //                       avatar
                                //                        |
                                //                        |
                                //                        |
                                //                        |
                                //                        v
                                //                        -X
                                //

                                // based on the above avatar coordinate system, classify the movement into 
                                // one of left/right/back/forward.
                                if (LocalVectorToTarget.Y > 0)//MoveLeft
                                {
                                    m_movementflag += (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
                                    update_movementflag = true;
                                }
                                else if (LocalVectorToTarget.Y < 0) //MoveRight
                                {
                                    m_movementflag += (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
                                    update_movementflag = true;
                                }
                                if (LocalVectorToTarget.X < 0) //MoveBack
                                {
                                    m_movementflag += (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
                                    update_movementflag = true;
                                }
                                else if (LocalVectorToTarget.X > 0) //Move Forward
                                {
                                    m_movementflag += (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
                                    update_movementflag = true;
                                }
                                if (LocalVectorToTarget.Z > 0) //Up
                                {
                                    // Don't set these flags for up - doing so will make the avatar
                                    // keep trying to jump even if walking along level ground.
                                    // m_movementflag += (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_UP;
                                    update_movementflag = true;
                                }
                                else if (LocalVectorToTarget.Z < 0) //Down
                                {
                                    // Don't set these flags for down - doing so will make the avatar crouch.
                                    // m_movementflag += (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN;
                                    update_movementflag = true;
                                }
                            }
                            catch (Exception)
                            {

                                //Avoid system crash, can be slower but...
                            }

                        }
                    }

                    // Determine whether the user has said to stop and the agent is not sitting.
                    physActor.SetAirBrakes = (m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0 && !IsInTransitOnPrim && !m_moveToPositionInProgress;

                }
                
                // Cause the avatar to stop flying if it's colliding
                // with something with the down arrow pressed.

                // Only do this if we're flying
                if (physActor != null && physActor.Flying && !m_forceFly)
                {
                    // Are the landing controls requirements filled?
                    bool controlland = (((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
                                        ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));

                    // Are the collision requirements fulfilled?
                    bool colliding = (physActor.CollidingGround == true);

                    if (physActor.Flying && colliding && controlland)
                    {
                        StopFlying();
                    }
                }

                if (m_newPhysActorNeedsUpdate && physActor != null)
                    update_movementflag = true;

                if (!m_sittingGround && (update_movementflag || (update_rotation && DCFlagKeyPressed)))
                {
                    AddNewMovement(agent_control_v3, bodyRotation);

                    if (update_movementflag)
                        UpdateMovementAnimations();

                    if (physActor != null)
                        m_newPhysActorNeedsUpdate = false;
                }
                else if (update_rotation)
                {
                    //avatar is spinning with no other changes
//                    m_log.WarnFormat("[SP]: HandleAgentUpdate: Sending terse update vel={0}",this.Velocity);
                    SendTerseUpdateToAllClients();
                }
            }

            m_scene.EventManager.TriggerOnClientMovement(this);

            m_scene.StatsReporter.AddAgentTime(Environment.TickCount - m_perfMonMS);
        }
Пример #3
0
        /// <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)
            {
                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;
                                /*
                                    if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
                                    && ((m_movementflag & (byte)nudgehack) == nudgehack))
                                    {
                                        m_log.Debug("Removed Hack flag");
                                    }
                                */
                            }
                            else
                            {
                                bAllowUpdateMoveToPosition = true;
                            }
                        }
                        i++;
                    }

                    //Paupaw:Do Proper PID for Autopilot here
                    if (bResetMoveToPosition)
                    {
                        m_moveToPositionTarget = Vector3.Zero;
                        m_moveToPositionInProgress = false;
                        update_movementflag = true;
                        bAllowUpdateMoveToPosition = false;
                    }

                    if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
                    {
                        //Check the error term of the current position in relation to the target position
                        if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f)
                        {
                            // we are close enough to the target
                            m_moveToPositionTarget = Vector3.Zero;
                            m_moveToPositionInProgress = false;
                            update_movementflag = true;
                        }
                        else
                        {
                            try
                            {
                                // move avatar in 2D at one meter/second towards target, in avatar coordinate frame.
                                // This movement vector gets added to the velocity through AddNewMovement().
                                // Theoretically we might need a more complex PID approach here if other 
                                // unknown forces are acting on the avatar and we need to adaptively respond
                                // to such forces, but the following simple approach seems to works fine.
                                Vector3 LocalVectorToTarget3D =
                                    (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
                                    * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
                                // Ignore z component of vector
                                Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
                                LocalVectorToTarget2D.Normalize();
                                agent_control_v3 += LocalVectorToTarget2D;

                                // update avatar movement flags. the avatar coordinate system is as follows:
                                //
                                //                        +X (forward)
                                //
                                //                        ^
                                //                        |
                                //                        |
                                //                        |
                                //                        |
                                //     (left) +Y <--------o--------> -Y
                                //                       avatar
                                //                        |
                                //                        |
                                //                        |
                                //                        |
                                //                        v
                                //                        -X
                                //

                                // based on the above avatar coordinate system, classify the movement into 
                                // one of left/right/back/forward.
                                if (LocalVectorToTarget2D.Y > 0)//MoveLeft
                                {
                                    m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
                                    //AgentControlFlags
                                    AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
                                    update_movementflag = true;
                                }
                                else if (LocalVectorToTarget2D.Y < 0) //MoveRight
                                {
                                    m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
                                    AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
                                    update_movementflag = true;
                                }
                                if (LocalVectorToTarget2D.X < 0) //MoveBack
                                {
                                    m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
                                    AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
                                    update_movementflag = true;
                                }
                                else if (LocalVectorToTarget2D.X > 0) //Move Forward
                                {
                                    m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
                                    AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
                                    update_movementflag = true;
                                }
                            }
                            catch (Exception e)
                            {
                                //Avoid system crash, can be slower but...
                                m_log.DebugFormat("Crash! {0}", e.ToString());
                            }
                        }
                    }
                }

                // Cause the avatar to stop flying if it's colliding
                // with something with the down arrow pressed.

                // Only do this if we're flying
                if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly)
                {
                    // Landing detection code

                    // Are the landing controls requirements filled?
                    bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
                                        ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));

                    // Are the collision requirements fulfilled?
                    bool colliding = (m_physicsActor.IsColliding == true);

                    if (m_physicsActor.Flying && colliding && controlland)
                    {
                        // nesting this check because LengthSquared() is expensive and we don't 
                        // want to do it every step when flying.
                        if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
                            StopFlying();
                    }
                }

                if (update_movementflag || (update_rotation && DCFlagKeyPressed))
                {
                    //                    m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed));
                    //                    m_log.DebugFormat(
                    //                        "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);

                    AddNewMovement(agent_control_v3, q);

                    
                }
            }

            if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround)
                Animator.UpdateMovementAnimations();

            m_scene.EventManager.TriggerOnClientMovement(this);

            m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
        }
Пример #4
0
        void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
        {
            //If we are forcing a position for them to go
            if (forcedPosition.ContainsKey(remoteClient.AgentId))
            {
                ScenePresence clientAvatar = m_scene.GetScenePresence(remoteClient.AgentId);

                //Putting the user into flying, both keeps the avatar in fligth when it bumps into something and stopped from going another direction AND
                //When the avatar walks into a ban line on the ground, it prevents getting stuck
                agentData.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;

                //Make sure we stop if they get about to the right place to prevent yoyo and prevents getting stuck on banlines
                if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) < .2)
                {
//                    m_log.DebugFormat(
//                        "[LAND MANAGEMENT MODULE]: Stopping force position of {0} because {1} is close enough to {2}",
//                        clientAvatar.Name, clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]);

                    forcedPosition.Remove(remoteClient.AgentId);
                }
                //if we are far away, teleport
                else if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) > 3)
                {
                    Vector3 forcePosition = forcedPosition[remoteClient.AgentId];
//                    m_log.DebugFormat(
//                        "[LAND MANAGEMENT MODULE]: Teleporting out {0} because {1} is too far from avatar position {2}",
//                        clientAvatar.Name, clientAvatar.AbsolutePosition, forcePosition);

                    m_scene.RequestTeleportLocation(remoteClient, m_scene.RegionInfo.RegionHandle,
                        forcePosition, clientAvatar.Lookat, (uint)Constants.TeleportFlags.ForceRedirect);

                    forcedPosition.Remove(remoteClient.AgentId);
                }
                else
                {
//                    m_log.DebugFormat(
//                        "[LAND MANAGEMENT MODULE]: Forcing {0} from {1} to {2}",
//                        clientAvatar.Name, clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]);

                    //Forces them toward the forced position we want if they aren't there yet
                    agentData.UseClientAgentPosition = true;
                    agentData.ClientAgentPosition = forcedPosition[remoteClient.AgentId];
                }
            }
        }
Пример #5
0
        public void FilterAgentUpdate(IClientAPI remoteClient, OpenMetaverse.Packets.AgentUpdatePacket.AgentDataBlock x)
        {
            bool update;

            if (m_lastAgentUpdate != null)
            {
                // These should be ordered from most-likely to
                // least likely to change. I've made an initial
                // guess at that.
                update =
                   (
                    (m_moveToPositionInProgress) ||
                    (Util.NotEquals(x.BodyRotation, m_lastAgentUpdate.BodyRotation, Util.DefaultComparePrecision)) ||
                    (Util.NotEquals(x.CameraAtAxis, m_lastAgentUpdate.CameraAtAxis, Util.DefaultComparePrecision)) ||
                    (Util.NotEquals(x.CameraCenter, m_lastAgentUpdate.CameraCenter, Util.DefaultComparePrecision)) ||
                    (Util.NotEquals(x.CameraLeftAxis, m_lastAgentUpdate.CameraLeftAxis, Util.DefaultComparePrecision)) ||
                    (Util.NotEquals(x.CameraUpAxis, m_lastAgentUpdate.CameraUpAxis, Util.DefaultComparePrecision)) ||
                    (x.ControlFlags != m_lastAgentUpdate.ControlFlags) ||
                    (Util.NotEquals(x.Far, m_lastAgentUpdate.Far, Util.DefaultComparePrecision)) ||
                    (x.Flags != m_lastAgentUpdate.Flags) ||
                    (x.State != m_lastAgentUpdate.State) ||
                    (Util.NotEquals(x.HeadRotation, m_lastAgentUpdate.HeadRotation, Util.DefaultComparePrecision)) ||
                    (x.SessionID != m_lastAgentUpdate.SessionID) ||
                    (x.AgentID != m_lastAgentUpdate.AgentID)
                   );
            }
            else
            {
                update = true;
            }

            if (update)
            {
                // m_log.WarnFormat("[SCENE PRESENCE]: AgentUpdate: {0} {1} {2} {3} {4}", this.Name, x.Flags.ToString("X2"), x.ControlFlags.ToString("X8"), x.State.ToString(), this.Velocity.ToString());
                AgentUpdateArgs arg = new AgentUpdateArgs();
                arg.AgentID = x.AgentID;
                arg.BodyRotation = x.BodyRotation;
                arg.CameraAtAxis = x.CameraAtAxis;
                arg.CameraCenter = x.CameraCenter;
                arg.CameraLeftAxis = x.CameraLeftAxis;
                arg.CameraUpAxis = x.CameraUpAxis;
                arg.ControlFlags = x.ControlFlags;
                arg.Far = x.Far;
                arg.Flags = x.Flags;
                arg.HeadRotation = x.HeadRotation;
                arg.SessionID = x.SessionID;
                arg.State = x.State;

                m_lastAgentUpdate = arg; // save this set of arguments for nexttime
                HandleAgentUpdate(remoteClient, arg);
            }
        }
Пример #6
0
        /// <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)
        {
//            m_log.DebugFormat(
//                "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}",
//                Scene.Name, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);

            if (IsChildAgent)
            {
//                m_log.DebugFormat("DEBUG: HandleAgentUpdate: child agent in {0}", Scene.Name);
                return;
            }

            if (IsInTransit)
                return;

            #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;

            // The Agent's Draw distance setting
            // When we get to the point of re-computing neighbors everytime this
            // changes, then start using the agent's drawdistance rather than the 
            // region's draw distance.

            DrawDistance = agentData.Far;

            m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;

            // FIXME: This does not work as intended because the viewer only sends the lbutton down when the button
            // is first pressed, not whilst it is held down.  If this is required in the future then need to look
            // for an AGENT_CONTROL_LBUTTON_UP event and make sure to handle cases where an initial DOWN is not 
            // received (e.g. on holding LMB down on the avatar in a viewer).
            m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;

            #endregion Inputs

//            // Make anims work for client side autopilot
//            if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0)
//                m_updateCount = UPDATE_COUNT;
//
//            // Make turning in place work
//            if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0 ||
//                (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
//                m_updateCount = UPDATE_COUNT;


            if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
            {
                StandUp();
            }

            // Raycast from the avatar's head to the camera to see if there's anything blocking the view
            // this exclude checks may not be complete

            if (m_movementUpdateCount % NumMovementsBetweenRayCast == 0 && m_scene.PhysicsScene.SupportsRayCast())
            {
                if (!m_doingCamRayCast && !m_mouseLook && ParentID == 0)
                {
                    Vector3 posAdjusted = AbsolutePosition;
//                    posAdjusted.Z += 0.5f * Appearance.AvatarSize.Z - 0.5f;
                    posAdjusted.Z += 1.0f; // viewer current camera focus point
                    Vector3 tocam = CameraPosition - posAdjusted;
                    tocam.X = (float)Math.Round(tocam.X, 1);
                    tocam.Y = (float)Math.Round(tocam.Y, 1);
                    tocam.Z = (float)Math.Round(tocam.Z, 1);

                    float distTocamlen = tocam.Length();
                    if (distTocamlen > 0.3f)
                    {
                        tocam *= (1.0f / distTocamlen);
                        posAdjusted.X = (float)Math.Round(posAdjusted.X, 1);
                        posAdjusted.Y = (float)Math.Round(posAdjusted.Y, 1);
                        posAdjusted.Z = (float)Math.Round(posAdjusted.Z, 1);

                        m_doingCamRayCast = true;
                        m_scene.PhysicsScene.RaycastWorld(posAdjusted, tocam, distTocamlen + 1.0f, RayCastCameraCallback);
                    }
                }
                else if (CameraConstraintActive && (m_mouseLook || ParentID != 0))
                {
                    Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -10000f); // not right...
                    UpdateCameraCollisionPlane(plane);
                    CameraConstraintActive = false;
                }
            }

            uint flagsForScripts = (uint)flags;
            flags = RemoveIgnoredControls(flags, IgnoredControls);

            if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
                HandleAgentSitOnGround();

            // In the future, these values might need to go global.
            // Here's where you get them.
            m_AgentControlFlags = flags;
            m_headrotation = agentData.HeadRotation;
            byte oldState = State;
            State = agentData.State;

            // We need to send this back to the client in order to stop the edit beams
            if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
                SendAgentTerseUpdate(this);

            PhysicsActor actor = PhysicsActor;

            // This will be the case if the agent is sitting on the groudn or on an object.
            if (actor == null)
            {
                SendControlsToScripts(flagsForScripts);
                return;
            }

            if (AllowMovement && !SitGround)
            {
//                m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name);              
                bool update_rotation = false;
                if (agentData.BodyRotation != Rotation)
                {
                    Rotation = agentData.BodyRotation;
                    update_rotation = true;
                }

                bool update_movementflag = false;

                if (agentData.UseClientAgentPosition)
                {
                    MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
                    MoveToPositionTarget = agentData.ClientAgentPosition;
                }

                int i = 0;
                bool DCFlagKeyPressed = false;
                Vector3 agent_control_v3 = Vector3.Zero;

                bool newFlying = false;

                if (ForceFly)
                    newFlying = true;
                else if (FlyDisabled)
                    newFlying = false;
                else
                    newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);

                if (actor.Flying != newFlying)
                {
                    // Note: ScenePresence.Flying is actually fetched from the physical actor
                    //     so setting PhysActor.Flying here also sets the ScenePresence's value.
                    actor.Flying = newFlying;
                    update_movementflag = true;
                }

                if (ParentID == 0)
                {
                    bool bAllowUpdateMoveToPosition = 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 (!Flying && (m_mouseLook || m_leftButtonDown))
//                        dirVectors = GetWalkDirectionVectors();
//                    else
                        dirVectors = Dir_Vectors;

                    // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction.
                    foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
                    {
                        if (((uint)flags & (uint)DCF) != 0)
                        {
                            DCFlagKeyPressed = true;

                            try
                            {
                                agent_control_v3 += Dir_Vectors[i];
                                //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]);
                            }
                            catch (IndexOutOfRangeException)
                            {
                                // Why did I get this?
                            }

                            if (((MovementFlag & (uint)DCF) == 0))
                            {   
                                //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
                                MovementFlag |= (uint)DCF;
                                update_movementflag = true;
                            }
                        }
                        else
                        {
                            if ((MovementFlag & (uint)DCF) != 0)
                            {
                                //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
                                MovementFlag &= (uint)~DCF;
                                update_movementflag = true;

                                /*
                                    if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
                                    && ((MovementFlag & (byte)nudgehack) == nudgehack))
                                    {
                                        m_log.Debug("Removed Hack flag");
                                    }
                                */
                            }
                            else
                            {
                                bAllowUpdateMoveToPosition = true;
                            }
                        }

                        i++;
                    }

                    // Detect AGENT_CONTROL_STOP state changes
                    if (AgentControlStopActive != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0))
                    {
                        AgentControlStopActive = !AgentControlStopActive;
                        update_movementflag = true;
                    }

                    if (MovingToTarget)
                    {
                        // If the user has pressed a key then we want to cancel any move to target.
                        if (DCFlagKeyPressed)
                        {
                            ResetMoveToTarget();
                            update_movementflag = true;
                        }
                        else if (bAllowUpdateMoveToPosition)
                        {
                            // The UseClientAgentPosition is set if parcel ban is forcing the avatar to move to a
                            // certain position.  It's only check for tolerance on returning to that position is 0.2
                            // rather than 1, at which point it removes its force target.
                            if (HandleMoveToTargetUpdate(agentData.UseClientAgentPosition ? 0.2 : 1, ref agent_control_v3))
                                update_movementflag = true;
                        }
                    }
                }

                // Cause the avatar to stop flying if it's colliding
                // with something with the down arrow pressed.

                // Only do this if we're flying
                if (Flying && !ForceFly)
                {
                    // Need to stop in mid air if user holds down AGENT_CONTROL_STOP
                    //                    if (AgentControlStopActive)
                    //                    {
                    //                        agent_control_v3 = Vector3.Zero;
                    //                    }
                    //                    else
                    {
                        // Landing detection code

                        // Are the landing controls requirements filled?
                        bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
                                            ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));

                        //m_log.Debug("[CONTROL]: " +flags);
                        // Applies a satisfying roll effect to the avatar when flying.
                        if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
                        {
                            ApplyFlyingRoll(
                                FLY_ROLL_RADIANS_PER_UPDATE,
                                (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
                                (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
                        }
                        else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
                                 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
                        {
                            ApplyFlyingRoll(
                                -FLY_ROLL_RADIANS_PER_UPDATE,
                                (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
                                (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
                        }
                        else
                        {
                            if (m_AngularVelocity.Z != 0)
                                m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
                        }
                        
                        /*
                                                if (Flying && IsColliding && controlland)
                                                {
                                                    // nesting this check because LengthSquared() is expensive and we don't 
                                                    // want to do it every step when flying.
                                                    if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
                                                        StopFlying();
                                                }
                         */
                    }
                }
                else if (IsColliding && agent_control_v3.Z < 0f)
                    agent_control_v3.Z = 0;
//                else if(AgentControlStopActive %% Velocity.Z <0.01f)
                    

//                m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);

                // If the agent update does move the avatar, then calculate the force ready for the velocity update,
                // which occurs later in the main scene loop
                // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they
                // held down AGENT_CONTROL_STOP whilst normal walking/running).  However, we do not want to update
                // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the 
                // avatar location in place).
                if (update_movementflag 
                    || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
                {

                    if (AgentControlStopActive)
                    {
                        //                        if (MovementFlag == 0 && Animator.Falling)
                        if (MovementFlag == 0 && Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling)
                        {
                            AddNewMovement(agent_control_v3, AgentControlStopSlowVel, true);
                        }
                        else
                            AddNewMovement(agent_control_v3, AgentControlStopSlowVel);
                    }
                    else
                    {
                        AddNewMovement(agent_control_v3);
                    }

                }

                if (update_movementflag && ParentID == 0)
                {
//                    m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name);
                    Animator.UpdateMovementAnimations();
                }

                SendControlsToScripts(flagsForScripts);
            }

            // We need to send this back to the client in order to see the edit beams
            if ((State & (uint)AgentState.Editing) != 0)
                SendAgentTerseUpdate(this);

            m_scene.EventManager.TriggerOnClientMovement(this);
        }
Пример #7
0
        public void OnBotAgentUpdate(ScenePresence presence, Vector3 toward, uint controlFlag, Quaternion bodyRotation, bool isMoving)
        {
            if (m_controller.Bot.Frozen && isMoving)
            {
                var pa = presence.PhysicsActor;
                bool fly = pa != null && pa.Flying;
                StopMoving(presence, fly, false);
                return;
            }

            if (isMoving)
                m_hasStoppedMoving = false;
            AgentUpdateArgs pack = new AgentUpdateArgs { ControlFlags = controlFlag, BodyRotation = bodyRotation };
            presence.HandleAgentUpdate(presence.ControllingClient, pack);
        }
Пример #8
0
        private void RealHandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
        {
            //if (m_isChildAgent)
            //{
            //    // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
            //    return;
            //}

            
            m_movementUpdateCount++;
            if (m_movementUpdateCount >= int.MaxValue)
                m_movementUpdateCount = 1;


            // Must check for standing up even when PhysicsActor is null,
            // since sitting currently removes avatar from physical scene
            //m_log.Debug("agentPos:" + AbsolutePosition.ToString());

            // 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;
            }
            //m_physicsActor.AddForce(new PhysicsVector(999999999, 99999999, 999999999999999), true);


            //ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
            //if (land != null)
            //{
                //if (land.landData.landingType == (byte)1 && land.landData.userLocation != Vector3.Zero)
                //{
                //    agent.startpos = land.landData.userLocation;
                //}
            //}

            m_perfMonMS = Environment.TickCount;

            uint flags = 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;

            // 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;

            if ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
            {
                StandUp();
            }                       

            // 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_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 headadjustment = new Vector3(0, 0, 0.3f);
                    m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - (m_pos + headadjustment)), Vector3.Distance(m_CameraCenter, (m_pos + headadjustment)) + 0.3f, RayCastCameraCallback);
                }
            }

            m_mouseLook = (flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;

            

            m_leftButtonDown = (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;

           

            lock (scriptedcontrols)
            {
                if (scriptedcontrols.Count > 0)
                {
                    SendControlToScripts(flags);
                    flags = RemoveIgnoredControls(flags, IgnoredControls);

                }
            }
            
            if (PhysicsActor == null)
            {
                return;
            }

            if (m_autopilotMoving)
                CheckAtSitTarget();

            if ((flags & (uint) 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.

                TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
            }
            // 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;

            if (m_allowMovement)
            {
                int i = 0;
                bool update_movementflag = false;
                bool update_rotation = false;
                bool DCFlagKeyPressed = false;
                Vector3 agent_control_v3 = new Vector3(0, 0, 0);
                Quaternion q = bodyRotation;
                if (PhysicsActor != null)
                {
                    bool oldflying = PhysicsActor.Flying;

                    if (m_forceFly)
                        PhysicsActor.Flying = true;
                    else if (m_flyDisabled)
                        PhysicsActor.Flying = false;
                    else
                        PhysicsActor.Flying = ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
                    
                    if (PhysicsActor.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;


                    foreach (Dir_ControlFlags DCF in Enum.GetValues(typeof (Dir_ControlFlags)))
                    {
                        if ((flags & (uint) DCF) != 0)
                        {
                            bResetMoveToPosition = true;
                            DCFlagKeyPressed = true;
                            try
                            {
                                agent_control_v3 += dirVectors[i];
                            }
                            catch (IndexOutOfRangeException)
                            {
                                // Why did I get this?
                            }
                            
                            if ((m_movementflag & (uint) DCF) == 0)
                            {
                                m_movementflag += (byte) (uint) DCF;
                                update_movementflag = true;
                            }
                        }
                        else
                        {
                            if ((m_movementflag & (uint) DCF) != 0)
                            {
                                m_movementflag -= (byte) (uint) DCF;
                                update_movementflag = true;
                            }
                            else
                            {
                                bAllowUpdateMoveToPosition = true;
                            }
                        }
                        i++;
                    }

                    //Paupaw:Do Proper PID for Autopilot here
                    if (bResetMoveToPosition)
                    {
                        m_moveToPositionTarget = Vector3.Zero;
                        m_moveToPositionInProgress = false;
                        update_movementflag = true;
                        bAllowUpdateMoveToPosition = false;
                    }

                    if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
                    {
                        //Check the error term of the current position in relation to the target position
                        if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 1.5)
                        {
                            // we are close enough to the target
                            m_moveToPositionTarget = Vector3.Zero;
                            m_moveToPositionInProgress = false;
                            update_movementflag = true;
                        }
                        else
                        {
                            try
                            {
                                // move avatar in 2D at one meter/second towards target, in avatar coordinate frame.
                                // This movement vector gets added to the velocity through AddNewMovement().
                                // Theoretically we might need a more complex PID approach here if other 
                                // unknown forces are acting on the avatar and we need to adaptively respond
                                // to such forces, but the following simple approach seems to works fine.
                                Vector3 LocalVectorToTarget3D =
                                    (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
                                    * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
                                // Ignore z component of vector
                                Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
                                LocalVectorToTarget2D.Normalize();
                                agent_control_v3 += LocalVectorToTarget2D;

                                // update avatar movement flags. the avatar coordinate system is as follows:
                                //
                                //                        +X (forward)
                                //
                                //                        ^
                                //                        |
                                //                        |
                                //                        |
                                //                        |
                                //     (left) +Y <--------o--------> -Y
                                //                       avatar
                                //                        |
                                //                        |
                                //                        |
                                //                        |
                                //                        v
                                //                        -X
                                //

                                // based on the above avatar coordinate system, classify the movement into 
                                // one of left/right/back/forward.
                                if (LocalVectorToTarget2D.Y > 0)//MoveLeft
                                {
                                    m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
                                    update_movementflag = true;
                                }
                                else if (LocalVectorToTarget2D.Y < 0) //MoveRight
                                {
                                    m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
                                    update_movementflag = true;
                                }
                                if (LocalVectorToTarget2D.X < 0) //MoveBack
                                {
                                    m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
                                    update_movementflag = true;
                                }
                                else if (LocalVectorToTarget2D.X > 0) //Move Forward
                                {
                                    m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
                                    update_movementflag = true;
                                }
                            }
                            catch (Exception)
                            {

                                //Avoid system crash, can be slower but...
                            }

                        }
                    }
                }
                
                // Cause the avatar to stop flying if it's colliding
                // with something with the down arrow pressed.

                // Only do this if we're flying
                if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly)
                {
                    // Are the landing controls requirements filled?
                    bool controlland = (((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
                                        ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));

                    // Are the collision requirements fulfilled?
                    bool colliding = (m_physicsActor.IsColliding == true);

                    if (m_physicsActor.Flying && colliding && controlland)
                    {
                        StopFlying();
                    }
                }

                if (update_movementflag || (update_rotation && DCFlagKeyPressed))
                {
//                    m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed));
//                    m_log.DebugFormat(
//                        "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);                    
                    
                    AddNewMovement(agent_control_v3, q);

                    if (update_movementflag)
                        UpdateMovementAnimations();
                }
            }

            m_scene.EventManager.TriggerOnClientMovement(this);

            m_scene.StatsReporter.AddAgentTime(Environment.TickCount - m_perfMonMS);
        }
Пример #9
0
        /// <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)
        {
            //m_log.DebugFormat(
            //    "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}",
            //    Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);

            if (IsChildAgent)
            {
            //    // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
                return;
            }

            #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;

            // The Agent's Draw distance setting
            // When we get to the point of re-computing neighbors everytime this
            // changes, then start using the agent's drawdistance rather than the 
            // region's draw distance.
            // DrawDistance = agentData.Far;
            DrawDistance = Scene.DefaultDrawDistance;

            m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
            m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;

            #endregion Inputs

//            // Make anims work for client side autopilot
//            if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0)
//                m_updateCount = UPDATE_COUNT;
//
//            // Make turning in place work
//            if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0 ||
//                (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
//                m_updateCount = UPDATE_COUNT;

            if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
            {
                StandUp();
            }

            uint flagsForScripts = (uint)flags;
            flags = RemoveIgnoredControls(flags, IgnoredControls);

            if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
                HandleAgentSitOnGround();

            // In the future, these values might need to go global.
            // Here's where you get them.
            m_AgentControlFlags = flags;
            m_headrotation = agentData.HeadRotation;
            byte oldState = State;
            State = agentData.State;

            // We need to send this back to the client in order to stop the edit beams
            if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
                ControllingClient.SendAgentTerseUpdate(this);


            PhysicsActor actor = PhysicsActor;
            if (actor == null)
            {
                SendControlsToScripts(flagsForScripts);
                return;
            }

            if (AllowMovement && !SitGround)
            {
                Quaternion bodyRotation = agentData.BodyRotation;
                bool update_rotation = false;

                if (bodyRotation != Rotation)
                {
                    Rotation = bodyRotation;
                    update_rotation = true;
                }

                bool update_movementflag = false;

                if (agentData.UseClientAgentPosition)
                {
                    MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
                    MoveToPositionTarget = agentData.ClientAgentPosition;
                }

                int i = 0;
                bool DCFlagKeyPressed = false;
                Vector3 agent_control_v3 = Vector3.Zero;

                bool newFlying = actor.Flying;

                if (ForceFly)
                    newFlying = true;
                else if (FlyDisabled)
                    newFlying = false;
                else
                    newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);

                if (actor.Flying != newFlying)
                {
                    // Note: ScenePresence.Flying is actually fetched from the physical actor
                    //     so setting PhysActor.Flying here also sets the ScenePresence's value.
                    actor.Flying = newFlying;
                    update_movementflag = true;
                }

                if (ParentID == 0)
                {
                    bool bAllowUpdateMoveToPosition = 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 (!Flying && (m_mouseLook || m_leftButtonDown))
                        dirVectors = GetWalkDirectionVectors();
                    else
                        dirVectors = Dir_Vectors;

                    // The fact that MovementFlag is a byte needs to be fixed
                    // it really should be a uint
                    // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction.
                    uint nudgehack = 250;
                    foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
                    {
                        if (((uint)flags & (uint)DCF) != 0)
                        {
                            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 ((MovementFlag & (byte)(uint)DCF) == 0)
                            {
                                if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
                                    DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
                                {
                                    MovementFlag |= (byte)nudgehack;
                                }

                                //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
                                MovementFlag += (byte)(uint)DCF;
                                update_movementflag = true;
                            }
                        }
                        else
                        {
                            if ((MovementFlag & (byte)(uint)DCF) != 0 ||
                                ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
                                DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
                                && ((MovementFlag & (byte)nudgehack) == nudgehack))
                                ) // This or is for Nudge forward
                            {
                                //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
                                MovementFlag -= ((byte)(uint)DCF);
                                update_movementflag = true;

                                /*
                                    if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
                                    && ((MovementFlag & (byte)nudgehack) == nudgehack))
                                    {
                                        m_log.Debug("Removed Hack flag");
                                    }
                                */
                            }
                            else
                            {
                                bAllowUpdateMoveToPosition = true;
                            }
                        }

                        i++;
                    }

                    if (MovingToTarget)
                    {
                        // If the user has pressed a key then we want to cancel any move to target.
                        if (DCFlagKeyPressed)
                        {
                            ResetMoveToTarget();
                            update_movementflag = true;
                        }
                        else if (bAllowUpdateMoveToPosition)
                        {
                            // The UseClientAgentPosition is set if parcel ban is forcing the avatar to move to a
                            // certain position.  It's only check for tolerance on returning to that position is 0.2
                            // rather than 1, at which point it removes its force target.
                            if (HandleMoveToTargetUpdate(agentData.UseClientAgentPosition ? 0.2 : 1, ref agent_control_v3))
                                update_movementflag = true;
                        }
                    }
                }

                // Cause the avatar to stop flying if it's colliding
                // with something with the down arrow pressed.

                // Only do this if we're flying
                if (Flying && !ForceFly)
                {
                    // Landing detection code

                    // Are the landing controls requirements filled?
                    bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
                                        ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));

                   //m_log.Debug("[CONTROL]: " +flags);
                    // Applies a satisfying roll effect to the avatar when flying.
                    if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
                    {
                        ApplyFlyingRoll(
                            FLY_ROLL_RADIANS_PER_UPDATE, 
                            (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, 
                            (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
                    } 
                    else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
                             (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
                    {
                        ApplyFlyingRoll(
                            -FLY_ROLL_RADIANS_PER_UPDATE, 
                            (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, 
                            (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);                      
                    }
                    else
                    {
                        if (m_AngularVelocity.Z != 0)
                            m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);                        
                    }                  

                    if (Flying && IsColliding && controlland)
                    {
                        // nesting this check because LengthSquared() is expensive and we don't 
                        // want to do it every step when flying.
                        if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
                            StopFlying();
                    }
                }

                // If the agent update does move the avatar, then calculate the force ready for the velocity update,
                // which occurs later in the main scene loop
                if (update_movementflag || (update_rotation && DCFlagKeyPressed))
                {
//                    m_log.DebugFormat(
//                        "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}",
//                        m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation);

                    AddNewMovement(agent_control_v3);
                }
//                else
//                {
//                    if (!update_movementflag)
//                    {
//                        m_log.DebugFormat(
//                            "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false",
//                            m_scene.RegionInfo.RegionName, agent_control_v3, Name);
//                    }
//                }

                if (update_movementflag && ParentID == 0)
                    Animator.UpdateMovementAnimations();

                SendControlsToScripts(flagsForScripts);
            }

            // We need to send this back to the client in order to see the edit beams
            if ((State & (uint)AgentState.Editing) != 0)
                ControllingClient.SendAgentTerseUpdate(this);

            m_scene.EventManager.TriggerOnClientMovement(this);
        }
        public void TestCrossOnSameSimulatorNoRootDestPerm()
        {
            TestHelpers.InMethod();
//            TestHelpers.EnableLogging();

            UUID userId = TestHelpers.ParseTail(0x1);

            EntityTransferModule etmA = new EntityTransferModule();
            EntityTransferModule etmB = new EntityTransferModule();
            LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();

            IConfigSource config = new IniConfigSource();
            IConfig modulesConfig = config.AddConfig("Modules");
            modulesConfig.Set("EntityTransferModule", etmA.Name);
            modulesConfig.Set("SimulationServices", lscm.Name);

            SceneHelpers sh = new SceneHelpers();
            TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
            TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999);

            SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
            SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);

            // We need to set up the permisions module on scene B so that our later use of agent limit to deny
            // QueryAccess won't succeed anyway because administrators are always allowed in and the default
            // IsAdministrator if no permissions module is present is true.
            SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new DefaultPermissionsModule(), etmB);

            AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
            TestClient tc = new TestClient(acd, sceneA);
            List<TestClient> destinationTestClients = new List<TestClient>();
            EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);

            // Make sure sceneB will not accept this avatar.
            sceneB.RegionInfo.EstateSettings.PublicAccess = false;

            ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
            originalSp.AbsolutePosition = new Vector3(128, 32, 10);

            AgentUpdateArgs moveArgs = new AgentUpdateArgs();
            //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero);
            moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2)));
            moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
            moveArgs.SessionID = acd.SessionID;

            originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs);

            sceneA.Update(1);

//            Console.WriteLine("Second pos {0}", originalSp.AbsolutePosition);

            // FIXME: This is a sufficient number of updates to for the presence to reach the northern border.
            // But really we want to do this in a more robust way.
            for (int i = 0; i < 100; i++)
            {
                sceneA.Update(1);
//                Console.WriteLine("Pos {0}", originalSp.AbsolutePosition);
            }

            // sceneA agent should still be root
            ScenePresence spAfterCrossSceneA = sceneA.GetScenePresence(originalSp.UUID);
            Assert.That(spAfterCrossSceneA.IsChildAgent, Is.False);

            ScenePresence spAfterCrossSceneB = sceneB.GetScenePresence(originalSp.UUID);

            // sceneB agent should still be child
            Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);

            // sceneB should ignore unauthorized attempt to upgrade agent to root
            TestClient sceneBTc = ((TestClient)spAfterCrossSceneB.ControllingClient);

            int agentMovementCompleteReceived = 0;
            sceneBTc.OnReceivedMoveAgentIntoRegion += (ri, pos, look) => agentMovementCompleteReceived++;

            sceneBTc.CompleteMovement();

            Assert.That(agentMovementCompleteReceived, Is.EqualTo(0));
            Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
        }
Пример #11
0
 /// <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)
 {
     lock (m_agentUpdates)
     {
         if (m_updatesAllowed)
         {
             RealHandleAgentUpdate(remoteClient, agentData);
             return;
         }
         
         m_agentUpdates.Add(agentData);
     }
 }
        void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
        {
            //If we are forcing a position for them to go
            if (forcedPosition != null)
            {
                ScenePresence clientAvatar = m_scene.GetScenePresence(remoteClient.AgentId);

                //Putting the user into flying, both keeps the avatar in fligth when it bumps into something and stopped from going another direction AND
                //When the avatar walks into a ban line on the ground, it prevents getting stuck
                agentData.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;


                //Make sure we stop if they get about to the right place to prevent yoyo and prevents getting stuck on banlines
                if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition.Value) < .2)
                {
                    Debug.WriteLine(string.Format("Stopping force position because {0} is close enough to position {1}", forcedPosition.Value, clientAvatar.AbsolutePosition));
                    forcedPosition = null;
                }
                //if we are far away, teleport 
                else if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition.Value) > 3)
                {
                    Debug.WriteLine(string.Format("Teleporting out because {0} is too far from avatar position {1}", forcedPosition.Value, clientAvatar.AbsolutePosition));
                    clientAvatar.Teleport(forcedPosition.Value);
                    forcedPosition = null;
                }
                else
                {
                    //Forces them toward the forced position we want if they aren't there yet
                    agentData.UseClientAgentPosition = true;
                    agentData.ClientAgentPosition = forcedPosition.Value;
                }
            }
        }
Пример #13
0
 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
 {
 }
Пример #14
0
        // Some presence property has changed. Generate a call into the scene presence
        // so the new values are evaluated (like AgentControlFlags).
        // The ScenePresence will trigger OnScenePresenceUpdated and we rely on the
        // fact that the values will all be equal to supress the generation of a
        // new outgoing property update message.
        private void GenerateAgentUpdated(ScenePresence sp)
        {
            // The call for the change of these values comes out of the client view
            // which has an OnAgentUpdate event that the scene presence connects to.
            // We can't use the OnAgentUpdate event subscription (we're not derived
            // from client view) so we fake the reception of a presenece changing
            // message by building up the parameter block and directly calling the
            // ScenePresence's handling routine.
            AgentUpdateArgs aua = new AgentUpdateArgs();

            aua.AgentID = sp.UUID;
            aua.BodyRotation = sp.Rotation;
            aua.CameraAtAxis = sp.CameraAtAxis;
            aua.CameraCenter = sp.CameraPosition;
            aua.CameraLeftAxis = sp.CameraLeftAxis;
            aua.CameraUpAxis = sp.CameraUpAxis;
            aua.ClientAgentPosition = sp.AbsolutePosition;
            aua.ControlFlags = sp.AgentControlFlags;
            aua.Far = sp.DrawDistance;
            aua.Flags = 0;
            aua.HeadRotation = sp.Rotation; // this is wrong but the only thing we can do
            aua.State = sp.State;
            aua.UseClientAgentPosition = true;

            sp.HandleAgentUpdate(null, aua);
        }
Пример #15
0
        /// <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)
        {
//            m_log.DebugFormat(
//                "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}",
//                Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);

            if (IsChildAgent)
            {
            //    // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
                return;
            }

            ++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;

            // Camera location in world.  We'll need to raytrace
            // from this location from time to time.
            CameraPosition = agentData.CameraCenter;
            if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
            {
                ReprioritizeUpdates();
                m_lastCameraPosition = CameraPosition;
            }

            // Use these three vectors to figure out what the agent is looking at
            // Convert it to a Matrix and/or Quaternion
            CameraAtAxis = agentData.CameraAtAxis;
            CameraLeftAxis = agentData.CameraLeftAxis;
            CameraUpAxis = agentData.CameraUpAxis;

            // The Agent's Draw distance setting
            // When we get to the point of re-computing neighbors everytime this
            // changes, then start using the agent's drawdistance rather than the 
            // region's draw distance.
            // DrawDistance = agentData.Far;
            DrawDistance = Scene.DefaultDrawDistance;

            // Check if Client has camera in 'follow cam' or 'build' mode.
            Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);

            m_followCamAuto = ((CameraUpAxis.Z > 0.959f && 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

//            // Make anims work for client side autopilot
//            if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0)
//                m_updateCount = UPDATE_COUNT;
//
//            // Make turning in place work
//            if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0 ||
//                (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
//                m_updateCount = UPDATE_COUNT;

            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(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
                }
            }

            uint flagsForScripts = (uint)flags;
            flags = RemoveIgnoredControls(flags, IgnoredControls);

            if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
                HandleAgentSitOnGround();

            // In the future, these values might need to go global.
            // Here's where you get them.
            m_AgentControlFlags = flags;
            m_headrotation = agentData.HeadRotation;
            State = agentData.State;

            PhysicsActor actor = PhysicsActor;
            if (actor == null)
            {
                SendControlsToScripts(flagsForScripts);
                return;
            }

            if (AllowMovement && !SitGround)
            {
                Quaternion bodyRotation = agentData.BodyRotation;
                bool update_rotation = false;

                if (bodyRotation != Rotation)
                {
                    Rotation = bodyRotation;
                    update_rotation = true;
                }

                bool update_movementflag = false;

                if (agentData.UseClientAgentPosition)
                {
                    MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
                    MoveToPositionTarget = agentData.ClientAgentPosition;
                }

                int i = 0;
                bool DCFlagKeyPressed = false;
                Vector3 agent_control_v3 = Vector3.Zero;

                bool newFlying = actor.Flying;

                if (ForceFly)
                    newFlying = true;
                else if (FlyDisabled)
                    newFlying = false;
                else
                    newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);

                if (actor.Flying != newFlying)
                {
                    // Note: ScenePresence.Flying is actually fetched from the physical actor
                    //     so setting PhysActor.Flying here also sets the ScenePresence's value.
                    actor.Flying = newFlying;
                    update_movementflag = true;
                }

                if (ParentID == 0)
                {
                    bool bAllowUpdateMoveToPosition = 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 (!Flying && (m_mouseLook || m_leftButtonDown))
                        dirVectors = GetWalkDirectionVectors();
                    else
                        dirVectors = Dir_Vectors;

                    // The fact that MovementFlag is a byte needs to be fixed
                    // it really should be a uint
                    // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction.
                    uint nudgehack = 250;
                    foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
                    {
                        if (((uint)flags & (uint)DCF) != 0)
                        {
                            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 ((MovementFlag & (byte)(uint)DCF) == 0)
                            {
                                if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
                                    DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
                                {
                                    MovementFlag |= (byte)nudgehack;
                                }

                                //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
                                MovementFlag += (byte)(uint)DCF;
                                update_movementflag = true;
                            }
                        }
                        else
                        {
                            if ((MovementFlag & (byte)(uint)DCF) != 0 ||
                                ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
                                DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
                                && ((MovementFlag & (byte)nudgehack) == nudgehack))
                                ) // This or is for Nudge forward
                            {
                                //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
                                MovementFlag -= ((byte)(uint)DCF);
                                update_movementflag = true;

                                /*
                                    if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
                                    && ((MovementFlag & (byte)nudgehack) == nudgehack))
                                    {
                                        m_log.Debug("Removed Hack flag");
                                    }
                                */
                            }
                            else
                            {
                                bAllowUpdateMoveToPosition = true;
                            }
                        }

                        i++;
                    }

                    if (MovingToTarget)
                    {
                        // If the user has pressed a key then we want to cancel any move to target.
                        if (DCFlagKeyPressed)
                        {
                            ResetMoveToTarget();
                            update_movementflag = true;
                        }
                        else if (bAllowUpdateMoveToPosition)
                        {
                            // The UseClientAgentPosition is set if parcel ban is forcing the avatar to move to a
                            // certain position.  It's only check for tolerance on returning to that position is 0.2
                            // rather than 1, at which point it removes its force target.
                            if (HandleMoveToTargetUpdate(agentData.UseClientAgentPosition ? 0.2 : 1, ref agent_control_v3))
                                update_movementflag = true;
                        }
                    }
                }

                // Cause the avatar to stop flying if it's colliding
                // with something with the down arrow pressed.

                // Only do this if we're flying
                if (Flying && !ForceFly)
                {
                    // Landing detection code

                    // Are the landing controls requirements filled?
                    bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
                                        ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));

                    if (Flying && IsColliding && controlland)
                    {
                        // nesting this check because LengthSquared() is expensive and we don't 
                        // want to do it every step when flying.
                        if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
                            StopFlying();
                    }
                }

                // If the agent update does move the avatar, then calculate the force ready for the velocity update,
                // which occurs later in the main scene loop
                if (update_movementflag || (update_rotation && DCFlagKeyPressed))
                {
//                    m_log.DebugFormat(
//                        "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}",
//                        m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation);

                    AddNewMovement(agent_control_v3);
                }
//                else
//                {
//                    if (!update_movementflag)
//                    {
//                        m_log.DebugFormat(
//                            "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false",
//                            m_scene.RegionInfo.RegionName, agent_control_v3, Name);
//                    }
//                }

                if (update_movementflag && ParentID == 0)
                    Animator.UpdateMovementAnimations();

                SendControlsToScripts(flagsForScripts);
            }

            m_scene.EventManager.TriggerOnClientMovement(this);
            TriggerScenePresenceUpdated();
        }
Пример #16
0
 protected virtual void OnBotAgentUpdate(uint controlFlag, Quaternion bodyRotation)
 {
     if (OnAgentUpdate != null)
     {
         AgentUpdateArgs pack = new AgentUpdateArgs();
         pack.ControlFlags = controlFlag;
         pack.BodyRotation = bodyRotation;
         OnAgentUpdate(this, pack);
     }
 }
Пример #17
0
        private void Update()
        {
            frame++;
            if (frame > 20)
            {
                frame = 0;
                if (OnAgentUpdate != null)
                {
                    AgentUpdateArgs pack = new AgentUpdateArgs();
                    pack.ControlFlags = movementFlag;
                    pack.BodyRotation = bodyDirection;

                    OnAgentUpdate(this, pack);
                }
                if (flyState == 0)
                {
                    movementFlag = (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY |
                                   (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG;
                    flyState = 1;
                }
                else if (flyState == 1)
                {
                    movementFlag = (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY |
                                   (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
                    flyState = 2;
                }
                else
                {
                    movementFlag = (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
                    flyState = 0;
                }

                if (count >= 10)
                {
                    if (OnChatFromClient != null)
                    {
                        OSChatMessage args = new OSChatMessage();
                        args.Message = "Hey You! Get out of my Home. This is my Region";
                        args.Channel = 0;
                        args.From = FirstName + " " + LastName;
                        args.Scene = m_scene;
                        args.Position = new Vector3(128, 128, 26);
                        args.Sender = this;
                        args.Type = ChatTypeEnum.Shout;

                        OnChatFromClient(this, args);
                    }
                    count = -1;
                }

                count++;
            }
        }
Пример #18
0
        /// <summary>
        /// This is the event handler for client movement. If a client is moving, this event is triggering.
        /// </summary>
        public virtual void HandleAgentUpdate (IClientAPI remoteClient, AgentUpdateArgs agentData)
        {
            m_perfMonMS = Util.EnvironmentTickCount();

            ++m_movementUpdateCount;
            if (m_movementUpdateCount < 1)
                m_movementUpdateCount = 1;

            #region Sanity Checking

            // This is irritating.  Really.
            if (!AbsolutePosition.IsFinite())
            {
                OutOfBoundsCall(Vector3.Zero);
                return;
            }

            #endregion Sanity Checking

            #region Inputs

            if (Frozen)
                return; //Do nothing, just end

            AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
            Quaternion bodyRotation = agentData.BodyRotation;

            //Check to see whether ray casting needs done
            // We multiply by 10 so that we don't trigger it when the camera moves slightly (as its 2 meter change)
            if (Util.GetFlatDistanceTo(agentData.CameraCenter, m_lastCameraCenter) > SIGNIFICANT_MOVEMENT * 10)
            {
                m_lastCameraCenter = agentData.CameraCenter;
                Scene.AuroraEventManager.FireGenericEventHandler("SignficantCameraMovement", this);
            }

            // Camera location in world.  We'll need to raytrace
            // from this location from time to time.
            m_CameraCenter = agentData.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
            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));

            m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
            m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
            m_isAway = (flags & AgentManager.ControlFlags.AGENT_CONTROL_AWAY) != 0;
            #endregion Inputs

            if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
            {
                StandUp();
            }

            //MainConsole.Instance.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);
                }
            }
            if (!m_CameraCenter.IsFinite())
            {
                m_CameraCenter = new Vector3(128, 128, 128);
            }

            IScriptControllerModule m = RequestModuleInterface<IScriptControllerModule> ();
            if (m != null) //Tell any scripts about it
                m.OnNewMovement (ref flags);

            if (m_autopilotMoving)
                CheckAtSitTarget();

            // In the future, these values might need to go global.
            // Here's where you get them.
            if (!SitGround)
                SitGround = (flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0;
            m_AgentControlFlags = flags;
            m_headrotation = agentData.HeadRotation;
            m_state = agentData.State;

            PhysicsCharacter actor = PhysicsActor;
            if (actor == null)
            {
                //This happens while sitting, don't spam it
                //MainConsole.Instance.Debug("Null physical actor in AgentUpdate in " + m_scene.RegionInfo.RegionName);
                return;
            }
            
            bool update_movementflag = false;

            if (AllowMovement && !SitGround && !Frozen)
            {
                if (FallenStandUp)
                {
                    //Poke the animator a bit
                    Animator.UpdateMovementAnimations(false);
                    m_bodyRot = bodyRotation;
                    AddNewMovement (Vector3.Zero, bodyRotation);
                    return;
                }
                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 == UUID.Zero)
                {
                    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
                    const uint nudgehack = 250;
                    //Do these two like this to block out all others because it will slow it down
                    if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS)
                    {
                        bResetMoveToPosition = true;
                        DCFlagKeyPressed = true;
                        agent_control_v3 += dirVectors[8];
                    }
                    else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG)
                    {
                        bResetMoveToPosition = true;
                        DCFlagKeyPressed = true;
                        agent_control_v3 += dirVectors[9];
                    }
                    else
                    {
                        foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
                        {
                            if (((uint)flags & (uint)DCF) != 0)
                            {
                                bResetMoveToPosition = true;
                                DCFlagKeyPressed = true;
                                agent_control_v3 += dirVectors[i];
                                //MainConsole.Instance.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]);

                                if ((m_movementflag & (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 |= nudgehack;
                                    }
                                    m_movementflag += (uint)DCF;
                                    update_movementflag = true;
                                }
                            }
                            else
                            {
                                if ((m_movementflag & (uint)DCF) != 0 ||
                                    ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
                                    && ((m_movementflag & nudgehack) == nudgehack))
                                    ) // This or is for Nudge forward
                                {
                                    m_movementflag -= ((uint)DCF);

                                    update_movementflag = true;
                                    /*
                                        if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
                                        && ((m_movementflag & (byte)nudgehack) == nudgehack))
                                        {
                                            MainConsole.Instance.Debug("Removed Hack flag");
                                        }
                                    */
                                }
                                else
                                {
                                    bAllowUpdateMoveToPosition = true;
                                }
                            }
                            i++;
                        }
                    }

                    //Paupaw:Do Proper PID for Autopilot here
                    if (bResetMoveToPosition)
                    {
                        m_moveToPositionTarget = Vector3.Zero;
                        m_moveToPositionInProgress = false;
                        update_movementflag = true;
                        bAllowUpdateMoveToPosition = false;
                    }

                    if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
                    {
                        //Check the error term of the current position in relation to the target position
                        if (Util.GetFlatDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f)
                        {
                            // we are close enough to the target
                            m_moveToPositionTarget = Vector3.Zero;
                            m_moveToPositionInProgress = false;
                            update_movementflag = true;
                        }
                        else
                        {
                            try
                            {
                                // move avatar in 2D at one meter/second towards target, in avatar coordinate frame.
                                // This movement vector gets added to the velocity through AddNewMovement().
                                // Theoretically we might need a more complex PID approach here if other 
                                // unknown forces are acting on the avatar and we need to adaptively respond
                                // to such forces, but the following simple approach seems to works fine.
                            Vector3 LocalVectorToTarget3D=
                                                         (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
                                //                                    * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
                                                        * Quaternion.Inverse(bodyRotation); // mult by matix is faster but with creation, use *quarternion
                                // Ignore z component of vector
                                Vector3 LocalVectorToTarget2D;
                                LocalVectorToTarget2D.X = LocalVectorToTarget3D.X;
                                LocalVectorToTarget2D.Y = LocalVectorToTarget3D.Y;
                                LocalVectorToTarget2D.Z = 0f;

                                agent_control_v3 += LocalVectorToTarget2D;

                                // update avatar movement flags. the avatar coordinate system is as follows:
                                //
                                //                        +X (forward)
                                //
                                //                        ^
                                //                        |
                                //                        |
                                //                        |
                                //                        |
                                //     (left) +Y <--------o--------> -Y
                                //                       avatar
                                //                        |
                                //                        |
                                //                        |
                                //                        |
                                //                        v
                                //                        -X
                                //

                                // based on the above avatar coordinate system, classify the movement into 
                                // one of left/right/back/forward.
                                if (LocalVectorToTarget2D.Y > 0)//MoveLeft
                                {
                                    m_movementflag += (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
                                    //AgentControlFlags
                                    AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
                                    update_movementflag = true;
                                }
                                else if (LocalVectorToTarget2D.Y < 0) //MoveRight
                                {
                                    m_movementflag += (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
                                    AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
                                    update_movementflag = true;
                                }
                                if (LocalVectorToTarget2D.X < 0) //MoveBack
                                {
                                    m_movementflag += (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
                                    AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
                                    update_movementflag = true;
                                }
                                else if (LocalVectorToTarget2D.X > 0) //Move Forward
                                {
                                    m_movementflag += (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
                                    AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
                                    update_movementflag = true;
                                }
                            }
                            catch (Exception e)
                            {
                                //Avoid system crash, can be slower but...
                                MainConsole.Instance.DebugFormat("Crash! {0}", e);
                            }
                        }
                    }
                }

                // Cause the avatar to stop flying if it's colliding
                // with something with the down arrow pressed.

                // Only do this if we're flying
                if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly)
                {
                    // Landing detection code

                    // Are the landing controls requirements filled?
                    bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
                                        ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));

                    // Are the collision requirements fulfilled?
                    bool colliding = (m_physicsActor.IsColliding == true);

                    if (m_physicsActor.Flying && colliding && controlland)
                    {
                        // nesting this check because LengthSquared() is expensive and we don't 
                        // want to do it every step when flying.
                        // then call it in the if...
                        //The == Zero and Z > 0.1 are to stop people from flying and then falling down because the physics engine hasn't calculted the push yet
                        if (Velocity != Vector3.Zero && Math.Abs(Velocity.Z) > 0.05 && (Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
                        {
                            StopFlying ();
                            SendTerseUpdateToAllClients ();
                        }
                    }
                }

                // If the agent update does move the avatar, then calculate the force ready for the velocity update,
                // which occurs later in the main scene loop
                if (update_movementflag || (update_rotation && DCFlagKeyPressed))
                {
                    //                    MainConsole.Instance.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed));
                    //                    MainConsole.Instance.DebugFormat(
                    //                        "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);

                    AddNewMovement(agent_control_v3, q);
                }
            }

            if (update_movementflag &&
                (m_parentID == UUID.Zero) && !SitGround && flags == AgentManager.ControlFlags.NONE)
                Animator.UpdateMovementAnimations(true);
            

            IAgentUpdateMonitor reporter = (IAgentUpdateMonitor)m_scene.RequestModuleInterface<IMonitorModule>().GetMonitor(m_scene.RegionInfo.RegionID.ToString(), MonitorModuleHelper.AgentUpdateCount);
            if (reporter != null)
                reporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
        }
Пример #19
0
        /// <summary>
        /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering.
        /// </summary>
        private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
        {
            //m_log.DebugFormat(
            //    "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}",
            //    Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);

            if (IsChildAgent)
            {
                //    // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
                return;
            }

            ++m_movementUpdateCount;
            if (m_movementUpdateCount < 1)
                m_movementUpdateCount = 1;

//            AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;

            // Camera location in world.  We'll need to raytrace
            // from this location from time to time.
            CameraPosition = agentData.CameraCenter;
            if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
            {
                ReprioritizeUpdates();
                m_lastCameraPosition = CameraPosition;
            }

            // Use these three vectors to figure out what the agent is looking at
            // Convert it to a Matrix and/or Quaternion
            CameraAtAxis = agentData.CameraAtAxis;
            CameraLeftAxis = agentData.CameraLeftAxis;
            CameraUpAxis = agentData.CameraUpAxis;

            // The Agent's Draw distance setting
            // When we get to the point of re-computing neighbors everytime this
            // changes, then start using the agent's drawdistance rather than the 
            // region's draw distance.

            DrawDistance = agentData.Far;

            // Check if Client has camera in 'follow cam' or 'build' mode.
            Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);

            m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f)
               && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;


            //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(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
                }
            }

            TriggerScenePresenceUpdated();
        }
Пример #20
0
        /// <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
            // When we get to the point of re-computing neighbors everytime this
            // changes, then start using the agent's drawdistance rather than the 
            // region's draw distance.
            // m_DrawDistance = agentData.Far;
            m_DrawDistance = Scene.DefaultDrawDistance;

            // 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;
            }

            if (m_allowMovement && !SitGround)
            {
                bool update_movementflag = false;

                if (agentData.UseClientAgentPosition)
                {
                    MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
                    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;

                    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
                    // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction.
                    uint nudgehack = 250;
                    foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
                    {
                        if (((uint)flags & (uint)DCF) != 0)
                        {
                            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;
                                /*
                                    if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
                                    && ((m_movementflag & (byte)nudgehack) == nudgehack))
                                    {
                                        m_log.Debug("Removed Hack flag");
                                    }
                                */
                            }
                            else
                            {
                                bAllowUpdateMoveToPosition = true;
                            }
                        }

                        i++;
                    }

                    if (MovingToTarget)
                    {
                        // If the user has pressed a key then we want to cancel any move to target.
                        if (DCFlagKeyPressed)
                        {
                            ResetMoveToTarget();
                            update_movementflag = true;
                        }
                        else if (bAllowUpdateMoveToPosition)
                        {
                            if (HandleMoveToTargetUpdate(ref agent_control_v3, bodyRotation))
                                update_movementflag = true;
                        }
                    }
                }

                // Cause the avatar to stop flying if it's colliding
                // with something with the down arrow pressed.

                // Only do this if we're flying
                if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly)
                {
                    // Landing detection code

                    // Are the landing controls requirements filled?
                    bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
                                        ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));

                    // Are the collision requirements fulfilled?
                    bool colliding = (m_physicsActor.IsColliding == true);

                    if (m_physicsActor.Flying && colliding && controlland)
                    {
                        // nesting this check because LengthSquared() is expensive and we don't 
                        // want to do it every step when flying.
                        if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
                            StopFlying();
                    }
                }

                // If the agent update does move the avatar, then calculate the force ready for the velocity update,
                // which occurs later in the main scene loop
                if (update_movementflag || (update_rotation && DCFlagKeyPressed))
                {
                    //                    m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed));
                    //                    m_log.DebugFormat(
                    //                        "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);

                    AddNewMovement(agent_control_v3, q);
                }

                if (update_movementflag
                    && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0)
                    && (m_parentID == 0)
                    && !SitGround)
                    Animator.UpdateMovementAnimations();
            }

            m_scene.EventManager.TriggerOnClientMovement(this);

            m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
        }