aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorOren Hurvitz2014-07-10 16:02:38 +0300
committerJustin Clark-Casey2014-08-02 00:56:58 +0100
commit37fcc827e25d362fcd0e2cbb11f5efd0c307e519 (patch)
treeb15dd3e656eec8d07054059cad0a5c0edf7f880a
parentAdded locking in AccessModule to prevent possible errors when shutting down a... (diff)
downloadopensim-SC-37fcc827e25d362fcd0e2cbb11f5efd0c307e519.zip
opensim-SC-37fcc827e25d362fcd0e2cbb11f5efd0c307e519.tar.gz
opensim-SC-37fcc827e25d362fcd0e2cbb11f5efd0c307e519.tar.bz2
opensim-SC-37fcc827e25d362fcd0e2cbb11f5efd0c307e519.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.
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs268
2 files changed, 134 insertions, 136 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 3b1c5d8..69491b7 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -568,7 +568,7 @@ namespace OpenSim.Region.Framework.Scenes
568 } 568 }
569 else 569 else
570 { 570 {
571 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val); 571 m_log.DebugFormat("[SCENE OBJECT]: Not crossing avatar {0} to {1} because it's already in transit", av.Name, val);
572 } 572 }
573 } 573 }
574 574
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.