StandUp() public method

Perform the logic necessary to stand the avatar up. This method also executes the stand animation.
public StandUp ( ) : void
return void
        public void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq)
        {
            if (reg == null || finalDestination == null)
            {
                sp.ControllingClient.SendTeleportFailed("Unable to locate destination");
                return;
            }

            m_log.DebugFormat(
                "[ENTITY TRANSFER MODULE]: Request Teleport to {0} ({1}) {2}/{3}",
                reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position);

            uint newRegionX = (uint)(reg.RegionHandle >> 40);
            uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
            uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40);
            uint oldRegionY = (((uint)(sp.Scene.RegionInfo.RegionHandle)) >> 8);

            ulong destinationHandle = finalDestination.RegionHandle;

            // Let's do DNS resolution only once in this process, please!
            // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
            // it's actually doing a lot of work.
            IPEndPoint endPoint = finalDestination.ExternalEndPoint;
            if (endPoint.Address != null)
            {
                // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
                // both regions
                if (sp.ParentID != (uint)0)
                    sp.StandUp();

                if (!sp.ValidateAttachments())
                    m_log.DebugFormat(
                        "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}.  Continuing.",
                        sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName);

//                if (!sp.ValidateAttachments())
//                {
//                    sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
//                    return;
//                }

                string reason;
                string version;
                if (!m_aScene.SimulationService.QueryAccess(finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason))
                {
                    sp.ControllingClient.SendTeleportFailed("Teleport failed: " + reason);
                    return;
                }
                m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version);

                sp.ControllingClient.SendTeleportStart(teleportFlags);

                // the avatar.Close below will clear the child region list. We need this below for (possibly)
                // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
                //List<ulong> childRegions = avatar.KnownRegionHandles;
                // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
                // failure at this point (unlike a border crossing failure).  So perhaps this can never fail
                // once we reach here...
                //avatar.Scene.RemoveCapsHandler(avatar.UUID);

                string capsPath = String.Empty;

                AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
                AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
                agentCircuit.startpos = position;
                agentCircuit.child = true;
                agentCircuit.Appearance = sp.Appearance;
                if (currentAgentCircuit != null)
                {
                    agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
                    agentCircuit.IPAddress = currentAgentCircuit.IPAddress;
                    agentCircuit.Viewer = currentAgentCircuit.Viewer;
                    agentCircuit.Channel = currentAgentCircuit.Channel;
                    agentCircuit.Mac = currentAgentCircuit.Mac;
                    agentCircuit.Id0 = currentAgentCircuit.Id0;
                }

                if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
                {
                    // brand new agent, let's create a new caps seed
                    agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
                }

                // Let's create an agent there if one doesn't exist yet. 
                bool logout = false;
                if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
                {
                    sp.ControllingClient.SendTeleportFailed(String.Format("Destination refused: {0}",
                                                                              reason));
                    return;
                }

                // OK, it got this agent. Let's close some child agents
                sp.CloseChildAgents(newRegionX, newRegionY);
                IClientIPEndpoint ipepClient;  
                if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
                {
                    //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
                    #region IP Translation for NAT
                    // Uses ipepClient above
                    if (sp.ClientView.TryGet(out ipepClient))
                    {
                        endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
                    }
                    #endregion
                    capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);

                    if (eq != null)
                    {
                        eq.EnableSimulator(destinationHandle, endPoint, sp.UUID);

                        // ES makes the client send a UseCircuitCode message to the destination, 
                        // which triggers a bunch of things there.
                        // So let's wait
                        Thread.Sleep(200);

                        eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);

                    }
                    else
                    {
                        sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
                    }
                }
                else
                {
                    agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
                    capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
                }


                SetInTransit(sp.UUID);

                // Let's send a full update of the agent. This is a synchronous call.
                AgentData agent = new AgentData();
                sp.CopyTo(agent);
                agent.Position = position;
                SetCallbackURL(agent, sp.Scene.RegionInfo);

                //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");

                if (!UpdateAgent(reg, finalDestination, agent))
                {
                    // Region doesn't take it
                    m_log.WarnFormat(
                        "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}.  Returning avatar to source region.", 
                        sp.Name, finalDestination.RegionName);
                    
                    Fail(sp, finalDestination);
                    return;
                }

                sp.ControllingClient.SendTeleportProgress(teleportFlags | (uint)TeleportFlags.DisableCancel, "sending_dest");

                m_log.DebugFormat(
                    "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, sp.UUID);

                if (eq != null)
                {
                    eq.TeleportFinishEvent(destinationHandle, 13, endPoint,
                                           0, teleportFlags, capsPath, sp.UUID);
                }
                else
                {
                    sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
                                                                teleportFlags, capsPath);
                }

                // Let's set this to true tentatively. This does not trigger OnChildAgent
                sp.IsChildAgent = true;

                // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
                // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
                // that the client contacted the destination before we close things here.
                if (!WaitForCallback(sp.UUID))
                {
                    m_log.WarnFormat(
                        "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} failed due to no callback from destination region.  Returning avatar to source region.", 
                        sp.Name, finalDestination.RegionName);
                    
                    Fail(sp, finalDestination);                   
                    return;
                }

                // For backwards compatibility
                if (version == "Unknown" || version == string.Empty)
                {
                    // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
                    m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Old simulator, sending attachments one by one...");
                    CrossAttachmentsIntoNewRegion(finalDestination, sp, true);
                }

                // May need to logout or other cleanup
                AgentHasMovedAway(sp, logout);

                // Well, this is it. The agent is over there.
                KillEntity(sp.Scene, sp.LocalId);

                // Now let's make it officially a child agent
                sp.MakeChildAgent();
                

//                sp.Scene.CleanDroppedAttachments();

                // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone

                if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
                {
                    Thread.Sleep(5000);
                    sp.Close();
                    sp.Scene.IncomingCloseAgent(sp.UUID);
                }
                else
                {
                    // now we have a child agent in this region. 
                    sp.IsInTransit = false; // not sure :(
                    sp.Reset();
                }

                // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
                if (sp.Scene.NeedSceneCacheClear(sp.UUID))
                {
                    m_log.DebugFormat(
                        "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
                        sp.UUID);
                }
            }
            else
            {
                sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
            }
        }
        public virtual void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq)
        {
            sp.ControllingClient.SendTeleportProgress(teleportFlags, "sending_dest");
            if (reg == null || finalDestination == null)
            {
                sp.ControllingClient.SendTeleportFailed("Unable to locate destination");
                return;
            }

            m_log.DebugFormat(
                "[ENTITY TRANSFER MODULE]: Request Teleport to {0}:{1}:{2}/{3}",
                reg.ExternalHostName, reg.HttpPort, finalDestination.RegionName, position);

            uint newRegionX = (uint)(reg.RegionHandle >> 40);
            uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
            uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40);
            uint oldRegionY = (((uint)(sp.Scene.RegionInfo.RegionHandle)) >> 8);

            ulong destinationHandle = finalDestination.RegionHandle;

            // Let's do DNS resolution only once in this process, please!
            // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
            // it's actually doing a lot of work.
            IPEndPoint endPoint = finalDestination.ExternalEndPoint;
            if (endPoint.Address != null)
            {
                sp.ControllingClient.SendTeleportProgress(teleportFlags, "arriving");
                    
                if (m_cancelingAgents.Contains(sp.UUID))
                {
                    Cancel(sp);
                    return;
                }
                // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
                // both regions
                if (sp.ParentID != UUID.Zero)
                    sp.StandUp();

                if (!sp.ValidateAttachments())
                {
                    sp.ControllingClient.SendTeleportProgress(teleportFlags, "missing_attach_tport");
                    sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
                    return;
                }

                string capsPath = String.Empty;

                AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
                AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
                agentCircuit.startpos = position;
                agentCircuit.child = true;
                agentCircuit.Appearance = sp.Appearance;
                if (currentAgentCircuit != null)
                {
                    agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
                    agentCircuit.IPAddress = currentAgentCircuit.IPAddress;
                    agentCircuit.Viewer = currentAgentCircuit.Viewer;
                    agentCircuit.Channel = currentAgentCircuit.Channel;
                    agentCircuit.Mac = currentAgentCircuit.Mac;
                    agentCircuit.Id0 = currentAgentCircuit.Id0;
                }

                if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY))
                {
                    // brand new agent, let's create a new caps seed
                    agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
                }

                string reason = String.Empty;
                // Let's create an agent there if one doesn't exist yet. 
                bool logout = false;
                if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
                {
                    sp.ControllingClient.SendTeleportFailed(String.Format("Destination refused: {0}",
                                                                              reason));
                    return;
                }

                // OK, it got this agent. Let's close some child agents
                sp.CloseChildAgents(newRegionX, newRegionY);

                if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY))
                {
                    //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");

                    #region IP Translation for NAT
                    IClientIPEndpoint ipepClient;
                    if (sp.ClientView.TryGet(out ipepClient))
                    {
                        capsPath
                            = "http://"
                              + NetworkUtil.GetHostFor(ipepClient.EndPoint, finalDestination.ExternalHostName)
                              + ":"
                              + finalDestination.HttpPort
                              + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
                    }
                    else
                    {
                        capsPath
                            = "http://"
                              + finalDestination.ExternalHostName
                              + ":"
                              + finalDestination.HttpPort
                              + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
                    }
                    #endregion

                    if (eq != null)
                    {
                        #region IP Translation for NAT
                        // Uses ipepClient above
                        if (sp.ClientView.TryGet(out ipepClient))
                        {
                            endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
                        }
                        #endregion

                        eq.EnableSimulator(destinationHandle, endPoint, sp.UUID);

                        // ES makes the client send a UseCircuitCode message to the destination, 
                        // which triggers a bunch of things there.
                        // So let's wait
                        Thread.Sleep(200);

                        eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);

                    }
                    else
                    {
                        sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
                    }
                }
                else
                {
                    agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
                    capsPath = "http://" + finalDestination.ExternalHostName + ":" + finalDestination.HttpPort
                                + "/CAPS/" + agentCircuit.CapsPath + "0000/";
                }

                if (m_cancelingAgents.Contains(sp.UUID))
                {
                    Cancel(sp);
                    return;
                }

                SetInTransit(sp.UUID);

                // Let's send a full update of the agent. This is a synchronous call.
                AgentData agent = new AgentData();
                sp.CopyTo(agent);
                agent.Position = position;
                SetCallbackURL(agent, sp.Scene.RegionInfo);

                //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");

                if (!UpdateAgent(reg, finalDestination, agent))
                {
                    // Region doesn't take it
                    Fail(sp, finalDestination);
                    return;
                }

                m_log.DebugFormat(
                    "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, sp.UUID);

                if (eq != null)
                {
                    eq.TeleportFinishEvent(destinationHandle, 13, endPoint,
                                           0, teleportFlags, capsPath, sp.UUID, teleportFlags);
                }
                else
                {
                    sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
                                                                teleportFlags, capsPath);
                }

                // Let's set this to true tentatively. This does not trigger OnChildAgent
                sp.IsChildAgent = true;

                // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
                // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
                // that the client contacted the destination before we send the attachments and close things here.
                
                //OpenSim sucks at callbacks, disable it for now
                
                if (!WaitForCallback(sp.UUID))
                {
                    /*//Make sure the client hasn't TPed back in this time.
                    ScenePresence SP = m_aScene.GetScenePresence(sp.UUID);
                    if (SP != null && SP.IsChildAgent)
                    {
                        //Disabling until this actually helps and doesn't kill clients
                        //Fail(sp, finalDestination);
                        return;
                    }
                    else if (SP == null)
                    {
                        //Err.. this happens somehow.
                        return;
                    }*/
                }

                /*//Make sure the client hasn't TPed back in this time.
                ScenePresence newSP = m_aScene.GetScenePresence(sp.UUID);
                if (newSP != null && !newSP.IsChildAgent)
                {
                    //They are root again, don't cross them!
                    return;
                }
                else if (newSP == null)
                {
                    //Err.. this happens somehow.
                    return;
                }*/


                // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
                CrossAttachmentsIntoNewRegion(finalDestination, sp, true);

                // Well, this is it. The agent is over there.

                KillEntity(sp.Scene, sp.LocalId);

                // May need to logout or other cleanup
                AgentHasMovedAway(sp.ControllingClient.SessionId, logout);

                // Now let's make it officially a child agent
                sp.MakeChildAgent();

                // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone

                if (NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
                {
                    Thread.Sleep(5000);
                    sp.Close();
                    sp.Scene.IncomingCloseAgent(sp.UUID);
                }
                else
                    // now we have a child agent in this region. 
                    sp.Reset();

                //If they canceled too late, remove them so the next tp does not fail.
                if (m_cancelingAgents.Contains(sp.UUID))
                    m_cancelingAgents.Remove(sp.UUID);
            }
            else
            {
                sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
            }
        }
        /// <summary>
        /// Try to teleport an agent to a new region.
        /// </summary>
        /// <param name="remoteClient"></param>
        /// <param name="RegionHandle"></param>
        /// <param name="position"></param>
        /// <param name="lookAt"></param>
        /// <param name="flags"></param>
        public virtual void RequestTeleportToLocation(ScenePresence avatar, ulong regionHandle, Vector3 position,
                                                      Vector3 lookAt, uint teleportFlags)
        {
            if (!avatar.Scene.Permissions.CanTeleport(avatar.UUID))
                return;

            bool destRegionUp = true;

            IEventQueue eq = avatar.Scene.RequestModuleInterface<IEventQueue>();

            // Reset animations; the viewer does that in teleports.
            avatar.Animator.ResetAnimations();

            if (regionHandle == m_regionInfo.RegionHandle)
            {
                m_log.DebugFormat(
                    "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation {0} within {1}",
                    position, m_regionInfo.RegionName);

                // Teleport within the same region
                if (IsOutsideRegion(avatar.Scene, position) || position.Z < 0)
                {
                    Vector3 emergencyPos = new Vector3(128, 128, 128);

                    m_log.WarnFormat(
                        "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}.  Substituting {3}",
                        position, avatar.Name, avatar.UUID, emergencyPos);
                    position = emergencyPos;
                }

                // TODO: Get proper AVG Height
                float localAVHeight = 1.56f;
                float posZLimit = 22;

                // TODO: Check other Scene HeightField
                if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <=(int)Constants.RegionSize)
                {
                    posZLimit = (float) avatar.Scene.Heightmap[(int) position.X, (int) position.Y];
                }

                float newPosZ = posZLimit + localAVHeight;
                if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
                {
                    position.Z = newPosZ;
                }

                // Only send this if the event queue is null
                if (eq == null)
                    avatar.ControllingClient.SendTeleportLocationStart();
                
                avatar.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
                avatar.Teleport(position);
            }
            else
            {
                uint x = 0, y = 0;
                Utils.LongToUInts(regionHandle, out x, out y);
                GridRegion reg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);

                if (reg != null)
                {
                    m_log.DebugFormat(
                        "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation to {0} in {1}", 
                        position, reg.RegionName);
                    
                    if (eq == null)
                        avatar.ControllingClient.SendTeleportLocationStart();

                    // Let's do DNS resolution only once in this process, please!
                    // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
                    // it's actually doing a lot of work.
                    IPEndPoint endPoint = reg.ExternalEndPoint;
                    if (endPoint.Address == null)
                    {
                        // Couldn't resolve the name. Can't TP, because the viewer wants IP addresses.
                        destRegionUp = false;
                    }

                    if (destRegionUp)
                    {
                        uint newRegionX = (uint)(reg.RegionHandle >> 40);
                        uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
                        uint oldRegionX = (uint)(m_regionInfo.RegionHandle >> 40);
                        uint oldRegionY = (((uint)(m_regionInfo.RegionHandle)) >> 8);

                        // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
                        // both regions
                        if (avatar.ParentID != (uint)0)
                            avatar.StandUp();
                        
                        if (!avatar.ValidateAttachments())
                        {
                            avatar.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
                            return;
                        }

                        // the avatar.Close below will clear the child region list. We need this below for (possibly)
                        // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
                        //List<ulong> childRegions = new List<ulong>(avatar.GetKnownRegionList());
                        // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
                        // failure at this point (unlike a border crossing failure).  So perhaps this can never fail
                        // once we reach here...
                        //avatar.Scene.RemoveCapsHandler(avatar.UUID);

                        string capsPath = String.Empty;
                        AgentCircuitData agentCircuit = avatar.ControllingClient.RequestClientInfo();
                        agentCircuit.BaseFolder = UUID.Zero;
                        agentCircuit.InventoryFolder = UUID.Zero;
                        agentCircuit.startpos = position;
                        agentCircuit.child = true;
                        
                        if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
                        {
                            // brand new agent, let's create a new caps seed
                            agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
                        }

                        string reason = String.Empty;

                        // Let's create an agent there if one doesn't exist yet. 
                        //if (!m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, agentCircuit))
                        if (!m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, agentCircuit, teleportFlags, out reason))
                        {
                            avatar.ControllingClient.SendTeleportFailed(String.Format("Destination is not accepting teleports: {0}",
                                                                                      reason));
                            return;
                        }

                        // OK, it got this agent. Let's close some child agents
                        avatar.CloseChildAgents(newRegionX, newRegionY);

                        if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
                        {
                            #region IP Translation for NAT
                            IClientIPEndpoint ipepClient;
                            if (avatar.ClientView.TryGet(out ipepClient))
                            {
                                capsPath
                                    = "http://"
                                      + NetworkUtil.GetHostFor(ipepClient.EndPoint, reg.ExternalHostName)
                                      + ":"
                                      + reg.HttpPort
                                      + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
                            }
                            else
                            {
                                capsPath
                                    = "http://"
                                      + reg.ExternalHostName
                                      + ":"
                                      + reg.HttpPort
                                      + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
                            }
                            #endregion

                            if (eq != null)
                            {
                                #region IP Translation for NAT
                                // Uses ipepClient above
                                if (avatar.ClientView.TryGet(out ipepClient))
                                {
                                    endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
                                }
                                #endregion

                                eq.EnableSimulator(reg.RegionHandle, endPoint, avatar.UUID);

                                // ES makes the client send a UseCircuitCode message to the destination, 
                                // which triggers a bunch of things there.
                                // So let's wait
                                Thread.Sleep(2000);

                                eq.EstablishAgentCommunication(avatar.UUID, endPoint, capsPath);
                            }
                            else
                            {
                                avatar.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
                            }
                        }
                        else
                        {
                            agentCircuit.CapsPath = avatar.Scene.CapsModule.GetChildSeed(avatar.UUID, reg.RegionHandle);
                            capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
                                        + "/CAPS/" + agentCircuit.CapsPath + "0000/";
                        }

                        // Expect avatar crossing is a heavy-duty function at the destination.
                        // That is where MakeRoot is called, which fetches appearance and inventory.
                        // Plus triggers OnMakeRoot, which spawns a series of asynchronous updates.
                        //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
                        //                                                      position, false);

                        //{
                        //    avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
                        //    // We should close that agent we just created over at destination...
                        //    List<ulong> lst = new List<ulong>();
                        //    lst.Add(reg.RegionHandle);
                        //    SendCloseChildAgentAsync(avatar.UUID, lst);
                        //    return;
                        //}

                        SetInTransit(avatar.UUID);
                        // Let's send a full update of the agent. This is a synchronous call.
                        AgentData agent = new AgentData();
                        avatar.CopyTo(agent);
                        agent.Position = position;
                        agent.CallbackURI = "http://" + m_regionInfo.ExternalHostName + ":" + m_regionInfo.HttpPort + 
                            "/agent/" + avatar.UUID.ToString() + "/" + avatar.Scene.RegionInfo.RegionHandle.ToString() + "/release/";

                        m_interregionCommsOut.SendChildAgentUpdate(reg.RegionHandle, agent);

                        m_log.DebugFormat(
                            "[CAPS]: Sending new CAPS seed url {0} to client {1}", capsPath, avatar.UUID);

                        
                        if (eq != null)
                        {
                            eq.TeleportFinishEvent(reg.RegionHandle, 13, endPoint,
                                                   0, teleportFlags, capsPath, avatar.UUID);
                        }
                        else
                        {
                            avatar.ControllingClient.SendRegionTeleport(reg.RegionHandle, 13, endPoint, 4,
                                                                        teleportFlags, capsPath);
                        }

                        // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
                        // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
                        // that the client contacted the destination before we send the attachments and close things here.
                        if (!WaitForCallback(avatar.UUID))
                        {
                            // Client never contacted destination. Let's restore everything back
                            avatar.ControllingClient.SendTeleportFailed("Problems connecting to destination.");

                            ResetFromTransit(avatar.UUID);
                            
                            // Yikes! We should just have a ref to scene here.
                            avatar.Scene.InformClientOfNeighbours(avatar);

                            // Finally, kill the agent we just created at the destination.
                            m_interregionCommsOut.SendCloseAgent(reg.RegionHandle, avatar.UUID);

                            return;
                        }

                        // Can't go back from here
                        if (KiPrimitive != null)
                        {
                            KiPrimitive(avatar.LocalId);
                        }

                        avatar.MakeChildAgent();

                        // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
                        avatar.CrossAttachmentsIntoNewRegion(reg.RegionHandle, true);

                        // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone

                        if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
                        {
                            Thread.Sleep(5000);
                            avatar.Close();
                            CloseConnection(avatar.UUID);
                        }
                        else
                            // now we have a child agent in this region. 
                            avatar.Reset();


                        // if (teleport success) // seems to be always success here
                        // the user may change their profile information in other region,
                        // so the userinfo in UserProfileCache is not reliable any more, delete it
                        if (avatar.Scene.NeedSceneCacheClear(avatar.UUID))
                        {
                            m_commsProvider.UserProfileCacheService.RemoveUser(avatar.UUID);
                            m_log.DebugFormat(
                                "[SCENE COMMUNICATION SERVICE]: User {0} is going to another region, profile cache removed",
                                avatar.UUID);
                        }
                    }
                    else
                    {
                        avatar.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
                    }
                }
                else
                {
                    // TP to a place that doesn't exist (anymore)
                    // Inform the viewer about that
                    avatar.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");
                    
                    // and set the map-tile to '(Offline)'
                    uint regX, regY;
                    Utils.LongToUInts(regionHandle, out regX, out regY);
                    
                    MapBlockData block = new MapBlockData();
                    block.X = (ushort)(regX / Constants.RegionSize);
                    block.Y = (ushort)(regY / Constants.RegionSize);
                    block.Access = 254; // == not there
                    
                    List<MapBlockData> blocks = new List<MapBlockData>();
                    blocks.Add(block);
                    avatar.ControllingClient.SendMapBlock(blocks, 0);
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Teleports the agent to another region.
        /// This method doesn't manage the transfer state; the caller must do that.
        /// </summary>
        private void DoTeleportInternal(
            ScenePresence sp, GridRegion reg, GridRegion finalDestination,
            Vector3 position, Vector3 lookAt, uint teleportFlags)
        {
            if (reg == null || finalDestination == null)
            {
                sp.ControllingClient.SendTeleportFailed("Unable to locate destination");
                return;
            }

            string homeURI = Scene.GetAgentHomeURI(sp.ControllingClient.AgentId);

            m_log.DebugFormat(
                "[ENTITY TRANSFER MODULE]: Teleporting {0} {1} from {2} to {3} ({4}) {5}/{6}",
                sp.Name, sp.UUID, sp.Scene.RegionInfo.RegionName,
                reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position);

            RegionInfo sourceRegion = sp.Scene.RegionInfo;

            if (!IsWithinMaxTeleportDistance(sourceRegion, finalDestination))
            {
                sp.ControllingClient.SendTeleportFailed(
                    string.Format(
                      "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way",
                      finalDestination.RegionName, finalDestination.RegionCoordX, finalDestination.RegionCoordY,
                      sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY,
                      MaxTransferDistance));

                return;
            }

            uint newRegionX, newRegionY, oldRegionX, oldRegionY;
            Util.RegionHandleToRegionLoc(reg.RegionHandle, out newRegionX, out newRegionY);
            Util.RegionHandleToRegionLoc(sp.Scene.RegionInfo.RegionHandle, out oldRegionX, out oldRegionY);

            ulong destinationHandle = finalDestination.RegionHandle;

            // Let's do DNS resolution only once in this process, please!
            // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
            // it's actually doing a lot of work.
            IPEndPoint endPoint = finalDestination.ExternalEndPoint;
            if (endPoint == null || endPoint.Address == null)
            {
                sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down");

                return;
            }

            if (!sp.ValidateAttachments())
                m_log.DebugFormat(
                    "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}.  Continuing.",
                    sp.Name, sp.Scene.Name, finalDestination.RegionName);

            string reason;
            string version;
            string myversion = string.Format("{0}/{1}", OutgoingTransferVersionName, MaxOutgoingTransferVersion);
            if (!Scene.SimulationService.QueryAccess(
                finalDestination, sp.ControllingClient.AgentId, homeURI, true, position, myversion, out version, out reason))
            {
                sp.ControllingClient.SendTeleportFailed(reason);

                m_log.DebugFormat(
                    "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because: {3}",
                    sp.Name, sp.Scene.Name, finalDestination.RegionName, reason);

                return;
            }

            // Before this point, teleport 'failure' is due to checkable pre-conditions such as whether the target
            // simulator can be found and is explicitly prepared to allow access.  Therefore, we will not count these
            // as server attempts.
            m_interRegionTeleportAttempts.Value++;

            m_log.DebugFormat(
                "[ENTITY TRANSFER MODULE]: {0} max transfer version is {1}/{2}, {3} max version is {4}", 
                sp.Scene.Name, OutgoingTransferVersionName, MaxOutgoingTransferVersion, finalDestination.RegionName, version);

            // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
            // both regions
            if (sp.ParentID != (uint)0)
                sp.StandUp();
            else if (sp.Flying)
                teleportFlags |= (uint)TeleportFlags.IsFlying;

            if (DisableInterRegionTeleportCancellation)
                teleportFlags |= (uint)TeleportFlags.DisableCancel;

            // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to
            // the viewer.  However, it might mean that the viewer does not see the black teleport screen (untested).
            sp.ControllingClient.SendTeleportStart(teleportFlags);

            // the avatar.Close below will clear the child region list. We need this below for (possibly)
            // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
            //List<ulong> childRegions = avatar.KnownRegionHandles;
            // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
            // failure at this point (unlike a border crossing failure).  So perhaps this can never fail
            // once we reach here...
            //avatar.Scene.RemoveCapsHandler(avatar.UUID);

            AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
            AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
            agentCircuit.startpos = position;
            agentCircuit.child = true;
            agentCircuit.Appearance = sp.Appearance;
            if (currentAgentCircuit != null)
            {
                agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
                agentCircuit.IPAddress = currentAgentCircuit.IPAddress;
                agentCircuit.Viewer = currentAgentCircuit.Viewer;
                agentCircuit.Channel = currentAgentCircuit.Channel;
                agentCircuit.Mac = currentAgentCircuit.Mac;
                agentCircuit.Id0 = currentAgentCircuit.Id0;
            }

            // if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
            float dist = (float)Math.Max(sp.Scene.DefaultDrawDistance,
                (float)Math.Max(sp.Scene.RegionInfo.RegionSizeX, sp.Scene.RegionInfo.RegionSizeY));
            if (NeedsNewAgent(dist, oldRegionX, newRegionX, oldRegionY, newRegionY))
            {
                // brand new agent, let's create a new caps seed
                agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
            }

            // We're going to fallback to V1 if the destination gives us anything smaller than 0.2 or we're forcing
            // use of the earlier protocol
            float versionNumber = 0.1f;
            string[] versionComponents = version.Split(new char[] { '/' });
            if (versionComponents.Length >= 2)
                float.TryParse(versionComponents[1], out versionNumber);

            if (versionNumber >= 0.2f && MaxOutgoingTransferVersion >= versionNumber)
                TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
            else
                TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);           
        }
        protected void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq)
        {
            if (reg == null || finalDestination == null)
            {
                sp.ControllingClient.SendTeleportFailed("Unable to locate destination");
                return;
            }

            m_log.DebugFormat(
                "[ENTITY TRANSFER MODULE]: Request Teleport to {0}:{1}:{2}/{3}",
                reg.ExternalHostName, reg.HttpPort, finalDestination.RegionName, position);

            uint newRegionX = (uint)(reg.RegionHandle >> 40);
            uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
            uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40);
            uint oldRegionY = (((uint)(sp.Scene.RegionInfo.RegionHandle)) >> 8);

            ulong destinationHandle = finalDestination.RegionHandle;

            if (eq == null)
                sp.ControllingClient.SendTeleportLocationStart();

            // Let's do DNS resolution only once in this process, please!
            // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
            // it's actually doing a lot of work.
            IPEndPoint endPoint = finalDestination.ExternalEndPoint;
            if (endPoint.Address != null)
            {
                // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
                // both regions
                if (sp.ParentID != (uint)0)
                    sp.StandUp();

                if (!sp.ValidateAttachments())
                {
                    sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
                    return;
                }

                // the avatar.Close below will clear the child region list. We need this below for (possibly)
                // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
                //List<ulong> childRegions = new List<ulong>(avatar.GetKnownRegionList());
                // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
                // failure at this point (unlike a border crossing failure).  So perhaps this can never fail
                // once we reach here...
                //avatar.Scene.RemoveCapsHandler(avatar.UUID);

                string capsPath = String.Empty;

                AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
                AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
                agentCircuit.startpos = position;
                agentCircuit.child = true;
                agentCircuit.Appearance = sp.Appearance;
                if (currentAgentCircuit != null)
                {
                    agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
                    agentCircuit.Viewer = currentAgentCircuit.Viewer;
                }

                if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY))
                {
                    // brand new agent, let's create a new caps seed
                    agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
                }

                string reason = String.Empty;

                // Let's create an agent there if one doesn't exist yet. 
                if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason))
                {
                    sp.ControllingClient.SendTeleportFailed(String.Format("Destination refused: {0}",
                                                                              reason));
                    return;
                }

                // OK, it got this agent. Let's close some child agents
                sp.CloseChildAgents(newRegionX, newRegionY);

                if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY))
                {
                    #region IP Translation for NAT
                    IClientIPEndpoint ipepClient;
                    if (sp.ClientView.TryGet(out ipepClient))
                    {
                        capsPath
                            = "http://"
                              + NetworkUtil.GetHostFor(ipepClient.EndPoint, finalDestination.ExternalHostName)
                              + ":"
                              + finalDestination.HttpPort
                              + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
                    }
                    else
                    {
                        capsPath
                            = "http://"
                              + finalDestination.ExternalHostName
                              + ":"
                              + finalDestination.HttpPort
                              + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
                    }
                    #endregion

                    if (eq != null)
                    {
                        #region IP Translation for NAT
                        // Uses ipepClient above
                        if (sp.ClientView.TryGet(out ipepClient))
                        {
                            endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
                        }
                        #endregion

                        eq.EnableSimulator(destinationHandle, endPoint, sp.UUID);

                        // ES makes the client send a UseCircuitCode message to the destination, 
                        // which triggers a bunch of things there.
                        // So let's wait
                        Thread.Sleep(200);

                        eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);

                    }
                    else
                    {
                        sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
                    }
                }
                else
                {
                    agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
                    capsPath = "http://" + finalDestination.ExternalHostName + ":" + finalDestination.HttpPort
                                + "/CAPS/" + agentCircuit.CapsPath + "0000/";
                }

                // Expect avatar crossing is a heavy-duty function at the destination.
                // That is where MakeRoot is called, which fetches appearance and inventory.
                // Plus triggers OnMakeRoot, which spawns a series of asynchronous updates.
                //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
                //                                                      position, false);

                //{
                //    avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
                //    // We should close that agent we just created over at destination...
                //    List<ulong> lst = new List<ulong>();
                //    lst.Add(reg.RegionHandle);
                //    SendCloseChildAgentAsync(avatar.UUID, lst);
                //    return;
                //}

                SetInTransit(sp.UUID);

                // Let's send a full update of the agent. This is a synchronous call.
                AgentData agent = new AgentData();
                sp.CopyTo(agent);
                agent.Position = position;
                SetCallbackURL(agent, sp.Scene.RegionInfo);

                UpdateAgent(reg, finalDestination, agent);

                m_log.DebugFormat(
                    "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, sp.UUID);


                if (eq != null)
                {
                    eq.TeleportFinishEvent(destinationHandle, 13, endPoint,
                                           0, teleportFlags, capsPath, sp.UUID);
                }
                else
                {
                    sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
                                                                teleportFlags, capsPath);
                }

                // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
                // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
                // that the client contacted the destination before we send the attachments and close things here.
                if (!WaitForCallback(sp.UUID))
                {
                    // Client never contacted destination. Let's restore everything back
                    sp.ControllingClient.SendTeleportFailed("Problems connecting to destination.");

                    ResetFromTransit(sp.UUID);

                    // Yikes! We should just have a ref to scene here.
                    //sp.Scene.InformClientOfNeighbours(sp);
                    EnableChildAgents(sp);

                    // Finally, kill the agent we just created at the destination.
                    m_aScene.SimulationService.CloseAgent(finalDestination, sp.UUID);

                    return;
                }


                // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
                CrossAttachmentsIntoNewRegion(finalDestination, sp, true);

                KillEntity(sp.Scene, sp.LocalId);

                sp.MakeChildAgent();
                // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone

                if (NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
                {
                    Thread.Sleep(5000);
                    sp.Close();
                    sp.Scene.IncomingCloseAgent(sp.UUID);
                }
                else
                    // now we have a child agent in this region. 
                    sp.Reset();


                // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
                if (sp.Scene.NeedSceneCacheClear(sp.UUID))
                {
                    m_log.DebugFormat(
                        "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
                        sp.UUID);
                }
            }
            else
            {
                sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
            }
        }
        private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position)
        {
            if (m_scene.Permissions.IsGod(avatar.UUID)) return;

            if (!position.HasValue)
                return;

            if(avatar.MovingToTarget)
                avatar.ResetMoveToTarget();
            avatar.AbsolutePosition = position.Value;
            avatar.lastKnownAllowedPosition = position.Value;
            avatar.Velocity = Vector3.Zero;
            if(avatar.IsSatOnObject)
                avatar.StandUp();
            forcedPosition.Add(avatar.UUID);
        }
Beispiel #7
0
        /// <summary>
        /// Tell a single agent to disconnect from the region.
        /// Does not send the DisableSimulator EQM or close child agents
        /// </summary>
        /// <param name="?"></param>
        /// <returns></returns>
        public bool RemoveAgent(ScenePresence presence)
        {
            presence.ControllingClient.Close();
            if (presence.ParentID != UUID.Zero)
            {
                presence.StandUp();
            }

            m_eventManager.TriggerClientClosed(presence.UUID, this);
            m_eventManager.TriggerOnClosingClient(presence.ControllingClient);
            m_eventManager.TriggerOnRemovePresence(presence);

            ForEachClient(
                delegate(IClientAPI client)
                {
                    //We can safely ignore null reference exceptions.  It means the avatar is dead and cleaned up anyway
                    try { client.SendKillObject(presence.Scene.RegionInfo.RegionHandle, new ISceneEntity[] { presence }); }
                    catch (NullReferenceException) { }
                });

            try
            {
                presence.Close();
            }
            catch (Exception e)
            {
                m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString());
            }

            // Remove the avatar from the scene
            m_sceneGraph.RemoveScenePresence(presence.UUID);
            m_clientManager.Remove(presence.UUID);

            AuthenticateHandler.RemoveCircuit(presence.ControllingClient.CircuitCode);
            //m_log.InfoFormat("[SCENE] Memory pre  GC {0}", System.GC.GetTotalMemory(false));
            //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
            return true;
        }
        public void RemoveAvatarFromParcel(ScenePresence avatar)
        {
            EntityBase.PositionInfo posInfo = avatar.GetPosInfo();

            if (posInfo.Parent != null)
            {
                // can't find the prim seated on, stand up
                avatar.StandUp(null, false, true);

                // fall through to unseated avatar code.
            }

            // If they are moving, stop them.  This updates the physics object as well.
            avatar.Velocity = Vector3.Zero;

            Vector3 pos = avatar.AbsolutePosition;  // may have changed from posInfo by StandUp above.

            ParcelPropertiesStatus reason2;
            if (!avatar.lastKnownAllowedPosition.Equals(Vector3.Zero))
            {
                pos = avatar.lastKnownAllowedPosition;
            }
            else
            {
                // Still a forbidden parcel, they must have been above the limit or entering region for the first time.
                // Let's put them up higher, over the restricted parcel.
                // We could add 50m to avatar.Scene.Heightmap[x,y] but then we need subscript checks, etc.
                // For now, this is simple and safer than TPing them home.
                pos.Z += 50.0f;
            }

            ILandObject parcel = landChannel.GetLandObject(pos.X, pos.Y);
            if ((parcel != null) && parcel.DenyParcelAccess(avatar.UUID, out reason2))
            {
                float minZ = LandChannel.BAN_LINE_SAFETY_HEIGHT + AVATAR_BOUNCE;
                if (pos.Z < minZ)
                    pos.Z = minZ;
            }

            // Now force the non-sitting avatar to a position above the parcel
            avatar.Teleport(pos);   // this is really just a move
        }
        public virtual void DoTeleport(ScenePresence sp, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags)
        {
            sp.ControllingClient.SendTeleportProgress(teleportFlags, "sending_dest");
            if (finalDestination == null)
            {
                sp.ControllingClient.SendTeleportFailed("Unable to locate destination");
                return;
            }

            m_log.DebugFormat(
                "[ENTITY TRANSFER MODULE]: Request Teleport to {0}:{1}/{2}",
                finalDestination.ServerURI, finalDestination.RegionName, position);

            int newRegionX = finalDestination.RegionLocX;
            int newRegionY = finalDestination.RegionLocY;
            int oldRegionX = sp.Scene.RegionInfo.RegionLocX;
            int oldRegionY = sp.Scene.RegionInfo.RegionLocY;

            sp.ControllingClient.SendTeleportProgress(teleportFlags, "arriving");

            // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
            // both regions
            if (sp.ParentID != UUID.Zero)
                sp.StandUp();

            //Make sure that all attachments are ready for the teleport
            IAttachmentsModule attModule = sp.Scene.RequestModuleInterface<IAttachmentsModule>();
            if(attModule != null)
                attModule.ValidateAttachments(sp.UUID);

            AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
            agentCircuit.startpos = position;
            //The agent will be a root agent
            agentCircuit.child = false;
            //Make sure the appearnace is right
            agentCircuit.Appearance = sp.Appearance;

            AgentData agent = new AgentData();
            sp.CopyTo(agent);
            //Fix the position
            agent.Position = position;

            IEventQueueService eq = sp.Scene.RequestModuleInterface<IEventQueueService>();
            if (eq != null)
            {
                //This does CreateAgent and sends the EnableSimulator/EstablishAgentCommunication/TeleportFinish
                //  messages if they need to be called and deals with the callback
                if (!eq.TeleportAgent(sp.UUID, (int)sp.DrawDistance,
                    agentCircuit, agent, teleportFlags, finalDestination, sp.Scene.RegionInfo.RegionHandle))
                {
                    // Fix the agent status
                    sp.IsChildAgent = false;
                    sp.ControllingClient.SendTeleportFailed("Destination refused");
                    return;
                }
            }

            //Kill the groups here, otherwise they will become ghost attachments 
            //  and stay in the sim, they'll get readded below into the new sim
            KillAttachments(sp);

            // Well, this is it. The agent is over there.
            KillEntity(sp.Scene, sp);

            INeighborService service = sp.Scene.RequestModuleInterface<INeighborService>();
            if (service != null)
            {
                //Check that the region the client is in right now isn't a part of the
                //  regions that should be closed as well
                if (service.IsOutsideView(sp.Scene.RegionInfo.RegionLocX, finalDestination.RegionLocX,
                    sp.Scene.RegionInfo.RegionLocY, finalDestination.RegionLocY))
                {
                    Thread.Sleep(1000);
                    // Fix this so that when we close, we don't have the wrong type
                    sp.IsChildAgent = false;
                    //Wait a bit for the agent to leave this region, then close them
                    sp.Scene.IncomingCloseAgent(sp.UUID);
                }
                else
                    sp.MakeChildAgent();
            }
        }
Beispiel #10
0
        public void DoTeleport(
            ScenePresence sp, GridRegion reg, GridRegion finalDestination,
            Vector3 position, Vector3 lookAt, uint teleportFlags)
        {
            // Record that this agent is in transit so that we can prevent simultaneous requests and do later detection
            // of whether the destination region completes the teleport.
            if (!m_entityTransferStateMachine.SetInTransit(sp.UUID))
            {
                m_log.DebugFormat(
                    "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.",
                    sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position);

                return;
            }

            if (reg == null || finalDestination == null)
            {
                sp.ControllingClient.SendTeleportFailed("Unable to locate destination");
                m_entityTransferStateMachine.ResetFromTransit(sp.UUID);

                return;
            }

            m_log.DebugFormat(
                "[ENTITY TRANSFER MODULE]: Teleporting {0} {1} from {2} to {3} ({4}) {5}/{6}",
                sp.Name, sp.UUID, sp.Scene.RegionInfo.RegionName,
                reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position);

            RegionInfo sourceRegion = sp.Scene.RegionInfo;

            if (!IsWithinMaxTeleportDistance(sourceRegion, finalDestination))
            {
                sp.ControllingClient.SendTeleportFailed(
                    string.Format(
                      "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way",
                      finalDestination.RegionName, finalDestination.RegionCoordX, finalDestination.RegionCoordY,
                      sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY,
                      MaxTransferDistance));

                m_entityTransferStateMachine.ResetFromTransit(sp.UUID);

                return;
            }

            uint newRegionX = (uint)(reg.RegionHandle >> 40);
            uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
            uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40);
            uint oldRegionY = (((uint)(sp.Scene.RegionInfo.RegionHandle)) >> 8);

            ulong destinationHandle = finalDestination.RegionHandle;

            // Let's do DNS resolution only once in this process, please!
            // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
            // it's actually doing a lot of work.
            IPEndPoint endPoint = finalDestination.ExternalEndPoint;

            if (endPoint.Address == null)
            {
                sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
                m_entityTransferStateMachine.ResetFromTransit(sp.UUID);

                return;
            }

            if (!sp.ValidateAttachments())
                m_log.DebugFormat(
                    "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}.  Continuing.",
                    sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName);

//                if (!sp.ValidateAttachments())
//                {
//                    sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
//                    return;
//                }

            string reason;
            string version;
            if (!Scene.SimulationService.QueryAccess(
                finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason))
            {
                sp.ControllingClient.SendTeleportFailed(reason);
                m_entityTransferStateMachine.ResetFromTransit(sp.UUID);

                m_log.DebugFormat(
                    "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}",
                    sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);

                return;
            }

            m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version);

            // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
            // both regions
            if (sp.ParentID != (uint)0)
                sp.StandUp();

            // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to
            // the viewer.  However, it might mean that the viewer does not see the black teleport screen (untested).
            sp.ControllingClient.SendTeleportStart(teleportFlags);

            // the avatar.Close below will clear the child region list. We need this below for (possibly)
            // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
            //List<ulong> childRegions = avatar.KnownRegionHandles;
            // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
            // failure at this point (unlike a border crossing failure).  So perhaps this can never fail
            // once we reach here...
            //avatar.Scene.RemoveCapsHandler(avatar.UUID);

            string capsPath = String.Empty;

            AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
            AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
            agentCircuit.startpos = position;
            agentCircuit.child = true;
            agentCircuit.Appearance = sp.Appearance;
            if (currentAgentCircuit != null)
            {
                agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
                agentCircuit.IPAddress = currentAgentCircuit.IPAddress;
                agentCircuit.Viewer = currentAgentCircuit.Viewer;
                agentCircuit.Channel = currentAgentCircuit.Channel;
                agentCircuit.Mac = currentAgentCircuit.Mac;
                agentCircuit.Id0 = currentAgentCircuit.Id0;
            }

            if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
            {
                // brand new agent, let's create a new caps seed
                agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
            }

            // Let's create an agent there if one doesn't exist yet. 
            bool logout = false;
            if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
            {
                sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason));
                m_entityTransferStateMachine.ResetFromTransit(sp.UUID);

                m_log.DebugFormat(
                    "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}",
                    sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);

                return;
            }

            // Past this point we have to attempt clean up if the teleport fails, so update transfer state.
            m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);

            // OK, it got this agent. Let's close some child agents
            sp.CloseChildAgents(newRegionX, newRegionY);

            IClientIPEndpoint ipepClient;  
            if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
            {
                //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
                #region IP Translation for NAT
                // Uses ipepClient above
                if (sp.ClientView.TryGet(out ipepClient))
                {
                    endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
                }
                #endregion
                capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);

                if (m_eqModule != null)
                {
                    m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID);

                    // ES makes the client send a UseCircuitCode message to the destination, 
                    // which triggers a bunch of things there.
                    // So let's wait
                    Thread.Sleep(200);

                    // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears
                    // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly
                    // only on TeleportFinish).  This is untested for region teleport between different simulators
                    // though this probably also works.
                    m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
                }
                else
                {
                    sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
                }
            }
            else
            {
                agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
                capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
            }

            // Let's send a full update of the agent. This is a synchronous call.
            AgentData agent = new AgentData();
            sp.CopyTo(agent);
            agent.Position = position;
            SetCallbackURL(agent, sp.Scene.RegionInfo);

            //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");

            if (!UpdateAgent(reg, finalDestination, agent, sp))
            {
                // Region doesn't take it
                m_log.WarnFormat(
                    "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}.  Returning avatar to source region.",
                    sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
                
                Fail(sp, finalDestination, logout);
                return;
            }

            sp.ControllingClient.SendTeleportProgress(teleportFlags | (uint)TeleportFlags.DisableCancel, "sending_dest");

            m_log.DebugFormat(
                "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
                capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);

            if (m_eqModule != null)
            {
                m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID);
            }
            else
            {
                sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
                                                            teleportFlags, capsPath);
            }

            // Let's set this to true tentatively. This does not trigger OnChildAgent
            sp.IsChildAgent = true;

            // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
            // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
            // that the client contacted the destination before we close things here.
            if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID))
            {
                m_log.WarnFormat(
                    "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region.  Returning avatar to source region.",
                    sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
                
                Fail(sp, finalDestination, logout);                   
                return;
            }

            m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);

            // For backwards compatibility
            if (version == "Unknown" || version == string.Empty)
            {
                // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
                m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Old simulator, sending attachments one by one...");
                CrossAttachmentsIntoNewRegion(finalDestination, sp, true);
            }

            // May need to logout or other cleanup
            AgentHasMovedAway(sp, logout);

            // Well, this is it. The agent is over there.
            KillEntity(sp.Scene, sp.LocalId);

            // Now let's make it officially a child agent
            sp.MakeChildAgent();

//                sp.Scene.CleanDroppedAttachments();

            // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone

            if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
            {
                // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before
                // they regard the new region as the current region after receiving the AgentMovementComplete
                // response.  If close is sent before then, it will cause the viewer to quit instead.
                //
                // This sleep can be increased if necessary.  However, whilst it's active,
                // an agent cannot teleport back to this region if it has teleported away.
                Thread.Sleep(2000);

                sp.Scene.IncomingCloseAgent(sp.UUID, false);
            }
            else
            {
                // now we have a child agent in this region. 
                sp.Reset();
            }

            // Commented pending deletion since this method no longer appears to do anything at all
//            // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
//            if (sp.Scene.NeedSceneCacheClear(sp.UUID))
//            {
//                m_log.DebugFormat(
//                    "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
//                    sp.UUID);
//            }

            m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
        }
        public void handleAvatarChangingParcel(ScenePresence avatar, int localLandID, UUID regionID)
        {
            if (m_scene.RegionInfo.RegionID == regionID)
            {
                ILandObject parcelAvatarIsEntering;
                lock (m_landList)
                {
                    parcelAvatarIsEntering = m_landList[localLandID];
                }

                if (parcelAvatarIsEntering != null)
                {
                    Vector3 pos = avatar.AbsolutePosition;
                    if (pos.Z < LandChannel.BAN_LINE_SAFETY_HEIGHT)
                    {
                        ParcelPropertiesStatus reason;
                        if (parcelAvatarIsEntering.DenyParcelAccess(avatar.UUID, out reason))
                        {
                            // Check if the avatar is seated and unsit before reposition/teleport in SendNoEntryNotice.
                            EntityBase.PositionInfo posInfo = avatar.GetPosInfo();
                            if (posInfo.Parent != null)
                                avatar.StandUp(null, false, true);
                            SendNoEntryNotice(avatar, reason);
                        }
                        else
                        {
                            avatar.lastKnownAllowedPosition = new Vector3(pos);
                        }
                    }
                    else
                    {
                        avatar.lastKnownAllowedPosition = new Vector3(pos);
                    }
                }
            }
        }
        private void SetPropertyValue(ScenePresence sp, SyncableProperties.Type property, SyncedProperty pSyncInfo)
        {
            if (sp == null || pSyncInfo == null) return;

            Object pValue = pSyncInfo.LastUpdateValue;
            switch (property)
            {
                case SyncableProperties.Type.LocalId:
                    sp.LocalId = (uint)pValue;
                    break;
                case SyncableProperties.Type.AbsolutePosition:
                    sp.AbsolutePosition = (Vector3)pValue;
                    break;
                case SyncableProperties.Type.AgentCircuitData:
                    DebugLog.WarnFormat("{0}: Received updated AgentCircuitData. Not implemented", LogHeader);
                    break;
                case SyncableProperties.Type.ParentId:
                    uint localID = (uint)pValue;
                    if (localID == 0)
                    {
                        // DebugLog.DebugFormat("{0}: SetPropertyValue:ParentID. Standup. Input={1}", LogHeader, localID); // DEBUG DEBUG
                        sp.StandUp();
                    }
                    else
                    {
                        SceneObjectPart parentPart = Scene.GetSceneObjectPart(localID);
                        if (parentPart != null) // TODO ??
                        {
                            sp.HandleAgentRequestSit(sp.ControllingClient, sp.ControllingClient.AgentId, parentPart.UUID, Vector3.Zero);
                            // DebugLog.DebugFormat("{0}: SetPropertyValue:ParentID. SitRequest. Input={1},sp={2},newParentID={3}",
                            //                 LogHeader, localID, (string)(sp == null ? "NULL" : sp.Name), sp.ParentID); // DEBUG DEBUG
                        }
                    }
                    //sp.ParentID = (uint)pValue;
                    break;
                case SyncableProperties.Type.AgentControlFlags:
                    sp.AgentControlFlags = (uint)pValue;
                    break;
                case SyncableProperties.Type.AllowMovement:
                    sp.AllowMovement = (bool)pValue;
                    break;
                case SyncableProperties.Type.AvatarAppearance:
                    sp.Appearance.Unpack((OSDMap)pValue);
                    sp.SendAppearanceToAllOtherAgents();
                    DebugLog.DebugFormat("{0} Received updated AvatarAppearance for uuid {1}.", LogHeader, sp.UUID);
                    break;
                case SyncableProperties.Type.Animations:
                    UpdateAvatarAnimations(sp, (OSDArray)pValue);
                    break;
                case SyncableProperties.Type.Rotation:
                    sp.Rotation = (Quaternion)pValue;
                    break;
                case SyncableProperties.Type.PA_Velocity:
                    if (sp.PhysicsActor != null)
                        sp.PhysicsActor.Velocity = (Vector3)pValue;
                    break;
                case SyncableProperties.Type.RealRegion:
                    ////// NOP //////
                    break;
                case SyncableProperties.Type.PA_TargetVelocity:
                    if(sp.PhysicsActor != null)
                        sp.PhysicsActor.TargetVelocity = (Vector3)pValue;
                     break;
                case SyncableProperties.Type.Flying:
                    sp.Flying = (bool)pValue;
                    break;
                case SyncableProperties.Type.PresenceType:
                    DebugLog.WarnFormat("{0} Received updated PresenceType for uuid {1}. Not implemented", LogHeader, sp.UUID);
                    break;
                case SyncableProperties.Type.IsColliding:
                    if(sp.PhysicsActor != null)
                        sp.IsColliding = (bool)pValue;
                    break;
            }

            // When presence values are changed, we tell the simulator with an event
            GenerateAgentUpdated(sp);
        }
 public void Teleport(ScenePresence botPresence, Vector3 pos)
 {
     botPresence.StandUp(null, false, true);
     botPresence.Teleport(pos);
 }
        // Bounce constants are how far above a no-entry parcel we'll place an object or avatar.
        public void RemoveAvatarFromParcel(ScenePresence avatar)
        {
            EntityBase.PositionInfo posInfo = avatar.GetPosInfo();

            if (posInfo.Parent != null)
            {
                // can't find the prim seated on, stand up
                avatar.StandUp(false, true);

                // fall through to unseated avatar code.
            }

            // If they are moving, stop them.  This updates the physics object as well.
            // The avatar needs to be stopped before entering the parcel otherwise there
            // are timing windows where the avatar can just pound away at the parcel border
            // and get across it due to physics placing them there.
            avatar.Velocity = Vector3.Zero;

            Vector3 pos = avatar.AbsolutePosition;  // may have changed from posInfo by StandUp above.

            ParcelPropertiesStatus reason2;
            if (!avatar.lastKnownAllowedPosition.Equals(Vector3.Zero))
            {
                pos = avatar.lastKnownAllowedPosition;
            }

            ILandObject parcel = landChannel.GetLandObject(pos.X, pos.Y);
            float minZ;
            if ((parcel != null) && m_scene.TestBelowHeightLimit(avatar.UUID, pos, parcel, out minZ, out reason2))
            {
                float groundZ = (float)m_scene.Heightmap.CalculateHeightAt(pos.X, pos.Y);
                minZ += groundZ;

                // make them bounce above the banned parcel if being removed
                if (pos.Z < minZ)
                    pos.Z = minZ + Constants.AVATAR_BOUNCE;
            }

            // Now force the non-sitting avatar to a position above the parcel
            avatar.Teleport(pos);   // this is really just a move
        }