diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 8e6e8fd15a..07564ba6e4 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1646,109 +1646,118 @@ namespace OpenSim.Region.Framework.Scenes "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", client.Name, Scene.Name, AbsolutePosition); - // Make sure it's not a login agent. We don't want to wait for updates during login - if (PresenceType != PresenceType.Npc && (m_teleportFlags & TeleportFlags.ViaLogin) == 0) - { - // Let's wait until UpdateAgent (called by departing region) is done - if (!WaitForUpdateAgent(client)) - // The sending region never sent the UpdateAgent data, we have to refuse - return; - } - - Vector3 look = Velocity; - - // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) - if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1)) - { - look = new Vector3(0.99f, 0.042f, 0); - } - - // Prevent teleporting to an underground location - // (may crash client otherwise) - // - Vector3 pos = AbsolutePosition; - float ground = m_scene.GetGroundHeight(pos.X, pos.Y); - if (pos.Z < ground + 1.5f) - { - pos.Z = ground + 1.5f; - AbsolutePosition = pos; - } - bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); - if (!MakeRootAgent(AbsolutePosition, flying)) + + IsInTransit = true; + try { - m_log.DebugFormat( - "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root", - Name, Scene.Name); + // Make sure it's not a login agent. We don't want to wait for updates during login + if (PresenceType != PresenceType.Npc && (m_teleportFlags & TeleportFlags.ViaLogin) == 0) + { + // Let's wait until UpdateAgent (called by departing region) is done + if (!WaitForUpdateAgent(client)) + // The sending region never sent the UpdateAgent data, we have to refuse + return; + } - return; + Vector3 look = Velocity; + + // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) + if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1)) + { + look = new Vector3(0.99f, 0.042f, 0); + } + + // Prevent teleporting to an underground location + // (may crash client otherwise) + // + Vector3 pos = AbsolutePosition; + float ground = m_scene.GetGroundHeight(pos.X, pos.Y); + if (pos.Z < ground + 1.5f) + { + pos.Z = ground + 1.5f; + AbsolutePosition = pos; + } + + + if (!MakeRootAgent(AbsolutePosition, flying)) + { + m_log.DebugFormat( + "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root", + Name, Scene.Name); + + return; + } + + // Tell the client that we're totally ready + ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); + + // Remember in HandleUseCircuitCode, we delayed this to here + if (m_teleportFlags > 0) + SendInitialDataToMe(); + + // m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); + + if (!string.IsNullOrEmpty(m_callbackURI)) + { + // We cannot sleep here since this would hold up the inbound packet processing thread, as + // CompleteMovement() is executed synchronously. However, it might be better to delay the release + // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete + // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this + // region as the current region, meaning that a close sent before then will fail the teleport. + // System.Threading.Thread.Sleep(2000); + + m_log.DebugFormat( + "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", + client.Name, client.AgentId, m_callbackURI); + + UUID originID; + + lock (m_originRegionIDAccessLock) + originID = m_originRegionID; + + Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI); + m_callbackURI = null; + } + // else + // { + // m_log.DebugFormat( + // "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}", + // client.Name, client.AgentId, m_scene.RegionInfo.RegionName); + // } + + ValidateAndSendAppearanceAndAgentData(); + + // Create child agents in neighbouring regions + if (openChildAgents && !IsChildAgent) + { + IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface(); + if (m_agentTransfer != null) + m_agentTransfer.EnableChildAgents(this); + + IFriendsModule friendsModule = m_scene.RequestModuleInterface(); + if (friendsModule != null) + friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); + + } + + // XXX: If we force an update here, then multiple attachments do appear correctly on a destination region + // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work. + // This may be due to viewer code or it may be something we're not doing properly simulator side. + lock (m_attachments) + { + foreach (SceneObjectGroup sog in m_attachments) + sog.ScheduleGroupForFullUpdate(); + } + + // m_log.DebugFormat( + // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", + // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); } - - // Tell the client that we're totally ready - ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); - - // Remember in HandleUseCircuitCode, we delayed this to here - if (m_teleportFlags > 0) - SendInitialDataToMe(); - -// m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); - - if (!string.IsNullOrEmpty(m_callbackURI)) + finally { - // We cannot sleep here since this would hold up the inbound packet processing thread, as - // CompleteMovement() is executed synchronously. However, it might be better to delay the release - // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete - // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this - // region as the current region, meaning that a close sent before then will fail the teleport. -// System.Threading.Thread.Sleep(2000); - - m_log.DebugFormat( - "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", - client.Name, client.AgentId, m_callbackURI); - - UUID originID; - - lock (m_originRegionIDAccessLock) - originID = m_originRegionID; - - Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI); - m_callbackURI = null; + IsInTransit = false; } -// else -// { -// m_log.DebugFormat( -// "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}", -// client.Name, client.AgentId, m_scene.RegionInfo.RegionName); -// } - - ValidateAndSendAppearanceAndAgentData(); - - // Create child agents in neighbouring regions - if (openChildAgents && !IsChildAgent) - { - IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface(); - if (m_agentTransfer != null) - m_agentTransfer.EnableChildAgents(this); - - IFriendsModule friendsModule = m_scene.RequestModuleInterface(); - if (friendsModule != null) - friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); - - } - - // XXX: If we force an update here, then multiple attachments do appear correctly on a destination region - // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work. - // This may be due to viewer code or it may be something we're not doing properly simulator side. - lock (m_attachments) - { - foreach (SceneObjectGroup sog in m_attachments) - sog.ScheduleGroupForFullUpdate(); - } - -// m_log.DebugFormat( -// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", -// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); - } ///