diff options
5 files changed, 85 insertions, 15 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs index 626932f..b3b0b8a 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs | |||
@@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests | |||
76 | } | 76 | } |
77 | 77 | ||
78 | [Test] | 78 | [Test] |
79 | public void AddForClient() | 79 | public void TestAddForClient() |
80 | { | 80 | { |
81 | TestHelpers.InMethod(); | 81 | TestHelpers.InMethod(); |
82 | // log4net.Config.XmlConfigurator.Configure(); | 82 | // log4net.Config.XmlConfigurator.Configure(); |
@@ -88,7 +88,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests | |||
88 | } | 88 | } |
89 | 89 | ||
90 | [Test] | 90 | [Test] |
91 | public void RemoveForClient() | 91 | public void TestRemoveForClient() |
92 | { | 92 | { |
93 | TestHelpers.InMethod(); | 93 | TestHelpers.InMethod(); |
94 | // TestHelpers.EnableLogging(); | 94 | // TestHelpers.EnableLogging(); |
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index 58f747b..5229c08 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs | |||
@@ -326,15 +326,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
326 | UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, | 326 | UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, |
327 | string message, ChatSourceType src, bool ignoreDistance) | 327 | string message, ChatSourceType src, bool ignoreDistance) |
328 | { | 328 | { |
329 | Vector3 fromRegionPos = fromPos + regionPos; | 329 | if (presence.LifecycleState != ScenePresenceState.Running) |
330 | Vector3 toRegionPos = presence.AbsolutePosition + | 330 | return false; |
331 | new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize, | ||
332 | presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); | ||
333 | |||
334 | int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos); | ||
335 | 331 | ||
336 | if (!ignoreDistance) | 332 | if (!ignoreDistance) |
337 | { | 333 | { |
334 | Vector3 fromRegionPos = fromPos + regionPos; | ||
335 | Vector3 toRegionPos = presence.AbsolutePosition + | ||
336 | new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize, | ||
337 | presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); | ||
338 | |||
339 | int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos); | ||
340 | |||
338 | if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance || | 341 | if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance || |
339 | type == ChatTypeEnum.Say && dis > m_saydistance || | 342 | type == ChatTypeEnum.Say && dis > m_saydistance || |
340 | type == ChatTypeEnum.Shout && dis > m_shoutdistance) | 343 | type == ChatTypeEnum.Shout && dis > m_shoutdistance) |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 17ebc83..316f882 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | |||
@@ -920,6 +920,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
920 | 920 | ||
921 | if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) | 921 | if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) |
922 | { | 922 | { |
923 | if (!sp.Scene.IncomingPreCloseAgent(sp)) | ||
924 | return; | ||
925 | |||
923 | // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before | 926 | // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before |
924 | // they regard the new region as the current region after receiving the AgentMovementComplete | 927 | // they regard the new region as the current region after receiving the AgentMovementComplete |
925 | // response. If close is sent before then, it will cause the viewer to quit instead. | 928 | // response. If close is sent before then, it will cause the viewer to quit instead. |
@@ -1082,6 +1085,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1082 | // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone | 1085 | // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone |
1083 | if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) | 1086 | if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) |
1084 | { | 1087 | { |
1088 | if (!sp.Scene.IncomingPreCloseAgent(sp)) | ||
1089 | return; | ||
1090 | |||
1085 | // RED ALERT!!!! | 1091 | // RED ALERT!!!! |
1086 | // PLEASE DO NOT DECREASE THIS WAIT TIME UNDER ANY CIRCUMSTANCES. | 1092 | // PLEASE DO NOT DECREASE THIS WAIT TIME UNDER ANY CIRCUMSTANCES. |
1087 | // THE VIEWERS SEEM TO NEED SOME TIME AFTER RECEIVING MoveAgentIntoRegion | 1093 | // THE VIEWERS SEEM TO NEED SOME TIME AFTER RECEIVING MoveAgentIntoRegion |
@@ -1095,6 +1101,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1095 | // then this will be handled in IncomingCloseAgent under lock conditions | 1101 | // then this will be handled in IncomingCloseAgent under lock conditions |
1096 | m_log.DebugFormat( | 1102 | m_log.DebugFormat( |
1097 | "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name); | 1103 | "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name); |
1104 | |||
1098 | sp.Scene.IncomingCloseAgent(sp.UUID, false); | 1105 | sp.Scene.IncomingCloseAgent(sp.UUID, false); |
1099 | } | 1106 | } |
1100 | else | 1107 | else |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 051c617..3eaa8fd 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -3695,10 +3695,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
3695 | 3695 | ||
3696 | // We need to ensure that we are not already removing the scene presence before we ask it not to be | 3696 | // We need to ensure that we are not already removing the scene presence before we ask it not to be |
3697 | // closed. | 3697 | // closed. |
3698 | if (sp != null && sp.IsChildAgent && sp.LifecycleState == ScenePresenceState.Running) | 3698 | if (sp != null && sp.IsChildAgent |
3699 | && (sp.LifecycleState == ScenePresenceState.Running | ||
3700 | || sp.LifecycleState == ScenePresenceState.PreRemove)) | ||
3699 | { | 3701 | { |
3700 | m_log.DebugFormat( | 3702 | m_log.DebugFormat( |
3701 | "[SCENE]: Reusing existing child scene presence for {0} in {1}", sp.Name, Name); | 3703 | "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}", |
3704 | sp.Name, sp.LifecycleState, Name); | ||
3702 | 3705 | ||
3703 | // In the case where, for example, an A B C D region layout, an avatar may | 3706 | // In the case where, for example, an A B C D region layout, an avatar may |
3704 | // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C | 3707 | // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C |
@@ -3720,6 +3723,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3720 | // } | 3723 | // } |
3721 | // else if (EntityTransferModule.IsInTransit(sp.UUID)) | 3724 | // else if (EntityTransferModule.IsInTransit(sp.UUID)) |
3722 | 3725 | ||
3726 | sp.LifecycleState = ScenePresenceState.Running; | ||
3727 | |||
3723 | if (EntityTransferModule.IsInTransit(sp.UUID)) | 3728 | if (EntityTransferModule.IsInTransit(sp.UUID)) |
3724 | { | 3729 | { |
3725 | sp.DoNotCloseAfterTeleport = true; | 3730 | sp.DoNotCloseAfterTeleport = true; |
@@ -4454,6 +4459,50 @@ namespace OpenSim.Region.Framework.Scenes | |||
4454 | } | 4459 | } |
4455 | 4460 | ||
4456 | /// <summary> | 4461 | /// <summary> |
4462 | /// Tell a single agent to prepare to close. | ||
4463 | /// </summary> | ||
4464 | /// <remarks> | ||
4465 | /// This should only be called if we may close the agent but there will be some delay in so doing. Meant for | ||
4466 | /// internal use - other callers should almost certainly called IncomingCloseAgent(). | ||
4467 | /// </remarks> | ||
4468 | /// <param name="sp"></param> | ||
4469 | /// <returns>true if pre-close state notification was successful. false if the agent | ||
4470 | /// was not in a state where it could transition to pre-close.</returns> | ||
4471 | public bool IncomingPreCloseAgent(ScenePresence sp) | ||
4472 | { | ||
4473 | lock (m_removeClientLock) | ||
4474 | { | ||
4475 | // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may | ||
4476 | // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not | ||
4477 | // want to obey this close since C may have renewed the child agent lease on B. | ||
4478 | if (sp.DoNotCloseAfterTeleport) | ||
4479 | { | ||
4480 | m_log.DebugFormat( | ||
4481 | "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection", | ||
4482 | sp.IsChildAgent ? "child" : "root", sp.Name, Name); | ||
4483 | |||
4484 | // Need to reset the flag so that a subsequent close after another teleport can succeed. | ||
4485 | sp.DoNotCloseAfterTeleport = false; | ||
4486 | |||
4487 | return false; | ||
4488 | } | ||
4489 | |||
4490 | if (sp.LifecycleState != ScenePresenceState.Running) | ||
4491 | { | ||
4492 | m_log.DebugFormat( | ||
4493 | "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}", | ||
4494 | sp.Name, Name, sp.LifecycleState); | ||
4495 | |||
4496 | return false; | ||
4497 | } | ||
4498 | |||
4499 | sp.LifecycleState = ScenePresenceState.PreRemove; | ||
4500 | |||
4501 | return true; | ||
4502 | } | ||
4503 | } | ||
4504 | |||
4505 | /// <summary> | ||
4457 | /// Tell a single agent to disconnect from the region. | 4506 | /// Tell a single agent to disconnect from the region. |
4458 | /// </summary> | 4507 | /// </summary> |
4459 | /// <param name="agentID"></param> | 4508 | /// <param name="agentID"></param> |
@@ -4472,16 +4521,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
4472 | if (sp == null) | 4521 | if (sp == null) |
4473 | { | 4522 | { |
4474 | m_log.DebugFormat( | 4523 | m_log.DebugFormat( |
4475 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in {1}", | 4524 | "[SCENE]: Called IncomingCloseAgent() with agent ID {0} but no such presence is in {1}", |
4476 | agentID, Name); | 4525 | agentID, Name); |
4477 | 4526 | ||
4478 | return false; | 4527 | return false; |
4479 | } | 4528 | } |
4480 | 4529 | ||
4481 | if (sp.LifecycleState != ScenePresenceState.Running) | 4530 | if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove) |
4482 | { | 4531 | { |
4483 | m_log.DebugFormat( | 4532 | m_log.DebugFormat( |
4484 | "[SCENE]: Called RemoveClient() for {0} in {1} but presence is already in state {2}", | 4533 | "[SCENE]: Called IncomingCloseAgent() for {0} in {1} but presence is already in state {2}", |
4485 | sp.Name, Name, sp.LifecycleState); | 4534 | sp.Name, Name, sp.LifecycleState); |
4486 | 4535 | ||
4487 | return false; | 4536 | return false; |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs index dc3a212..cae7fe5 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs | |||
@@ -37,7 +37,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
37 | /// This is a state machine. | 37 | /// This is a state machine. |
38 | /// | 38 | /// |
39 | /// [Entry] => Running | 39 | /// [Entry] => Running |
40 | /// Running => Removing | 40 | /// Running => PreRemove, Removing |
41 | /// PreRemove => Running, Removing | ||
41 | /// Removing => Removed | 42 | /// Removing => Removed |
42 | /// | 43 | /// |
43 | /// All other methods should only see the scene presence in running state - this is the normal operational state | 44 | /// All other methods should only see the scene presence in running state - this is the normal operational state |
@@ -46,6 +47,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
46 | public enum ScenePresenceState | 47 | public enum ScenePresenceState |
47 | { | 48 | { |
48 | Running, // Normal operation state. The scene presence is available. | 49 | Running, // Normal operation state. The scene presence is available. |
50 | PreRemove, // The presence is due to be removed but can still be returning to running. | ||
49 | Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient. | 51 | Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient. |
50 | Removed, // The presence has been removed from the scene and is effectively dead. | 52 | Removed, // The presence has been removed from the scene and is effectively dead. |
51 | // There is no exit from this state. | 53 | // There is no exit from this state. |
@@ -80,8 +82,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
80 | 82 | ||
81 | lock (this) | 83 | lock (this) |
82 | { | 84 | { |
83 | if (newState == ScenePresenceState.Removing && m_state == ScenePresenceState.Running) | 85 | if (newState == m_state) |
86 | return; | ||
87 | else if (newState == ScenePresenceState.Running && m_state == ScenePresenceState.PreRemove) | ||
84 | transitionOkay = true; | 88 | transitionOkay = true; |
89 | else if (newState == ScenePresenceState.PreRemove && m_state == ScenePresenceState.Running) | ||
90 | transitionOkay = true; | ||
91 | else if (newState == ScenePresenceState.Removing) | ||
92 | { | ||
93 | if (m_state == ScenePresenceState.Running || m_state == ScenePresenceState.PreRemove) | ||
94 | transitionOkay = true; | ||
95 | } | ||
85 | else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing) | 96 | else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing) |
86 | transitionOkay = true; | 97 | transitionOkay = true; |
87 | } | 98 | } |