From 056e66b3dec555613bd96b153ba03a124863dbf2 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 4 Sep 2012 03:14:39 +0200 Subject: Refactor avatar transfer so that the heavy (UpdateAgent) part is separated into it's own sub-method --- .../EntityTransfer/EntityTransferModule.cs | 204 +++++++++++---------- .../Framework/Interfaces/IEntityTransferModule.cs | 4 +- .../Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- 3 files changed, 113 insertions(+), 97 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 9ffb851..1f884c8 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -220,7 +220,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer /// /// /// - /// private void TeleportAgentWithinRegion(ScenePresence sp, Vector3 position, Vector3 lookAt, uint teleportFlags) { m_log.DebugFormat( @@ -982,7 +982,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer agent.IsInTransit = true; CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; - d.BeginInvoke(agent, newpos, x, y, neighbourRegion, isFlying, version, CrossAgentToNewRegionCompleted, d); + d.BeginInvoke(agent, newpos, neighbourRegion, isFlying, version, CrossAgentToNewRegionCompleted, d); return true; } @@ -1039,42 +1039,43 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer icon.EndInvoke(iar); } + public bool CrossAgentToNewRegionPrep(ScenePresence agent, GridRegion neighbourRegion) + { + if (neighbourRegion == null) + return false; + + m_entityTransferStateMachine.SetInTransit(agent.UUID); + + agent.RemoveFromPhysicalScene(); + + return true; + } + /// /// This Closes child agents on neighbouring regions /// Calls an asynchronous method to do so.. so it doesn't lag the sim. /// public ScenePresence CrossAgentToNewRegionAsync( - ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, + ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version) { - if (neighbourRegion == null) + if (!CrossAgentToNewRegionPrep(agent, neighbourRegion)) return agent; - try - { - m_entityTransferStateMachine.SetInTransit(agent.UUID); - - ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); - - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3} running version {4}", - agent.Firstname, agent.Lastname, neighbourx, neighboury, version); - - Scene m_scene = agent.Scene; - - if (!agent.ValidateAttachments()) - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for region crossing of {0} from {1} to {2}. Continuing.", - agent.Name, agent.Scene.RegionInfo.RegionName, neighbourRegion.RegionName); - - pos = pos + agent.Velocity; - Vector3 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0); + if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying)) + return agent; - agent.RemoveFromPhysicalScene(); + CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, version); + return agent; + } + public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying) + { + try + { AgentData cAgent = new AgentData(); agent.CopyTo(cAgent); - cAgent.Position = pos; + cAgent.Position = pos + agent.Velocity; if (isFlying) cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; @@ -1084,7 +1085,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // Beyond this point, extra cleanup is needed beyond removing transit state m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring); - if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) + if (!agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) { // region doesn't take it m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); @@ -1093,93 +1094,108 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer agent.AddToPhysicalScene(isFlying); m_entityTransferStateMachine.ResetFromTransit(agent.UUID); - return agent; + return false; } - //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo(); - agent.ControllingClient.RequestClientInfo(); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[ENTITY TRANSFER MODULE]: Problem crossing user {0} to new region {1} from {2}. Exception {3}{4}", + agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName, e.Message, e.StackTrace); - //m_log.Debug("BEFORE CROSS"); - //Scene.DumpChildrenSeeds(UUID); - //DumpKnownRegions(); - string agentcaps; - if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps)) - { - m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.", - neighbourRegion.RegionHandle); - return agent; - } - // No turning back - agent.IsChildAgent = true; + // TODO: Might be worth attempting other restoration here such as reinstantiation of scripts, etc. + return false; + } - string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); + return true; + } - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); + public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, + bool isFlying, string version) + { + agent.ControllingClient.RequestClientInfo(); - if (m_eqModule != null) - { - m_eqModule.CrossRegion( - neighbourHandle, pos, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint, - capsPath, agent.UUID, agent.ControllingClient.SessionId); - } - else - { - agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint, - capsPath); - } + string agentcaps; + if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps)) + { + m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.", + neighbourRegion.RegionHandle); + return; + } - // SUCCESS! - m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination); + // No turning back + agent.IsChildAgent = true; - // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. - m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); + string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); - agent.MakeChildAgent(); + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); - // FIXME: Possibly this should occur lower down after other commands to close other agents, - // but not sure yet what the side effects would be. - m_entityTransferStateMachine.ResetFromTransit(agent.UUID); + Vector3 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0); - // now we have a child agent in this region. Request all interesting data about other (root) agents - agent.SendOtherAgentsAvatarDataToMe(); - agent.SendOtherAgentsAppearanceToMe(); + if (m_eqModule != null) + { + m_eqModule.CrossRegion( + neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint, + capsPath, agent.UUID, agent.ControllingClient.SessionId); + } + else + { + agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint, + capsPath); + } - // Backwards compatibility. Best effort - if (version == "Unknown" || version == string.Empty) - { - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one..."); - Thread.Sleep(3000); // wait a little now that we're not waiting for the callback - CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); - } + // SUCCESS! + m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination); - // Next, let's close the child agent connections that are too far away. - agent.CloseChildAgents(neighbourx, neighboury); + // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. + m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); - AgentHasMovedAway(agent, false); + agent.MakeChildAgent(); - // the user may change their profile information in other region, - // so the userinfo in UserProfileCache is not reliable any more, delete it - // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! - if (agent.Scene.NeedSceneCacheClear(agent.UUID)) - { - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); - } - - //m_log.Debug("AFTER CROSS"); - //Scene.DumpChildrenSeeds(UUID); - //DumpKnownRegions(); - } - catch (Exception e) + // FIXME: Possibly this should occur lower down after other commands to close other agents, + // but not sure yet what the side effects would be. + m_entityTransferStateMachine.ResetFromTransit(agent.UUID); + + // now we have a child agent in this region. Request all interesting data about other (root) agents + agent.SendOtherAgentsAvatarDataToMe(); + agent.SendOtherAgentsAppearanceToMe(); + + // Backwards compatibility. Best effort + if (version == "Unknown" || version == string.Empty) { - m_log.ErrorFormat( - "[ENTITY TRANSFER MODULE]: Problem crossing user {0} to new region {1} from {2}. Exception {3}{4}", - agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName, e.Message, e.StackTrace); + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one..."); + Thread.Sleep(3000); // wait a little now that we're not waiting for the callback + CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); + } - // TODO: Might be worth attempting other restoration here such as reinstantiation of scripts, etc. + // Next, let's close the child agent connections that are too far away. + uint neighbourx; + uint neighboury; + + Utils.LongToUInts(neighbourRegion.RegionHandle, out neighbourx, out neighboury); + + neighbourx /= Constants.RegionSize; + neighboury /= Constants.RegionSize; + + agent.CloseChildAgents(neighbourx, neighboury); + + AgentHasMovedAway(agent, false); + + // the user may change their profile information in other region, + // so the userinfo in UserProfileCache is not reliable any more, delete it + // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! + if (agent.Scene.NeedSceneCacheClear(agent.UUID)) + { + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); } - return agent; + //m_log.Debug("AFTER CROSS"); + //Scene.DumpChildrenSeeds(UUID); + //DumpKnownRegions(); + + return; } private void CrossAgentToNewRegionCompleted(IAsyncResult iar) diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs index 5bc8e51..1949a90 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs @@ -35,7 +35,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.Framework.Interfaces { - public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version); + public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); public interface IEntityTransferModule { @@ -76,7 +76,7 @@ namespace OpenSim.Region.Framework.Interfaces void Cross(SceneObjectGroup sog, Vector3 position, bool silent); - ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version); + ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index bc0f5b6..4798481 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -581,7 +581,7 @@ namespace OpenSim.Region.Framework.Scenes av.IsInTransit = true; CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync; - d.BeginInvoke(av, val, x, y, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d); + d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d); } else m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val); -- cgit v1.1