From 37dd174697c0bcc201f8d8e4d7569c2a51f53757 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 1 May 2012 17:52:30 +0100 Subject: refactor: Split most of EntityTransferModule.Teleport() into its same region and different region teleport components. DoTeleport() now retrives IEventQueue itself rather than requiring it to be passed in. --- .../Region/CoreModules/Avatar/Lure/HGLureModule.cs | 10 +- .../EntityTransfer/EntityTransferModule.cs | 266 ++++++++++++--------- .../EntityTransfer/HGEntityTransferModule.cs | 15 +- .../Framework/Interfaces/IEntityTransferModule.cs | 37 ++- 4 files changed, 198 insertions(+), 130 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs index bc5c1ff..92cf9d1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs @@ -240,13 +240,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure { ScenePresence sp = scene.GetScenePresence(client.AgentId); IEntityTransferModule transferMod = scene.RequestModuleInterface(); - IEventQueue eq = sp.Scene.RequestModuleInterface(); - if (transferMod != null && sp != null && eq != null) - transferMod.DoTeleport(sp, gatekeeper, finalDestination, im.Position + new Vector3(0.5f, 0.5f, 0f), Vector3.UnitX, teleportflags, eq); + + if (transferMod != null && sp != null) + transferMod.DoTeleport( + sp, gatekeeper, finalDestination, im.Position + new Vector3(0.5f, 0.5f, 0f), + Vector3.UnitX, teleportflags); } } } } } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 779fd6b..b547317 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -170,8 +170,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (!sp.Scene.Permissions.CanTeleport(sp.UUID)) return; - IEventQueue eq = sp.Scene.RequestModuleInterface(); - // Reset animations; the viewer does that in teleports. sp.Animator.ResetAnimations(); @@ -183,145 +181,183 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { destinationRegionName = sp.Scene.RegionInfo.RegionName; - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}", - sp.Name, position, destinationRegionName); + TeleportAgentWithinRegion(sp, position, lookAt, teleportFlags); + } + else // Another region possibly in another simulator + { + GridRegion finalDestination; + TeleportAgentToDifferentRegion( + sp, regionHandle, position, lookAt, teleportFlags, out finalDestination); - // Teleport within the same region - if (IsOutsideRegion(sp.Scene, position) || position.Z < 0) - { - Vector3 emergencyPos = new Vector3(128, 128, 128); + if (finalDestination != null) + destinationRegionName = finalDestination.RegionName; + } + } + catch (Exception e) + { + m_log.ErrorFormat( + "[ENTITY TRANSFER MODULE]: Exception on teleport of {0} from {1}@{2} to {3}@{4}: {5}{6}", + sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName, + e.Message, e.StackTrace); - m_log.WarnFormat( - "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", - position, sp.Name, sp.UUID, emergencyPos); + sp.ControllingClient.SendTeleportFailed("Internal error"); + } + } - position = emergencyPos; - } + /// + /// Teleports the agent within its current region. + /// + /// + /// + /// + /// 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize) - { - posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y]; - } + m_log.WarnFormat( + "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", + position, sp.Name, sp.UUID, emergencyPos); - float newPosZ = posZLimit + localAVHeight; - if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) - { - position.Z = newPosZ; - } + position = emergencyPos; + } - sp.ControllingClient.SendTeleportStart(teleportFlags); + // TODO: Get proper AVG Height + float localAVHeight = 1.56f; + float posZLimit = 22; - sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags); - sp.Velocity = Vector3.Zero; - sp.Teleport(position); + // TODO: Check other Scene HeightField + if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize) + { + posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y]; + } - foreach (SceneObjectGroup grp in sp.GetAttachments()) - { - sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT); - } - } - else // Another region possibly in another simulator - { - uint x = 0, y = 0; - Utils.LongToUInts(regionHandle, out x, out y); - GridRegion reg = m_aScene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y); + float newPosZ = posZLimit + localAVHeight; + if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) + { + position.Z = newPosZ; + } - if (reg != null) - { - GridRegion finalDestination = GetFinalDestination(reg); - if (finalDestination == null) - { - m_log.WarnFormat( - "[ENTITY TRANSFER MODULE]: Final destination is having problems. Unable to teleport {0} {1}", - sp.Name, sp.UUID); + sp.ControllingClient.SendTeleportStart(teleportFlags); - sp.ControllingClient.SendTeleportFailed("Problem at destination"); - return; - } + sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags); + sp.Velocity = Vector3.Zero; + sp.Teleport(position); - destinationRegionName = finalDestination.RegionName; + foreach (SceneObjectGroup grp in sp.GetAttachments()) + { + sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT); + } + } - uint curX = 0, curY = 0; - Utils.LongToUInts(sp.Scene.RegionInfo.RegionHandle, out curX, out curY); - int curCellX = (int)(curX / Constants.RegionSize); - int curCellY = (int)(curY / Constants.RegionSize); - int destCellX = (int)(finalDestination.RegionLocX / Constants.RegionSize); - int destCellY = (int)(finalDestination.RegionLocY / Constants.RegionSize); + /// + /// Teleports the agent to a different region. + /// + /// + /// /param> + /// + /// + /// + /// + private void TeleportAgentToDifferentRegion( + ScenePresence sp, ulong regionHandle, Vector3 position, + Vector3 lookAt, uint teleportFlags, out GridRegion finalDestination) + { + uint x = 0, y = 0; + Utils.LongToUInts(regionHandle, out x, out y); + GridRegion reg = m_aScene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y); + + if (reg != null) + { + finalDestination = GetFinalDestination(reg); + + if (finalDestination == null) + { + m_log.WarnFormat( + "[ENTITY TRANSFER MODULE]: Final destination is having problems. Unable to teleport {0} {1}", + sp.Name, sp.UUID); + + sp.ControllingClient.SendTeleportFailed("Problem at destination"); + return; + } + + uint curX = 0, curY = 0; + Utils.LongToUInts(sp.Scene.RegionInfo.RegionHandle, out curX, out curY); + int curCellX = (int)(curX / Constants.RegionSize); + int curCellY = (int)(curY / Constants.RegionSize); + int destCellX = (int)(finalDestination.RegionLocX / Constants.RegionSize); + int destCellY = (int)(finalDestination.RegionLocY / Constants.RegionSize); // m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY); // // m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}", // destRegionX, destRegionY, finalDestination.RegionID, finalDestination.ServerURI); - // Check that these are not the same coordinates - if (finalDestination.RegionLocX == sp.Scene.RegionInfo.RegionLocX && - finalDestination.RegionLocY == sp.Scene.RegionInfo.RegionLocY) - { - // Can't do. Viewer crashes - sp.ControllingClient.SendTeleportFailed("Space warp! You would crash. Move to a different region and try again."); - return; - } - - if (Math.Abs(curCellX - destCellX) > MaxTransferDistance || Math.Abs(curCellY - destCellY) > MaxTransferDistance) - { - sp.ControllingClient.SendTeleportFailed( - string.Format( - "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way", - finalDestination.RegionName, destCellX, destCellY, - sp.Scene.RegionInfo.RegionName, curCellX, curCellY, - MaxTransferDistance)); - - return; - } - - // - // This is it - // - DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags, eq); - // - // - // - } - else - { - // TP to a place that doesn't exist (anymore) - // Inform the viewer about that - sp.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore"); - - // and set the map-tile to '(Offline)' - uint regX, regY; - Utils.LongToUInts(regionHandle, out regX, out regY); - - MapBlockData block = new MapBlockData(); - block.X = (ushort)(regX / Constants.RegionSize); - block.Y = (ushort)(regY / Constants.RegionSize); - block.Access = 254; // == not there - - List blocks = new List(); - blocks.Add(block); - sp.ControllingClient.SendMapBlock(blocks, 0); - } + // Check that these are not the same coordinates + if (finalDestination.RegionLocX == sp.Scene.RegionInfo.RegionLocX && + finalDestination.RegionLocY == sp.Scene.RegionInfo.RegionLocY) + { + // Can't do. Viewer crashes + sp.ControllingClient.SendTeleportFailed("Space warp! You would crash. Move to a different region and try again."); + return; + } + + if (Math.Abs(curCellX - destCellX) > MaxTransferDistance || Math.Abs(curCellY - destCellY) > MaxTransferDistance) + { + sp.ControllingClient.SendTeleportFailed( + string.Format( + "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way", + finalDestination.RegionName, destCellX, destCellY, + sp.Scene.RegionInfo.RegionName, curCellX, curCellY, + MaxTransferDistance)); + + return; } + + // + // This is it + // + DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags); + // + // + // } - catch (Exception e) + else { - m_log.ErrorFormat( - "[ENTITY TRANSFER MODULE]: Exception on teleport of {0} from {1}@{2} to {3}@{4}: {5}{6}", - sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName, - e.Message, e.StackTrace); - - sp.ControllingClient.SendTeleportFailed("Internal error"); + finalDestination = null; + + // TP to a place that doesn't exist (anymore) + // Inform the viewer about that + sp.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore"); + + // and set the map-tile to '(Offline)' + uint regX, regY; + Utils.LongToUInts(regionHandle, out regX, out regY); + + MapBlockData block = new MapBlockData(); + block.X = (ushort)(regX / Constants.RegionSize); + block.Y = (ushort)(regY / Constants.RegionSize); + block.Access = 254; // == not there + + List blocks = new List(); + blocks.Add(block); + sp.ControllingClient.SendMapBlock(blocks, 0); } } - public void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq) + public void DoTeleport( + ScenePresence sp, GridRegion reg, GridRegion finalDestination, + Vector3 position, Vector3 lookAt, uint teleportFlags) { + IEventQueue eq = sp.Scene.RequestModuleInterface(); + if (reg == null || finalDestination == null) { sp.ControllingClient.SendTeleportFailed("Unable to locate destination"); diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 488bbcb..b578bcb 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -242,13 +242,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } - IEventQueue eq = sp.Scene.RequestModuleInterface(); GridRegion homeGatekeeper = MakeRegion(aCircuit); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: teleporting user {0} {1} home to {2} via {3}:{4}", aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ServerURI, homeGatekeeper.RegionName); - DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome), eq); + DoTeleport( + sp, homeGatekeeper, finalDestination, + position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome)); } /// @@ -288,17 +289,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { ScenePresence sp = scene.GetScenePresence(remoteClient.AgentId); IEntityTransferModule transferMod = scene.RequestModuleInterface(); - IEventQueue eq = sp.Scene.RequestModuleInterface(); - if (transferMod != null && sp != null && eq != null) - transferMod.DoTeleport(sp, gatekeeper, finalDestination, lm.Position, - Vector3.UnitX, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark), eq); + + if (transferMod != null && sp != null) + transferMod.DoTeleport( + sp, gatekeeper, finalDestination, lm.Position, Vector3.UnitX, + (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark)); } } // can't find the region: Tell viewer and abort remoteClient.SendTeleportFailed("The teleport destination could not be found."); - } #endregion diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs index 07e97d5..18e9e3c 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs @@ -37,12 +37,41 @@ namespace OpenSim.Region.Framework.Interfaces { public interface IEntityTransferModule { - void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, - Vector3 lookAt, uint teleportFlags); + /// + /// Teleport an agent within the same or to a different region. + /// + /// + /// + /// The handle of the destination region. If it's the same as the region currently + /// occupied by the agent then the teleport will be within that region. + /// + /// + /// + /// + void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); - void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, - Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq); + /// + /// Teleport an agent directly to a given region without checking whether the region should be subsituted. + /// + /// + /// Please use Teleport() instead unless you know exactly what you're doing. + /// Do not use for same region teleports. + /// + /// + /// + /// /param> + /// + /// + /// + void DoTeleport( + ScenePresence sp, GridRegion reg, GridRegion finalDestination, + Vector3 position, Vector3 lookAt, uint teleportFlags); + /// + /// Teleports the agent for the given client to their home destination. + /// + /// + /// void TeleportHome(UUID id, IClientAPI client); bool Cross(ScenePresence agent, bool isFlying); -- cgit v1.1 From 5786521103eb6721e86e4abfce742019b960491e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 1 May 2012 18:38:46 +0100 Subject: Move max teleport distance check down into etm.DoTeleport() since this should apply to all teleport calls, not just those through Teleport() --- .../EntityTransfer/EntityTransferModule.cs | 81 +++++++++++----------- 1 file changed, 41 insertions(+), 40 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index b547317..230706e 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -51,15 +51,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + public const int DefaultMaxTransferDistance = 4095; + /// /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer. /// - private int m_MaxTransferDistance = 4095; - public int MaxTransferDistance - { - get { return m_MaxTransferDistance; } - set { m_MaxTransferDistance = value; } - } + public int MaxTransferDistance { get; set; } protected bool m_Enabled = false; protected Scene m_aScene; @@ -102,9 +99,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { IConfig transferConfig = source.Configs["EntityTransfer"]; if (transferConfig != null) - { - MaxTransferDistance = transferConfig.GetInt("max_distance", 4095); - } + MaxTransferDistance = transferConfig.GetInt("max_distance", DefaultMaxTransferDistance); + else + MaxTransferDistance = DefaultMaxTransferDistance; m_agentsInTransit = new List(); m_Enabled = true; @@ -288,18 +285,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } - uint curX = 0, curY = 0; - Utils.LongToUInts(sp.Scene.RegionInfo.RegionHandle, out curX, out curY); - int curCellX = (int)(curX / Constants.RegionSize); - int curCellY = (int)(curY / Constants.RegionSize); - int destCellX = (int)(finalDestination.RegionLocX / Constants.RegionSize); - int destCellY = (int)(finalDestination.RegionLocY / Constants.RegionSize); - -// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY); -// -// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}", -// destRegionX, destRegionY, finalDestination.RegionID, finalDestination.ServerURI); - // Check that these are not the same coordinates if (finalDestination.RegionLocX == sp.Scene.RegionInfo.RegionLocX && finalDestination.RegionLocY == sp.Scene.RegionInfo.RegionLocY) @@ -309,18 +294,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } - if (Math.Abs(curCellX - destCellX) > MaxTransferDistance || Math.Abs(curCellY - destCellY) > MaxTransferDistance) - { - sp.ControllingClient.SendTeleportFailed( - string.Format( - "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way", - finalDestination.RegionName, destCellX, destCellY, - sp.Scene.RegionInfo.RegionName, curCellX, curCellY, - MaxTransferDistance)); - - return; - } - // // This is it // @@ -332,7 +305,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer else { finalDestination = null; - + // TP to a place that doesn't exist (anymore) // Inform the viewer about that sp.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore"); @@ -352,10 +325,44 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } + /// + /// Determines whether this instance is within the max transfer distance. + /// + /// + /// + /// + /// true if this instance is within max transfer distance; otherwise, false. + /// + private bool IsWithinMaxTeleportDistance(RegionInfo sourceRegion, GridRegion destRegion) + { +// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY); +// +// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}", +// destRegionX, destRegionY, finalDestination.RegionID, finalDestination.ServerURI); + + // Insanely, RegionLoc on RegionInfo is the 256m map co-ord whilst GridRegion.RegionLoc is the raw meters position. + return Math.Abs(sourceRegion.RegionLocX - destRegion.RegionCoordX) <= MaxTransferDistance + && Math.Abs(sourceRegion.RegionLocY - destRegion.RegionCoordY) <= MaxTransferDistance; + } + public void DoTeleport( ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags) { + RegionInfo sourceRegion = sp.Scene.RegionInfo; + + if (!IsWithinMaxTeleportDistance(sourceRegion, finalDestination)) + { + sp.ControllingClient.SendTeleportFailed( + string.Format( + "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way", + finalDestination.RegionName, finalDestination.RegionCoordX, finalDestination.RegionCoordY, + sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY, + MaxTransferDistance)); + + return; + } + IEventQueue eq = sp.Scene.RequestModuleInterface(); if (reg == null || finalDestination == null) @@ -665,7 +672,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected virtual bool IsOutsideRegion(Scene s, Vector3 pos) { - if (s.TestBorderCross(pos, Cardinals.N)) return true; if (s.TestBorderCross(pos, Cardinals.S)) @@ -806,7 +812,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer neighboury = ba.TriggerRegionY; neighbourx = ba.TriggerRegionX; - Vector3 newposition = pos; newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize; newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize; @@ -814,7 +819,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false); InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene); - return true; } @@ -854,8 +858,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer neighboury += (uint)(int)(c.BorderLine.Z / (int)Constants.RegionSize); newpos.Y = enterDistance; } - - } else if (scene.TestBorderCross(pos + southCross, Cardinals.S)) { @@ -882,7 +884,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } else if (scene.TestBorderCross(pos + northCross, Cardinals.N)) { - Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N); neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize); newpos.Y = enterDistance; -- cgit v1.1 From 9d2e1c67a8969e4769006c7347505b58a7827b3f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 1 May 2012 23:14:12 +0100 Subject: Add regression test for teleporting between neighbouring regions on the same simulator This adds a non-advertised wait_for_callback option in [EntityTransfer]. Default is always true. Teleport tests disable the wait for callback from the destination region in order to run within a single thread. --- .../Linden/UDP/Tests/LLImageManagerTests.cs | 3 +- .../Region/ClientStack/RegionApplicationBase.cs | 2 +- .../EntityTransfer/EntityTransferModule.cs | 30 +++++- .../Tests/InventoryAccessModuleTests.cs | 7 +- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 +- .../Scenes/Tests/ScenePresenceAgentTests.cs | 3 +- .../Scenes/Tests/ScenePresenceTeleportTests.cs | 112 +++++++++++++++++++-- 7 files changed, 142 insertions(+), 19 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs index 221f02b..5fcf376 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs @@ -79,7 +79,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests J2KDecoderModule j2kdm = new J2KDecoderModule(); - scene = new SceneHelpers().SetupScene(); + SceneHelpers sceneHelpers = new SceneHelpers(); + scene = sceneHelpers.SetupScene(); SceneHelpers.SetupSceneModules(scene, j2kdm); tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene); diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs index 6e3a58e..6e78d6d 100644 --- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs +++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs @@ -111,7 +111,7 @@ namespace OpenSim.Region.ClientStack server.Start(); } } - + base.StartupSpecific(); } diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 230706e..35486bb 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -52,12 +52,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public const int DefaultMaxTransferDistance = 4095; + public const bool EnableWaitForCallbackFromTeleportDestDefault = true; + /// /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer. /// public int MaxTransferDistance { get; set; } + /// + /// If true then on a teleport, the source region waits for a callback from the destination region. If + /// a callback fails to arrive within a set time then the user is pulled back into the source region. + /// + public bool EnableWaitForCallbackFromTeleportDest { get; set; } + protected bool m_Enabled = false; protected Scene m_aScene; protected List m_Scenes = new List(); @@ -99,9 +107,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { IConfig transferConfig = source.Configs["EntityTransfer"]; if (transferConfig != null) + { + EnableWaitForCallbackFromTeleportDest + = transferConfig.GetBoolean("wait_for_callback", EnableWaitForCallbackFromTeleportDestDefault); + MaxTransferDistance = transferConfig.GetInt("max_distance", DefaultMaxTransferDistance); + } else + { MaxTransferDistance = DefaultMaxTransferDistance; + } m_agentsInTransit = new List(); m_Enabled = true; @@ -499,6 +514,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } else { + ICapabilitiesModule capModule = sp.Scene.CapsModule; + ulong regionHandle = reg.RegionHandle; + capModule.GetChildSeed(UUID.Zero, regionHandle); agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle); capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); } @@ -527,7 +545,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.ControllingClient.SendTeleportProgress(teleportFlags | (uint)TeleportFlags.DisableCancel, "sending_dest"); m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, sp.UUID); + "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", + capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); if (eq != null) { @@ -546,7 +565,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation // that the client contacted the destination before we close things here. - if (!WaitForCallback(sp.UUID)) + if (EnableWaitForCallbackFromTeleportDest && !WaitForCallback(sp.UUID)) { m_log.WarnFormat( "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} failed due to no callback from destination region. Returning avatar to source region.", @@ -1286,7 +1305,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) { - AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); AgentCircuitData agent = sp.ControllingClient.RequestClientInfo(); agent.BaseFolder = UUID.Zero; @@ -1311,7 +1329,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer seeds.Add(neighbour.RegionHandle, agent.CapsPath); } else + { agent.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, neighbour.RegionHandle); + } cagents.Add(agent); } @@ -1926,7 +1946,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer int count = 200; while (m_agentsInTransit.Contains(id) && count-- > 0) { - //m_log.Debug(" >>> Waiting... " + count); +// m_log.Debug(" >>> Waiting... " + count); Thread.Sleep(100); } @@ -1934,6 +1954,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return true; else return false; + + return true; } protected void SetInTransit(UUID id) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index d6afaa9..21d8bd7 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -64,8 +64,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests IConfigSource config = new IniConfigSource(); config.AddConfig("Modules"); config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); - - m_scene = new SceneHelpers().SetupScene(); + + SceneHelpers sceneHelpers = new SceneHelpers(); + m_scene = sceneHelpers.SetupScene(); SceneHelpers.SetupSceneModules(m_scene, config, m_iam); // Create user @@ -76,7 +77,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests AgentCircuitData acd = new AgentCircuitData(); acd.AgentID = m_userId; - m_tc = new TestClient(acd, m_scene); + m_tc = new TestClient(acd, m_scene); } [Test] diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index f1d0926..e5a9a99 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2895,8 +2895,8 @@ namespace OpenSim.Region.Framework.Scenes x = x / Constants.RegionSize; y = y / Constants.RegionSize; - //m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); - //m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); +// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); +// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); if (Util.IsOutsideView(DrawDistance, x, newRegionX, y, newRegionY)) { byebyeRegions.Add(handle); diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index 2e46377..1aa48d7 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs @@ -128,7 +128,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests IConfig config = configSource.AddConfig("Modules"); config.Set("SimulationServices", "LocalSimulationConnectorModule"); - TestScene scene = new SceneHelpers().SetupScene(); + SceneHelpers sceneHelpers = new SceneHelpers(); + TestScene scene = sceneHelpers.SetupScene(); SceneHelpers.SetupSceneModules(scene, configSource, lsc); UUID agentId = TestHelpers.ParseTail(0x01); diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs index c750cc5..ea4fb66 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs @@ -33,8 +33,9 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; using OpenSim.Framework.Servers; -using OpenSim.Region.CoreModules.Framework.EntityTransfer; using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.CoreModules.Framework; +using OpenSim.Region.CoreModules.Framework.EntityTransfer; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; @@ -49,6 +50,22 @@ namespace OpenSim.Region.Framework.Scenes.Tests [TestFixture] public class ScenePresenceTeleportTests { + [TestFixtureSetUp] + public void FixtureInit() + { + // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. + Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; + } + + [TestFixtureTearDown] + public void TearDown() + { + // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple + // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression + // tests really shouldn't). + Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; + } + [Test] public void TestSameRegionTeleport() { @@ -96,10 +113,14 @@ namespace OpenSim.Region.Framework.Scenes.Tests LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - // Not strictly necessary since FriendsModule assumes it is the default (!) - config.Configs["Modules"].Set("EntityTransferModule", etm.Name); - config.Configs["Modules"].Set("SimulationServices", lscm.Name); + IConfig modulesConfig = config.AddConfig("Modules"); + modulesConfig.Set("EntityTransferModule", etm.Name); + modulesConfig.Set("SimulationServices", lscm.Name); + IConfig entityTransferConfig = config.AddConfig("EntityTransfer"); + + // In order to run a single threaded regression test we do not want the entity transfer module waiting + // for a callback from the destination scene before removing its avatar data. + entityTransferConfig.Set("wait_for_callback", false); SceneHelpers sh = new SceneHelpers(); TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); @@ -110,12 +131,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests Vector3 teleportPosition = new Vector3(10, 11, 12); Vector3 teleportLookAt = new Vector3(20, 21, 22); - ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId); + ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); sp.AbsolutePosition = new Vector3(30, 31, 32); // XXX: A very nasty hack to tell the client about the destination scene without having to crank the whole // UDP stack (?) - ((TestClient)sp.ControllingClient).TeleportTargetScene = sceneB; +// ((TestClient)sp.ControllingClient).TeleportTargetScene = sceneB; sceneA.RequestTeleportLocation( sp.ControllingClient, @@ -124,6 +145,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests teleportLookAt, (uint)TeleportFlags.ViaLocation); + ((TestClient)sp.ControllingClient).CompleteTeleportClientSide(); + Assert.That(sceneA.GetScenePresence(userId), Is.Null); ScenePresence sceneBSp = sceneB.GetScenePresence(userId); @@ -137,5 +160,80 @@ namespace OpenSim.Region.Framework.Scenes.Tests // position instead). // Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); } + + [Test] + public void TestSameSimulatorNeighbouringRegionsTeleport() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + UUID userId = TestHelpers.ParseTail(0x1); + + EntityTransferModule etm = new EntityTransferModule(); + LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); + + IConfigSource config = new IniConfigSource(); + IConfig modulesConfig = config.AddConfig("Modules"); + modulesConfig.Set("EntityTransferModule", etm.Name); + modulesConfig.Set("SimulationServices", lscm.Name); + IConfig entityTransferConfig = config.AddConfig("EntityTransfer"); + + // In order to run a single threaded regression test we do not want the entity transfer module waiting + // for a callback from the destination scene before removing its avatar data. + entityTransferConfig.Set("wait_for_callback", false); + + SceneHelpers sh = new SceneHelpers(); + TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); + TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000); + + SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, etm, lscm); + SceneHelpers.SetupSceneModules(sceneA, new CapabilitiesModule()); + SceneHelpers.SetupSceneModules(sceneB, new CapabilitiesModule()); + + Vector3 teleportPosition = new Vector3(10, 11, 12); + Vector3 teleportLookAt = new Vector3(20, 21, 22); + + ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); + originalSp.AbsolutePosition = new Vector3(30, 31, 32); + + ScenePresence beforeSceneASp = sceneA.GetScenePresence(userId); + Assert.That(beforeSceneASp, Is.Not.Null); + Assert.That(beforeSceneASp.IsChildAgent, Is.False); + + ScenePresence beforeSceneBSp = sceneB.GetScenePresence(userId); + Assert.That(beforeSceneBSp, Is.Not.Null); + Assert.That(beforeSceneBSp.IsChildAgent, Is.True); + + // XXX: A very nasty hack to tell the client about the destination scene without having to crank the whole + // UDP stack (?) +// ((TestClient)beforeSceneASp.ControllingClient).TeleportTargetScene = sceneB; + + sceneA.RequestTeleportLocation( + beforeSceneASp.ControllingClient, + sceneB.RegionInfo.RegionHandle, + teleportPosition, + teleportLookAt, + (uint)TeleportFlags.ViaLocation); + + ((TestClient)beforeSceneASp.ControllingClient).CompleteTeleportClientSide(); + + ScenePresence afterSceneASp = sceneA.GetScenePresence(userId); + Assert.That(afterSceneASp, Is.Not.Null); + Assert.That(afterSceneASp.IsChildAgent, Is.True); + + ScenePresence afterSceneBSp = sceneB.GetScenePresence(userId); + Assert.That(afterSceneBSp, Is.Not.Null); + Assert.That(afterSceneBSp.IsChildAgent, Is.False); + Assert.That(afterSceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName)); + Assert.That(afterSceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition)); + + // TODO: Add assertions to check correct circuit details in both scenes. + + // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera + // position instead). +// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); + +// TestHelpers.DisableLogging(); + } } } \ No newline at end of file -- cgit v1.1 From a29f7f7551c0b6d783d9c6df9f6a6487901dfd82 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 1 May 2012 23:25:30 +0100 Subject: Remove some test code that accidentally crept in with 9d2e1c67 --- .../CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 3 --- 1 file changed, 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 35486bb..75d1586 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -514,9 +514,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } else { - ICapabilitiesModule capModule = sp.Scene.CapsModule; - ulong regionHandle = reg.RegionHandle; - capModule.GetChildSeed(UUID.Zero, regionHandle); agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle); capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); } -- cgit v1.1 From 40f3c24562e620e8f09b3569c0b643eb5eae013f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 1 May 2012 23:49:02 +0100 Subject: Comment out the five second sleep in etm.DoTeleport() if the old agent needs to be closed because it is no longer in the child's view distance. This sleep appears unnecessary since a sleep has already occurred in WaitForCallback() whilst waiting for the destination region to notify of teleport success. There are no async operations between this sleep and the WaitForCallback() If this sleep is present, then teleporting back to the source region within 5 seconds results in a disconnection. If this sleep is commented out then teleporting quickly back and forth between two simulators appears to work without issue. Tested on standalone, local grid and distributed grid. Please revert if there's something that I've missed. --- .../Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 75d1586..8d5e0a5 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -595,7 +595,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) { - Thread.Sleep(5000); +// Thread.Sleep(5000); sp.Close(); sp.Scene.IncomingCloseAgent(sp.UUID); } -- cgit v1.1