diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/ScenePresence.cs | 268 |
1 files changed, 133 insertions, 135 deletions
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 17f6301..493090c 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -1691,109 +1691,122 @@ namespace OpenSim.Region.Framework.Scenes | |||
1691 | "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", | 1691 | "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", |
1692 | client.Name, Scene.Name, AbsolutePosition); | 1692 | client.Name, Scene.Name, AbsolutePosition); |
1693 | 1693 | ||
1694 | // Make sure it's not a login agent. We don't want to wait for updates during login | 1694 | bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); // Get this ahead of time because IsInTransit modifies 'm_AgentControlFlags' |
1695 | if (PresenceType != PresenceType.Npc && (m_teleportFlags & TeleportFlags.ViaLogin) == 0) | 1695 | |
1696 | IsInTransit = true; | ||
1697 | try | ||
1696 | { | 1698 | { |
1697 | // Let's wait until UpdateAgent (called by departing region) is done | 1699 | // Make sure it's not a login agent. We don't want to wait for updates during login |
1698 | if (!WaitForUpdateAgent(client)) | 1700 | if (PresenceType != PresenceType.Npc && (m_teleportFlags & TeleportFlags.ViaLogin) == 0) |
1699 | // The sending region never sent the UpdateAgent data, we have to refuse | 1701 | { |
1700 | return; | 1702 | // Let's wait until UpdateAgent (called by departing region) is done |
1701 | } | 1703 | if (!WaitForUpdateAgent(client)) |
1704 | // The sending region never sent the UpdateAgent data, we have to refuse | ||
1705 | return; | ||
1706 | } | ||
1702 | 1707 | ||
1703 | Vector3 look = Velocity; | 1708 | Vector3 look = Velocity; |
1704 | 1709 | ||
1705 | // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) | 1710 | // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) |
1706 | if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1)) | 1711 | if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1)) |
1707 | { | 1712 | { |
1708 | look = new Vector3(0.99f, 0.042f, 0); | 1713 | look = new Vector3(0.99f, 0.042f, 0); |
1709 | } | 1714 | } |
1710 | 1715 | ||
1711 | // Prevent teleporting to an underground location | 1716 | // Prevent teleporting to an underground location |
1712 | // (may crash client otherwise) | 1717 | // (may crash client otherwise) |
1713 | // | 1718 | // |
1714 | Vector3 pos = AbsolutePosition; | 1719 | Vector3 pos = AbsolutePosition; |
1715 | float ground = m_scene.GetGroundHeight(pos.X, pos.Y); | 1720 | float ground = m_scene.GetGroundHeight(pos.X, pos.Y); |
1716 | if (pos.Z < ground + 1.5f) | 1721 | if (pos.Z < ground + 1.5f) |
1717 | { | 1722 | { |
1718 | pos.Z = ground + 1.5f; | 1723 | pos.Z = ground + 1.5f; |
1719 | AbsolutePosition = pos; | 1724 | AbsolutePosition = pos; |
1720 | } | 1725 | } |
1721 | 1726 | ||
1722 | bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); | 1727 | if (!MakeRootAgent(AbsolutePosition, flying)) |
1723 | if (!MakeRootAgent(AbsolutePosition, flying)) | 1728 | { |
1724 | { | 1729 | m_log.DebugFormat( |
1725 | m_log.DebugFormat( | 1730 | "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root", |
1726 | "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root", | 1731 | Name, Scene.Name); |
1727 | Name, Scene.Name); | ||
1728 | 1732 | ||
1729 | return; | 1733 | return; |
1730 | } | 1734 | } |
1731 | 1735 | ||
1732 | // Tell the client that we're totally ready | 1736 | // Tell the client that we're totally ready |
1733 | ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); | 1737 | ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); |
1734 | 1738 | ||
1735 | // Remember in HandleUseCircuitCode, we delayed this to here | 1739 | // Remember in HandleUseCircuitCode, we delayed this to here |
1736 | if (m_teleportFlags > 0) | 1740 | if (m_teleportFlags > 0) |
1737 | SendInitialDataToMe(); | 1741 | SendInitialDataToMe(); |
1738 | 1742 | ||
1739 | // m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); | 1743 | // m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); |
1740 | 1744 | ||
1741 | if (!string.IsNullOrEmpty(m_callbackURI)) | 1745 | if (!string.IsNullOrEmpty(m_callbackURI)) |
1742 | { | 1746 | { |
1743 | // We cannot sleep here since this would hold up the inbound packet processing thread, as | 1747 | // We cannot sleep here since this would hold up the inbound packet processing thread, as |
1744 | // CompleteMovement() is executed synchronously. However, it might be better to delay the release | 1748 | // CompleteMovement() is executed synchronously. However, it might be better to delay the release |
1745 | // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete | 1749 | // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete |
1746 | // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this | 1750 | // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this |
1747 | // region as the current region, meaning that a close sent before then will fail the teleport. | 1751 | // region as the current region, meaning that a close sent before then will fail the teleport. |
1748 | // System.Threading.Thread.Sleep(2000); | 1752 | // System.Threading.Thread.Sleep(2000); |
1749 | 1753 | ||
1750 | m_log.DebugFormat( | 1754 | m_log.DebugFormat( |
1751 | "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", | 1755 | "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", |
1752 | client.Name, client.AgentId, m_callbackURI); | 1756 | client.Name, client.AgentId, m_callbackURI); |
1753 | 1757 | ||
1754 | UUID originID; | 1758 | UUID originID; |
1755 | 1759 | ||
1756 | lock (m_originRegionIDAccessLock) | 1760 | lock (m_originRegionIDAccessLock) |
1757 | originID = m_originRegionID; | 1761 | originID = m_originRegionID; |
1758 | 1762 | ||
1759 | Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI); | 1763 | Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI); |
1760 | m_callbackURI = null; | 1764 | m_callbackURI = null; |
1761 | } | 1765 | } |
1762 | // else | 1766 | // else |
1763 | // { | 1767 | // { |
1764 | // m_log.DebugFormat( | 1768 | // m_log.DebugFormat( |
1765 | // "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}", | 1769 | // "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}", |
1766 | // client.Name, client.AgentId, m_scene.RegionInfo.RegionName); | 1770 | // client.Name, client.AgentId, m_scene.RegionInfo.RegionName); |
1767 | // } | 1771 | // } |
1768 | 1772 | ||
1769 | ValidateAndSendAppearanceAndAgentData(); | 1773 | ValidateAndSendAppearanceAndAgentData(); |
1770 | 1774 | ||
1771 | // Create child agents in neighbouring regions | 1775 | // Create child agents in neighbouring regions |
1772 | if (openChildAgents && !IsChildAgent) | 1776 | if (openChildAgents && !IsChildAgent) |
1773 | { | 1777 | { |
1774 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); | 1778 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); |
1775 | if (m_agentTransfer != null) | 1779 | if (m_agentTransfer != null) |
1776 | m_agentTransfer.EnableChildAgents(this); | 1780 | { |
1781 | // Note: this call can take a while, because it notifies each of the simulator's neighbours. | ||
1782 | // It's important that we don't allow the avatar to cross regions meanwhile, as that will | ||
1783 | // cause serious errors. We've prevented that from happening by setting IsInTransit=true. | ||
1784 | m_agentTransfer.EnableChildAgents(this); | ||
1785 | } | ||
1777 | 1786 | ||
1778 | IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); | 1787 | IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); |
1779 | if (friendsModule != null) | 1788 | if (friendsModule != null) |
1780 | friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); | 1789 | friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); |
1781 | 1790 | ||
1782 | } | 1791 | } |
1783 | 1792 | ||
1784 | // XXX: If we force an update here, then multiple attachments do appear correctly on a destination region | 1793 | // XXX: If we force an update here, then multiple attachments do appear correctly on a destination region |
1785 | // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work. | 1794 | // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work. |
1786 | // This may be due to viewer code or it may be something we're not doing properly simulator side. | 1795 | // This may be due to viewer code or it may be something we're not doing properly simulator side. |
1787 | lock (m_attachments) | 1796 | lock (m_attachments) |
1797 | { | ||
1798 | foreach (SceneObjectGroup sog in m_attachments) | ||
1799 | sog.ScheduleGroupForFullUpdate(); | ||
1800 | } | ||
1801 | |||
1802 | // m_log.DebugFormat( | ||
1803 | // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", | ||
1804 | // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); | ||
1805 | } | ||
1806 | finally | ||
1788 | { | 1807 | { |
1789 | foreach (SceneObjectGroup sog in m_attachments) | 1808 | IsInTransit = false; |
1790 | sog.ScheduleGroupForFullUpdate(); | ||
1791 | } | 1809 | } |
1792 | |||
1793 | // m_log.DebugFormat( | ||
1794 | // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", | ||
1795 | // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); | ||
1796 | |||
1797 | } | 1810 | } |
1798 | 1811 | ||
1799 | /// <summary> | 1812 | /// <summary> |
@@ -3587,65 +3600,50 @@ namespace OpenSim.Region.Framework.Scenes | |||
3587 | if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) | 3600 | if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) |
3588 | return; | 3601 | return; |
3589 | 3602 | ||
3590 | if (!IsInTransit) | 3603 | if (IsInTransit) |
3591 | { | 3604 | return; |
3592 | Vector3 pos2 = AbsolutePosition; | ||
3593 | Vector3 origPosition = pos2; | ||
3594 | Vector3 vel = Velocity; | ||
3595 | 3605 | ||
3596 | // Compute the avatar position in the next physics tick. | 3606 | Vector3 pos2 = AbsolutePosition; |
3597 | // If the avatar will be crossing, we force the crossing to happen now | 3607 | Vector3 origPosition = pos2; |
3598 | // in the hope that this will make the avatar movement smoother when crossing. | 3608 | Vector3 vel = Velocity; |
3599 | float timeStep = 0.1f; | ||
3600 | pos2.X = pos2.X + (vel.X * timeStep); | ||
3601 | pos2.Y = pos2.Y + (vel.Y * timeStep); | ||
3602 | pos2.Z = pos2.Z + (vel.Z * timeStep); | ||
3603 | 3609 | ||
3604 | if (!IsInTransit) | 3610 | // Compute the avatar position in the next physics tick. |
3605 | { | 3611 | // If the avatar will be crossing, we force the crossing to happen now |
3606 | if (!m_scene.PositionIsInCurrentRegion(pos2)) | 3612 | // in the hope that this will make the avatar movement smoother when crossing. |
3607 | { | 3613 | float timeStep = 0.1f; |
3608 | m_log.DebugFormat("{0} CheckForBorderCrossing: position outside region. {1} in {2} at pos {3}", | 3614 | pos2.X = pos2.X + (vel.X * timeStep); |
3609 | LogHeader, Name, Scene.Name, pos2); | 3615 | pos2.Y = pos2.Y + (vel.Y * timeStep); |
3610 | 3616 | pos2.Z = pos2.Z + (vel.Z * timeStep); | |
3611 | // Disconnect from the current region | ||
3612 | bool isFlying = Flying; | ||
3613 | RemoveFromPhysicalScene(); | ||
3614 | // pos2 is the forcasted position so make that the 'current' position so the crossing | ||
3615 | // code will move us into the newly addressed region. | ||
3616 | m_pos = pos2; | ||
3617 | if (CrossToNewRegion()) | ||
3618 | { | ||
3619 | AddToPhysicalScene(isFlying); | ||
3620 | } | ||
3621 | else | ||
3622 | { | ||
3623 | // Tried to make crossing happen but it failed. | ||
3624 | if (m_requestedSitTargetUUID == UUID.Zero) | ||
3625 | { | ||
3626 | m_log.DebugFormat("{0} CheckForBorderCrossing: Crossing failed. Restoring old position.", LogHeader); | ||
3627 | 3617 | ||
3628 | Velocity = Vector3.Zero; | 3618 | if (m_scene.PositionIsInCurrentRegion(pos2)) |
3629 | AbsolutePosition = EnforceSanityOnPosition(origPosition); | 3619 | return; |
3630 | 3620 | ||
3631 | AddToPhysicalScene(isFlying); | 3621 | m_log.DebugFormat("{0} CheckForBorderCrossing: position outside region. {1} in {2} at pos {3}", |
3632 | } | 3622 | LogHeader, Name, Scene.Name, pos2); |
3633 | } | 3623 | |
3634 | } | 3624 | // Disconnect from the current region |
3635 | } | 3625 | bool isFlying = Flying; |
3636 | else | 3626 | RemoveFromPhysicalScene(); |
3627 | // pos2 is the forcasted position so make that the 'current' position so the crossing | ||
3628 | // code will move us into the newly addressed region. | ||
3629 | m_pos = pos2; | ||
3630 | if (CrossToNewRegion()) | ||
3631 | { | ||
3632 | AddToPhysicalScene(isFlying); | ||
3633 | } | ||
3634 | else | ||
3635 | { | ||
3636 | // Tried to make crossing happen but it failed. | ||
3637 | if (m_requestedSitTargetUUID == UUID.Zero) | ||
3637 | { | 3638 | { |
3638 | // This constant has been inferred from experimentation | 3639 | m_log.DebugFormat("{0} CheckForBorderCrossing: Crossing failed. Restoring old position.", LogHeader); |
3639 | // I'm not sure what this value should be, so I tried a few values. | 3640 | |
3640 | timeStep = 0.04f; | 3641 | Velocity = Vector3.Zero; |
3641 | pos2 = AbsolutePosition; | 3642 | AbsolutePosition = EnforceSanityOnPosition(origPosition); |
3642 | pos2.X = pos2.X + (vel.X * timeStep); | 3643 | |
3643 | pos2.Y = pos2.Y + (vel.Y * timeStep); | 3644 | AddToPhysicalScene(isFlying); |
3644 | // Don't touch the Z | ||
3645 | m_pos = pos2; | ||
3646 | m_log.DebugFormat("[SCENE PRESENCE]: In transit m_pos={0}", m_pos); | ||
3647 | } | 3645 | } |
3648 | } | 3646 | } |
3649 | } | 3647 | } |
3650 | 3648 | ||
3651 | // Given a position, make sure it is within the current region. | 3649 | // Given a position, make sure it is within the current region. |