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