Teleport() public method

public Teleport ( Vector3 pos ) : void
pos Vector3
return void
        public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
        {
            if (!sp.Scene.Permissions.CanTeleport(sp.UUID))
                return;

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

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

            try
            {
                if (regionHandle == sp.Scene.RegionInfo.RegionHandle)
                {
                    m_log.DebugFormat(
                        "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation {0} within {1}",
                        position, sp.Scene.RegionInfo.RegionName);

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

                        m_log.WarnFormat(
                            "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}.  Substituting {3}",
                            position, sp.Name, sp.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)sp.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;
                    }

                    sp.ControllingClient.SendTeleportStart(teleportFlags);

                    sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
                    sp.Teleport(position);

                    foreach (SceneObjectGroup grp in sp.GetAttachments())
                    {
                        if (grp.IsDeleted)
                            sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT);
                    }
                }
                else // Another region possibly in another simulator
                {
                    uint x = 0, y = 0;
                    Utils.LongToUInts(regionHandle, out x, out y);
                    GridRegion reg = m_aScene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);

                    if (reg != null)
                    {
                        GridRegion finalDestination = GetFinalDestination(reg);
                        if (finalDestination == null)
                        {
                            m_log.WarnFormat("[ENTITY TRANSFER MODULE]: Final destination is having problems. Unable to teleport agent.");
                            sp.ControllingClient.SendTeleportFailed("Problem at destination");
                            return;
                        }

                        uint curX = 0, curY = 0;
                        Utils.LongToUInts(sp.Scene.RegionInfo.RegionHandle, out curX, out curY);
                        int curCellX = (int)(curX / Constants.RegionSize);
                        int curCellY = (int)(curY / Constants.RegionSize);
                        int destCellX = (int)(finalDestination.RegionLocX / Constants.RegionSize);
                        int destCellY = (int)(finalDestination.RegionLocY / Constants.RegionSize);

//                        m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY);
//
//                        m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}",
//                            destRegionX, destRegionY, finalDestination.RegionID, finalDestination.ServerURI);

                        // Check that these are not the same coordinates
                        if (finalDestination.RegionLocX == sp.Scene.RegionInfo.RegionLocX &&
                            finalDestination.RegionLocY == sp.Scene.RegionInfo.RegionLocY)
                        {
                            // Can't do. Viewer crashes
                            sp.ControllingClient.SendTeleportFailed("Space warp! You would crash. Move to a different region and try again.");
                            return;
                        }

                        if (Math.Abs(curCellX - destCellX) > MaxTransferDistance || Math.Abs(curCellY - destCellY) > MaxTransferDistance)
                        {
                            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, destCellX, destCellY,
                                  sp.Scene.RegionInfo.RegionName, curCellX, curCellY,
                                  MaxTransferDistance));

                            return;
                        }

                        //
                        // This is it
                        //
                        DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags, eq);
                        //
                        //
                        //
                    }
                    else
                    {
                        // TP to a place that doesn't exist (anymore)
                        // Inform the viewer about that
                        sp.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);
                        sp.ControllingClient.SendMapBlock(blocks, 0);
                    }
                }
            }
            catch (Exception e)
            {
                m_log.WarnFormat("[ENTITY TRANSFER MODULE]: Exception on teleport: {0} {1}", e.Message, e.StackTrace);
                sp.ControllingClient.SendTeleportFailed("Internal error");
            }
        }
        /// <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 #3
0
        /// <summary>
        /// Teleports the agent within its current region.
        /// </summary>
        /// <param name="sp"></param>
        /// <param name="position"></param>
        /// <param name="lookAt"></param>
        /// <param name="teleportFlags"></param>
        private void TeleportAgentWithinRegion(ScenePresence sp, Vector3 position, Vector3 lookAt, uint teleportFlags)
        {
            m_log.DebugFormat(
                "[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}",
                sp.Name, position, sp.Scene.RegionInfo.RegionName);

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

                m_log.WarnFormat(
                    "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2} in {3}.  Substituting {4}",
                    position, sp.Name, sp.UUID, Scene.Name, emergencyPos);

                position = emergencyPos;
            }

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

            // TODO: Check other Scene HeightField
            posZLimit = (float)sp.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;
            }

            if (sp.Flying)
                teleportFlags |= (uint)TeleportFlags.IsFlying;

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

            sp.ControllingClient.SendTeleportStart(teleportFlags);

            sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
            sp.TeleportFlags = (Constants.TeleportFlags)teleportFlags;
            sp.Velocity = Vector3.Zero;
            sp.Teleport(position);

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

            foreach (SceneObjectGroup grp in sp.GetAttachments())
            {
                sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT);
            }

            m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
        }
        public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
        {
            if (!sp.Scene.Permissions.CanTeleport(sp.UUID))
                return;

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

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

            try
            {
                if (regionHandle == sp.Scene.RegionInfo.RegionHandle)
                {
                    m_log.DebugFormat(
                        "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation {0} within {1}",
                        position, sp.Scene.RegionInfo.RegionName);

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

                        m_log.WarnFormat(
                            "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}.  Substituting {3}",
                            position, sp.Name, sp.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)sp.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)
                        sp.ControllingClient.SendTeleportLocationStart();

                    sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
                    sp.Teleport(position);
                }
                else // Another region possibly in another simulator
                {
                    uint x = 0, y = 0;
                    Utils.LongToUInts(regionHandle, out x, out y);
                    GridRegion reg = m_aScene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);

                    if (reg != null)
                    {
                        GridRegion finalDestination = GetFinalDestination(reg);
                        if (finalDestination == null)
                        {
                            m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final destination is having problems. Unable to teleport agent.");
                            sp.ControllingClient.SendTeleportFailed("Problem at destination");
                            return;
                        }
                        m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final destination is x={0} y={1} uuid={2}",
                            finalDestination.RegionLocX / Constants.RegionSize, finalDestination.RegionLocY / Constants.RegionSize, finalDestination.RegionID);

                        //
                        // This is it
                        //
                        DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags, eq);
                        //
                        //
                        //
                    }
                    else
                    {
                        // TP to a place that doesn't exist (anymore)
                        // Inform the viewer about that
                        sp.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);
                        sp.ControllingClient.SendMapBlock(blocks, 0);
                    }
                }
            }
            catch (Exception e)
            {
                m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Exception on teleport: {0}\n{1}", e.Message, e.StackTrace);
                sp.ControllingClient.SendTeleportFailed("Internal error");
            }
        }
        public void EventManagerOnAvatarEnteringNewParcel(ScenePresence avatar, int localLandID, UUID regionID)
        {
            if (m_scene.RegionInfo.RegionID == regionID)
            {
                ILandObject parcelAvatarIsEntering = GetLandObject(localLandID);

                if (parcelAvatarIsEntering != null)
                {
                    //Tell the clint about it
                    parcelAvatarIsEntering.SendLandUpdateToClient(avatar.ControllingClient);
                    
                    if (UseDwell)
                        parcelAvatarIsEntering.LandData.Dwell += 1;
                    if (avatar.AbsolutePosition.Z < ParcelManagementModule.BAN_LINE_SAFETY_HEIGHT)
                    {
                        if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID))
                        {
                            SendYouAreBannedNotice(avatar);
                            Vector3 pos = GetNearestAllowedPosition(avatar);
                            avatar.Teleport(pos);
                        }
                        else if (parcelAvatarIsEntering.IsRestrictedFromLand(avatar.UUID))
                        {
                            SendYouAreRestrictedNotice(avatar);
                            Vector3 pos = GetNearestAllowedPosition(avatar);
                            avatar.Teleport(pos);
                        }
                    }
                }
            }
        }
 public void EventManagerOnClientMovement(ScenePresence avatar)
 //Like handleEventManagerOnSignificantClientMovement, but called with an AgentUpdate regardless of distance.
 {
     ILandObject over = GetLandObject((int)avatar.AbsolutePosition.X, (int)avatar.AbsolutePosition.Y);
     if (over != null)
     {
         if (!over.IsRestrictedFromLand(avatar.UUID) && (!over.IsBannedFromLand(avatar.UUID) || avatar.AbsolutePosition.Z >= LandChannel.BAN_LINE_SAFETY_HEIGHT))
         {
             avatar.lastKnownAllowedPosition =
                 new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z);
         }
         else
         {
             //Kick them out
             Vector3? pos = landChannel.GetNearestAllowedPosition(avatar);
             if (pos.HasValue)
                 avatar.Teleport(pos.Value);
         }
     }
 }
        public virtual void Teleport(ScenePresence sp, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags)
        {
            string reason = "";

            sp.ControllingClient.SendTeleportStart(teleportFlags);
            sp.ControllingClient.SendTeleportProgress(teleportFlags, "requesting");

            // Reset animations; the viewer does that in teleports.
            if(sp.Animator != null)
                sp.Animator.ResetAnimations();

            try
            {
                long XShift = (finalDestination.RegionLocX - sp.Scene.RegionInfo.RegionLocX);
                long YShift = (finalDestination.RegionLocY - sp.Scene.RegionInfo.RegionLocY);
                if (finalDestination.RegionHandle == sp.Scene.RegionInfo.RegionHandle || //Take region size into account as well
                    (XShift < sp.Scene.RegionInfo.RegionSizeX && YShift < sp.Scene.RegionInfo.RegionSizeY &&
                    XShift > 0 && YShift > 0 && //Can't have negatively sized regions
                    sp.Scene.RegionInfo.RegionSizeX != int.MaxValue && sp.Scene.RegionInfo.RegionSizeY != int.MaxValue))
                {
                    //First check whether the user is allowed to move at all
                    if (!sp.Scene.Permissions.AllowedOutgoingLocalTeleport(sp.UUID, out reason))
                    {
                        sp.ControllingClient.SendTeleportFailed(reason);
                        return;
                    }
                    //Now respect things like parcel bans with this
                    if (!sp.Scene.Permissions.AllowedIncomingTeleport(sp.UUID, position, out position, out reason))
                    {
                        sp.ControllingClient.SendTeleportFailed(reason);
                        return;
                    }
                    m_log.DebugFormat(
                        "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation {0} within {1}",
                        position, sp.Scene.RegionInfo.RegionName);

                    //We have to add the shift as it is brought into this as well in regions that have larger RegionSizes
                    position.X += XShift;
                    position.Y += YShift;

                    //Keep users from being underground
                    ITerrainChannel channel = sp.Scene.RequestModuleInterface<ITerrainChannel>();
                    float groundHeight = channel.GetNormalizedGroundHeight(position.X, position.Y);
                    if (position.Z < groundHeight)
                    {
                        position.Z = groundHeight;
                    }

                    sp.ControllingClient.SendTeleportStart(teleportFlags);

                    sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
                    sp.Teleport(position);
                }
                else // Another region possibly in another simulator
                {
                    // Make sure the user is allowed to leave this region
                    if (!sp.Scene.Permissions.AllowedOutgoingRemoteTeleport(sp.UUID, out reason))
                    {
                        sp.ControllingClient.SendTeleportFailed(reason);
                        return;
                    }
                    //m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final destination is x={0} y={1} uuid={2}",
                    //    finalDestination.RegionLocX / Constants.RegionSize, finalDestination.RegionLocY / Constants.RegionSize, finalDestination.RegionID);

                    // Check that these are not the same coordinates
                    if (finalDestination.RegionLocX == sp.Scene.RegionInfo.RegionLocX &&
                        finalDestination.RegionLocY == sp.Scene.RegionInfo.RegionLocY)
                    {
                        // Can't do. Viewer crashes
                        sp.ControllingClient.SendTeleportFailed("Space warp! You would crash. Move to a different region and try again.");
                        return;
                    }

                    //
                    // This is it
                    //
                    DoTeleport(sp, finalDestination, position, lookAt, teleportFlags);
                    //
                    //
                    //
                }
            }
            catch (Exception e)
            {
                m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: Exception on teleport: {0}\n{1}", e.Message, e.StackTrace);
                sp.ControllingClient.SendTeleportFailed("Internal error");
            }
        }
        public void EventManagerOnAvatarEnteringNewParcel(ScenePresence avatar, int localLandID, UUID regionID)
        {
            if (m_scene.RegionInfo.RegionID == regionID)
            {
                ILandObject parcelAvatarIsEntering = landChannel.GetLandObject(localLandID);

                if (parcelAvatarIsEntering != null)
                {
                    if (UseDwell)
                        parcelAvatarIsEntering.LandData.Dwell += 1;
                    if (AllowedForcefulBans)
                    {
                        if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HEIGHT)
                        {
                            if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID))
                            {
                                SendYouAreBannedNotice(avatar);
                                Vector3? pos = landChannel.GetNearestAllowedPosition(avatar);
                                if (pos.HasValue)
                                    avatar.Teleport(pos.Value);
                            }
                            else if (parcelAvatarIsEntering.IsRestrictedFromLand(avatar.UUID))
                            {
                                SendYouAreRestrictedNotice(avatar);
                                Vector3? pos = landChannel.GetNearestAllowedPosition(avatar);
                                if (pos.HasValue)
                                    avatar.Teleport(pos.Value);
                            }
                        }
                    }
                }
            }
        }
        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 bool SendNoEntryNotice(ScenePresence avatar, ParcelPropertiesStatus reason)
        {
            if (!AllowedForcefulBans)
            {
                avatar.ControllingClient.SendAlertMessage(
                    "You are not allowed on this parcel, however the grid administrator has disabled ban lines globally. Please respect the land owner's privacy, or you could be banned from the full region.");
                return false;
            }

            if (reason == ParcelPropertiesStatus.CollisionBanned)
                avatar.ControllingClient.SendAlertMessage(
                    "You are not permitted to enter this parcel because you are banned.");
            else
                avatar.ControllingClient.SendAlertMessage(
                    "You are not permitted to enter this parcel due to parcel restrictions.");

            // If they are moving, stop them.  This updates the physics object as well.
            avatar.Velocity = Vector3.Zero;
            Vector3 pos;
            ParcelPropertiesStatus reason2;
            if (!avatar.lastKnownAllowedPosition.Equals(Vector3.Zero))
            {
                pos = new Vector3(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y, avatar.lastKnownAllowedPosition.Z);
            }
            else
            {
                // Still a forbidden parcel, they must have been above the limit or entering region for the first time.
                pos = new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z);
                // 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.DenyParcelAccess(avatar.UUID, out reason2))
            {
                // Havent found anywhere safe to put the avatar, TP them home.
//              avatar.ControllingClient.SendTeleportLocationStart();
//              avatar.Scene.TeleportClientHome(avatar.UUID, avatar.ControllingClient);
//              return true;

                if (pos.Z < 150.0f)
                    pos.Z = 150.0f;
            }

            avatar.Teleport(pos);
            return true;
        }
 public void Teleport(ScenePresence botPresence, Vector3 pos)
 {
     botPresence.StandUp(null, false, true);
     botPresence.Teleport(pos);
 }
        /// <summary>
        /// Teleports the agent within its current region.
        /// </summary>
        /// <param name="sp"></param>
        /// <param name="position"></param>
        /// <param name="lookAt"></param>
        /// <param name="teleportFlags"></param
        private void TeleportAgentWithinRegion(ScenePresence sp, Vector3 position, Vector3 lookAt, uint teleportFlags)
        {
            m_log.DebugFormat(
                "[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}",
                sp.Name, position, sp.Scene.RegionInfo.RegionName);

            if (!SetInTransit(sp.UUID))
            {
                m_log.DebugFormat(
                    "[ENTITY TRANSFER MODULE]: Ignoring within region teleport request of {0} {1} to {2} - agent is already in transit.",
                    sp.Name, sp.UUID, position);

                return;
            }

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

                m_log.WarnFormat(
                    "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}.  Substituting {3}",
                    position, sp.Name, sp.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)sp.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;
            }

            UpdateInTransit(sp.UUID, AgentTransferState.Transferring);

            sp.ControllingClient.SendTeleportStart(teleportFlags);

            sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
            sp.Velocity = Vector3.Zero;
            sp.Teleport(position);

            UpdateInTransit(sp.UUID, AgentTransferState.ReceivedAtDestination);

            foreach (SceneObjectGroup grp in sp.GetAttachments())
            {
                sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT);
            }

            UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
            ResetFromTransit(sp.UUID);            
        }
        // 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
        }