Merge branch 'master' into careminster

Conflicts:
	OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
	OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
	OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
avinationmerge
Melanie 2012-05-02 01:37:51 +01:00
commit bf630fb808
13 changed files with 444 additions and 180 deletions

View File

@ -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);

View File

@ -240,9 +240,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
{
ScenePresence sp = scene.GetScenePresence(client.AgentId);
IEntityTransferModule transferMod = scene.RequestModuleInterface<IEntityTransferModule>();
IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
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);
}
}
}

View File

@ -51,15 +51,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;
/// <summary>
/// The maximum distance, in standard region units (256m) that an agent is allowed to transfer.
/// </summary>
private int m_MaxTransferDistance = 4095;
public int MaxTransferDistance
{
get { return m_MaxTransferDistance; }
set { m_MaxTransferDistance = value; }
}
public int MaxTransferDistance { get; set; }
/// <summary>
/// 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.
/// </summary>
public bool EnableWaitForCallbackFromTeleportDest { get; set; }
protected bool m_Enabled = false;
protected Scene m_aScene;
@ -103,7 +108,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
IConfig transferConfig = source.Configs["EntityTransfer"];
if (transferConfig != null)
{
MaxTransferDistance = transferConfig.GetInt("max_distance", 4095);
EnableWaitForCallbackFromTeleportDest
= transferConfig.GetBoolean("wait_for_callback", EnableWaitForCallbackFromTeleportDestDefault);
MaxTransferDistance = transferConfig.GetInt("max_distance", DefaultMaxTransferDistance);
}
else
{
MaxTransferDistance = DefaultMaxTransferDistance;
}
m_agentsInTransit = new List<UUID>();
@ -170,8 +182,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (!sp.Scene.Permissions.CanTeleport(sp.UUID))
return;
IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
// Reset animations; the viewer does that in teleports.
sp.Animator.ResetAnimations();
@ -183,9 +193,41 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{
destinationRegionName = sp.Scene.RegionInfo.RegionName;
TeleportAgentWithinRegion(sp, position, lookAt, teleportFlags);
}
else // Another region possibly in another simulator
{
GridRegion finalDestination;
TeleportAgentToDifferentRegion(
sp, regionHandle, position, lookAt, teleportFlags, out finalDestination);
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);
sp.ControllingClient.SendTeleportFailed("Internal error");
}
}
/// <summary>
/// Teleports the agent within its current region.
/// </summary>
/// <param name="sp"></param>
/// <param name="position"></param>
/// <param name="lookAt"></param>
/// <param name="teleportFlags"></param
private void TeleportAgentWithinRegion(ScenePresence sp, Vector3 position, Vector3 lookAt, uint teleportFlags)
{
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}",
sp.Name, position, destinationRegionName);
sp.Name, position, sp.Scene.RegionInfo.RegionName);
// Teleport within the same region
if (IsOutsideRegion(sp.Scene, position) || position.Z < 0)
@ -227,7 +269,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT);
}
}
else // Another region possibly in another simulator
/// <summary>
/// Teleports the agent to a different region.
/// </summary>
/// <param name='sp'></param>
/// <param name='regionHandle'>/param>
/// <param name='position'></param>
/// <param name='lookAt'></param>
/// <param name='teleportFlags'></param>
/// <param name='finalDestination'></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);
@ -235,7 +289,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (reg != null)
{
GridRegion finalDestination = GetFinalDestination(reg);
finalDestination = GetFinalDestination(reg);
if (finalDestination == null)
{
m_log.WarnFormat(
@ -246,20 +301,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return;
}
destinationRegionName = finalDestination.RegionName;
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)
@ -269,28 +310,18 @@ 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
//
DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags, eq);
DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags);
//
//
//
}
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");
@ -309,20 +340,47 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
sp.ControllingClient.SendMapBlock(blocks, 0);
}
}
}
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);
sp.ControllingClient.SendTeleportFailed("Internal error");
}
/// <summary>
/// Determines whether this instance is within the max transfer distance.
/// </summary>
/// <param name="sourceRegion"></param>
/// <param name="destRegion"></param>
/// <returns>
/// <c>true</c> if this instance is within max transfer distance; otherwise, <c>false</c>.
/// </returns>
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, IEventQueue eq)
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<IEventQueue>();
if (reg == null || finalDestination == null)
{
sp.ControllingClient.SendTeleportFailed("Unable to locate destination");
@ -485,7 +543,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)
{
@ -504,7 +563,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.",
@ -537,7 +596,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);
}
@ -630,7 +689,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))
@ -752,7 +810,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
neighbourx--;
newpos.X = Constants.RegionSize - enterDistance;
}
else if (scene.TestBorderCross(pos + eastCross, Cardinals.E))
{
@ -1202,7 +1259,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;
@ -1227,7 +1283,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);
}
@ -1851,7 +1909,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);
}
@ -1859,6 +1917,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return true;
else
return false;
return true;
}
protected void SetInTransit(UUID id)

View File

@ -246,13 +246,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return false;
}
IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
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));
return true;
}
@ -293,17 +292,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{
ScenePresence sp = scene.GetScenePresence(remoteClient.AgentId);
IEntityTransferModule transferMod = scene.RequestModuleInterface<IEntityTransferModule>();
IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
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

View File

@ -65,7 +65,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
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

View File

@ -39,13 +39,23 @@ namespace OpenSim.Region.Framework.Interfaces
public interface IEntityTransferModule
{
void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position,
Vector3 lookAt, uint teleportFlags);
/// <summary>
/// Teleport an agent within the same or to a different region.
/// </summary>
/// <param name='agent'></param>
/// <param name='regionHandle'>
/// 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.
/// </param>
/// <param name='position'></param>
/// <param name='lookAt'></param>
/// <param name='teleportFlags'></param>
void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags);
bool TeleportHome(UUID id, IClientAPI client);
void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq);
Vector3 position, Vector3 lookAt, uint teleportFlags);
bool Cross(ScenePresence agent, bool isFlying);

View File

@ -3049,8 +3049,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);

View File

@ -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);

View File

@ -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();
}
}
}

View File

@ -58,6 +58,11 @@ namespace OpenSim.Tests.Common
/// </summary>
public class SceneHelpers
{
/// <summary>
/// We need a scene manager so that test clients can retrieve a scene when performing teleport tests.
/// </summary>
public SceneManager SceneManager { get; private set; }
private AgentCircuitManager m_acm = new AgentCircuitManager();
private ISimulationDataService m_simDataService
= OpenSim.Server.Base.ServerUtils.LoadPlugin<ISimulationDataService>("OpenSim.Tests.Common.dll", null);
@ -76,6 +81,8 @@ namespace OpenSim.Tests.Common
public SceneHelpers(CoreAssetCache cache)
{
SceneManager = new SceneManager();
m_assetService = StartAssetService(cache);
m_authenticationService = StartAuthenticationService();
m_inventoryService = StartInventoryService();
@ -186,6 +193,8 @@ namespace OpenSim.Tests.Common
testScene.LoginsDisabled = false;
testScene.RegisterRegionWithGrid();
SceneManager.Add(testScene);
return testScene;
}
@ -350,6 +359,7 @@ namespace OpenSim.Tests.Common
List<IRegionModuleBase> newModules = new List<IRegionModuleBase>();
foreach (object module in modules)
{
// Console.WriteLine("MODULE RAW {0}", module);
if (module is IRegionModule)
{
IRegionModule m = (IRegionModule)module;
@ -367,6 +377,7 @@ namespace OpenSim.Tests.Common
// for the new system, everything has to be initialised first,
// shared modules have to be post-initialised, then all get an AddRegion with the scene
IRegionModuleBase m = (IRegionModuleBase)module;
// Console.WriteLine("MODULE {0}", m.Name);
m.Initialise(config);
newModules.Add(m);
}
@ -426,6 +437,10 @@ namespace OpenSim.Tests.Common
/// <summary>
/// Add a root agent where the details of the agent connection (apart from the id) are unimportant for the test
/// </summary>
/// <remarks>
/// This can be used for tests where there is only one region or where there are multiple non-neighbour regions
/// and teleport doesn't take place.
/// </remarks>
/// <param name="scene"></param>
/// <param name="agentId"></param>
/// <returns></returns>
@ -434,6 +449,18 @@ namespace OpenSim.Tests.Common
return AddScenePresence(scene, GenerateAgentData(agentId));
}
/// <summary>
/// Add a root agent where the details of the agent connection (apart from the id) are unimportant for the test
/// </summary>
/// <param name="scene"></param>
/// <param name="agentId"></param>
/// <param name="sceneManager"></param>
/// <returns></returns>
public static ScenePresence AddScenePresence(Scene scene, UUID agentId, SceneManager sceneManager)
{
return AddScenePresence(scene, GenerateAgentData(agentId), sceneManager);
}
/// <summary>
/// Add a root agent.
/// </summary>
@ -453,6 +480,30 @@ namespace OpenSim.Tests.Common
/// <param name="agentData"></param>
/// <returns></returns>
public static ScenePresence AddScenePresence(Scene scene, AgentCircuitData agentData)
{
return AddScenePresence(scene, agentData, null);
}
/// <summary>
/// Add a root agent.
/// </summary>
/// <remarks>
/// This function
///
/// 1) Tells the scene that an agent is coming. Normally, the login service (local if standalone, from the
/// userserver if grid) would give initial login data back to the client and separately tell the scene that the
/// agent was coming.
///
/// 2) Connects the agent with the scene
///
/// This function performs actions equivalent with notifying the scene that an agent is
/// coming and then actually connecting the agent to the scene. The one step missed out is the very first
/// </remarks>
/// <param name="scene"></param>
/// <param name="agentData"></param>
/// <param name="sceneManager"></param>
/// <returns></returns>
public static ScenePresence AddScenePresence(Scene scene, AgentCircuitData agentData, SceneManager sceneManager)
{
// We emulate the proper login sequence here by doing things in four stages
@ -463,7 +514,7 @@ namespace OpenSim.Tests.Common
lpsc.m_PresenceService.LoginAgent(agentData.AgentID.ToString(), agentData.SessionID, agentData.SecureSessionID);
// Stages 1 & 2
ScenePresence sp = IntroduceClientToScene(scene, agentData, TeleportFlags.ViaLogin);
ScenePresence sp = IntroduceClientToScene(scene, sceneManager, agentData, TeleportFlags.ViaLogin);
// Stage 3: Complete the entrance into the region. This converts the child agent into a root agent.
sp.CompleteMovement(sp.ControllingClient, true);
@ -471,7 +522,20 @@ namespace OpenSim.Tests.Common
return sp;
}
private static ScenePresence IntroduceClientToScene(Scene scene, AgentCircuitData agentData, TeleportFlags tf)
/// <summary>
/// Introduce an agent into the scene by adding a new client.
/// </summary>
/// <returns>The scene presence added</returns>
/// <param name='sceneManager'>
/// Scene manager. Can be null if there is only one region in the test or multiple regions that are not
/// neighbours and where no teleporting takes place.
/// </param>
/// <param name='scene'></param>
/// <param name='sceneManager></param>
/// <param name='agentData'></param>
/// <param name='tf'></param>
private static ScenePresence IntroduceClientToScene(
Scene scene, SceneManager sceneManager, AgentCircuitData agentData, TeleportFlags tf)
{
string reason;
@ -480,7 +544,7 @@ namespace OpenSim.Tests.Common
Console.WriteLine("NewUserConnection failed: " + reason);
// Stage 2: add the new client as a child agent to the scene
TestClient client = new TestClient(agentData, scene);
TestClient client = new TestClient(agentData, scene, sceneManager);
scene.AddNewClient(client, PresenceType.User);
return scene.GetScenePresence(agentData.AgentID);
@ -492,7 +556,7 @@ namespace OpenSim.Tests.Common
acd.child = true;
// XXX: ViaLogin may not be correct for child agents
return IntroduceClientToScene(scene, acd, TeleportFlags.ViaLogin);
return IntroduceClientToScene(scene, null, acd, TeleportFlags.ViaLogin);
}
/// <summary>

View File

@ -46,12 +46,10 @@ namespace OpenSim.Tests.Common.Mock
EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing");
// TODO: This is a really nasty (and temporary) means of telling the test client which scene to invoke setup
// methods on when a teleport is requested
public Scene TeleportTargetScene;
private TestClient TeleportSceneClient;
private Scene m_scene;
private SceneManager m_sceneManager;
// Properties so that we can get at received data for test purposes
public List<UUID> ReceivedOfflineNotifications { get; private set; }
@ -434,15 +432,29 @@ namespace OpenSim.Tests.Common.Mock
/// <summary>
/// Constructor
/// </summary>
/// <remarks>
/// Can be used for a test where there is only one region or where there are multiple regions that are not
/// neighbours and where no teleporting takes place. In other situations, the constructor that takes in a
/// scene manager should be used.
/// </remarks>
/// <param name="agentData"></param>
/// <param name="scene"></param>
public TestClient(AgentCircuitData agentData, Scene scene)
public TestClient(AgentCircuitData agentData, Scene scene) : this(agentData, scene, null) {}
/// <summary>
/// Constructor
/// </summary>
/// <param name="agentData"></param>
/// <param name="scene"></param>
/// <param name="sceneManager"></param>
public TestClient(AgentCircuitData agentData, Scene scene, SceneManager sceneManager)
{
m_agentId = agentData.AgentID;
m_firstName = agentData.firstname;
m_lastName = agentData.lastname;
m_circuitCode = agentData.circuitcode;
m_scene = scene;
m_sceneManager = sceneManager;
SessionId = agentData.SessionID;
SecureSessionId = agentData.SecureSessionID;
CapsSeedUrl = agentData.CapsPath;
@ -592,8 +604,16 @@ namespace OpenSim.Tests.Common.Mock
AgentCircuitData newAgent = RequestClientInfo();
// Stage 2: add the new client as a child agent to the scene
TeleportSceneClient = new TestClient(newAgent, TeleportTargetScene);
TeleportTargetScene.AddNewClient(TeleportSceneClient, PresenceType.User);
uint x, y;
Utils.LongToUInts(neighbourHandle, out x, out y);
x /= Constants.RegionSize;
y /= Constants.RegionSize;
Scene neighbourScene;
m_sceneManager.TryGetScene(x, y, out neighbourScene);
TeleportSceneClient = new TestClient(newAgent, neighbourScene, m_sceneManager);
neighbourScene.AddNewClient(TeleportSceneClient, PresenceType.User);
}
public virtual void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint,
@ -603,6 +623,13 @@ namespace OpenSim.Tests.Common.Mock
CapsSeedUrl = capsURL;
// We don't do this here so that the source region can complete processing first in a single-threaded
// regression test scenario. The test itself will have to call CompleteTeleportClientSide() after a teleport
// CompleteTeleportClientSide();
}
public void CompleteTeleportClientSide()
{
TeleportSceneClient.CompleteMovement();
//TeleportTargetScene.AgentCrossing(newAgent.AgentID, new Vector3(90, 90, 90), false);
}

View File

@ -46,7 +46,8 @@ namespace OpenSim.Tests.Common
<!-- A1 uses PatternLayout -->
<layout type=""log4net.Layout.PatternLayout"">
<!-- Print the date in ISO 8601 format -->
<conversionPattern value=""%date [%thread] %-5level %logger %ndc - %message%newline"" />
<!-- <conversionPattern value=""%date [%thread] %-5level %logger %ndc - %message%newline"" /> -->
<conversionPattern value=""%date %message%newline"" />
</layout>
</appender>
@ -62,9 +63,9 @@ namespace OpenSim.Tests.Common
Encoding.UTF8.GetBytes(
// "<?xml version=\"1.0\" encoding=\"utf-8\" ?><configuration><log4net><root><level value=\"OFF\"/><appender-ref ref=\"A1\"/></root></log4net></configuration>")));
//"<?xml version=\"1.0\" encoding=\"utf-8\" ?><configuration><log4net><root><level value=\"OFF\"/></root></log4net></configuration>")));
//"<configuration><log4net><root><level value=\"OFF\"/></root></log4net></configuration>")));
//"<configuration><log4net><root></root></log4net></configuration>")));
//"<configuration><log4net><root/></log4net></configuration>")));
// "<configuration><log4net><root><level value=\"OFF\"/></root></log4net></configuration>"));
// "<configuration><log4net><root></root></log4net></configuration>")));
// "<configuration><log4net><root/></log4net></configuration>"));
"<log4net><root/></log4net>"));
public static bool AssertThisDelegateCausesArgumentException(TestDelegate d)