diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs
index 7c5af4c319..e14878cf64 100644
--- a/OpenSim/Framework/ChildAgentDataUpdate.cs
+++ b/OpenSim/Framework/ChildAgentDataUpdate.cs
@@ -287,7 +287,7 @@ namespace OpenSim.Framework
public Vector3 AtAxis;
public Vector3 LeftAxis;
public Vector3 UpAxis;
- public bool ChangedGrid;
+ public bool SenderWantsToWaitForRoot;
public float Far;
public float Aspect;
@@ -356,8 +356,9 @@ namespace OpenSim.Framework
args["left_axis"] = OSD.FromString(LeftAxis.ToString());
args["up_axis"] = OSD.FromString(UpAxis.ToString());
-
- args["changed_grid"] = OSD.FromBoolean(ChangedGrid);
+ //backwards compatibility
+ args["changed_grid"] = OSD.FromBoolean(SenderWantsToWaitForRoot);
+ args["wait_for_root"] = OSD.FromBoolean(SenderWantsToWaitForRoot);
args["far"] = OSD.FromReal(Far);
args["aspect"] = OSD.FromReal(Aspect);
@@ -526,8 +527,8 @@ namespace OpenSim.Framework
if (args["up_axis"] != null)
Vector3.TryParse(args["up_axis"].AsString(), out AtAxis);
- if (args["changed_grid"] != null)
- ChangedGrid = args["changed_grid"].AsBoolean();
+ if (args.ContainsKey("wait_for_root") && args["wait_for_root"] != null)
+ SenderWantsToWaitForRoot = args["wait_for_root"].AsBoolean();
if (args["far"] != null)
Far = (float)(args["far"].AsReal());
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 32282af19a..b0ec88ce40 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -1196,6 +1196,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// UseCircuitCode handling
if (packet.Type == PacketType.UseCircuitCode)
{
+ m_log.DebugFormat("[ZZZ]: In the dungeon: UseCircuitCode");
// We need to copy the endpoint so that it doesn't get changed when another thread reuses the
// buffer.
object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
@@ -1204,6 +1205,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return;
}
+ else if (packet.Type == PacketType.CompleteAgentMovement)
+ {
+ // Send ack straight away to let the viewer know that we got it.
+ SendAckImmediate(endPoint, packet.Header.Sequence);
+
+ m_log.DebugFormat("[ZZZ]: In the dungeon: CompleteAgentMovement");
+ // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
+ // buffer.
+ object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
+
+ Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
+
+ return;
+ }
// Determine which agent this packet came from
IClientAPI client;
@@ -1542,6 +1557,56 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
+ private void HandleCompleteMovementIntoRegion(object o)
+ {
+ IPEndPoint endPoint = null;
+ IClientAPI client = null;
+
+ try
+ {
+ object[] array = (object[])o;
+ endPoint = (IPEndPoint)array[0];
+ CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1];
+
+ // Determine which agent this packet came from
+ int count = 10;
+ while (!m_scene.TryGetClient(endPoint, out client) && count-- > 0)
+ {
+ m_log.Debug("[LLUDPSERVER]: Received a CompleteMovementIntoRegion in " + m_scene.RegionInfo.RegionName + " (not ready yet)");
+ Thread.Sleep(200);
+ }
+
+ if (client == null)
+ return;
+
+ IncomingPacket incomingPacket1;
+
+ // Inbox insertion
+ if (UsePools)
+ {
+ incomingPacket1 = m_incomingPacketPool.GetObject();
+ incomingPacket1.Client = (LLClientView)client;
+ incomingPacket1.Packet = packet;
+ }
+ else
+ {
+ incomingPacket1 = new IncomingPacket((LLClientView)client, packet);
+ }
+
+ packetInbox.Enqueue(incomingPacket1);
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat(
+ "[LLUDPSERVER]: CompleteMovementIntoRegion handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
+ endPoint != null ? endPoint.ToString() : "n/a",
+ client != null ? client.Name : "unknown",
+ client != null ? client.AgentId.ToString() : "unknown",
+ e.Message,
+ e.StackTrace);
+ }
+ }
+
///
/// Send an ack immediately to the given endpoint.
///
@@ -1934,6 +1999,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Packet packet = incomingPacket.Packet;
LLClientView client = incomingPacket.Client;
+ if (packet is CompleteAgentMovementPacket)
+ m_log.DebugFormat("[ZZZ]: Received CompleteAgentMovementPacket");
+
if (client.IsActive)
{
m_currentIncomingClient = client;
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 5124aedae4..b0c0b1d370 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -684,7 +684,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
}
- //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Contacting destination...");
+ if (version.Equals("SIMULATION/0.2"))
+ TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
+ else
+ TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
+
+ }
+
+ private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
+ IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, string version, out string reason)
+ {
+ ulong destinationHandle = finalDestination.RegionHandle;
+ AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
// Let's create an agent there if one doesn't exist yet.
// NOTE: logout will always be false for a non-HG teleport.
@@ -707,7 +718,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
m_interRegionTeleportCancels.Value++;
m_log.DebugFormat(
- "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
+ "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
sp.Name, finalDestination.RegionName, sp.Scene.Name);
return;
@@ -725,14 +736,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// Past this point we have to attempt clean up if the teleport fails, so update transfer state.
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
-
- #region old protocol
-
- IClientIPEndpoint ipepClient;
+
+ IClientIPEndpoint ipepClient;
+ string capsPath = String.Empty;
if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
{
m_log.DebugFormat(
- "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
+ "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
//sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
@@ -745,30 +755,30 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
#endregion
capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
- //if (m_eqModule != null)
- //{
- // // The EnableSimulator message makes the client establish a connection with the destination
- // // simulator by sending the initial UseCircuitCode UDP packet to the destination containing the
- // // correct circuit code.
- // m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID);
+ if (m_eqModule != null)
+ {
+ // The EnableSimulator message makes the client establish a connection with the destination
+ // simulator by sending the initial UseCircuitCode UDP packet to the destination containing the
+ // correct circuit code.
+ m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID);
- // // XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination
- // // simulator to confirm that it has established communication with the viewer.
- // Thread.Sleep(200);
+ // XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination
+ // simulator to confirm that it has established communication with the viewer.
+ Thread.Sleep(200);
- // // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears
- // // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly
- // // only on TeleportFinish). This is untested for region teleport between different simulators
- // // though this probably also works.
- // m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
- //}
- //else
- //{
- // // XXX: This is a little misleading since we're information the client of its avatar destination,
- // // which may or may not be a neighbour region of the source region. This path is probably little
- // // used anyway (with EQ being the one used). But it is currently being used for test code.
- // sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
- //}
+ // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears
+ // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly
+ // only on TeleportFinish). This is untested for region teleport between different simulators
+ // though this probably also works.
+ m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
+ }
+ else
+ {
+ // XXX: This is a little misleading since we're information the client of its avatar destination,
+ // which may or may not be a neighbour region of the source region. This path is probably little
+ // used anyway (with EQ being the one used). But it is currently being used for test code.
+ sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
+ }
}
else
{
@@ -776,15 +786,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
}
- #endregion old protocol
-
// Let's send a full update of the agent. This is a synchronous call.
AgentData agent = new AgentData();
sp.CopyTo(agent);
- agent.Position = position;
- //SetCallbackURL(agent, sp.Scene.RegionInfo);
+ agent.Position = agentCircuit.startpos;
+ SetCallbackURL(agent, sp.Scene.RegionInfo);
- //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
// We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to
// establish th econnection to the destination which makes it return true.
@@ -814,7 +821,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
teleportFlags, capsPath);
}
-
+
// A common teleport failure occurs when we can send CreateAgent to the
// destination region but the viewer cannot establish the connection (e.g. due to network issues between
// the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then
@@ -835,7 +842,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
m_log.WarnFormat(
"[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.",
sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
-
+
Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
return;
}
@@ -845,7 +852,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
m_interRegionTeleportCancels.Value++;
m_log.DebugFormat(
- "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
+ "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
sp.Name, finalDestination.RegionName, sp.Scene.Name);
CleanupFailedInterRegionTeleport(sp, currentAgentCircuit.SessionID.ToString(), finalDestination);
@@ -857,30 +864,30 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
"[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
- //// 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 (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID))
- //{
- // if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
- // {
- // m_interRegionTeleportAborts.Value++;
+ // 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 (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID))
+ {
+ if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
+ {
+ m_interRegionTeleportAborts.Value++;
- // m_log.DebugFormat(
- // "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.",
- // sp.Name, finalDestination.RegionName, sp.Scene.Name);
+ m_log.DebugFormat(
+ "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.",
+ sp.Name, finalDestination.RegionName, sp.Scene.Name);
- // return;
- // }
+ return;
+ }
- // m_log.WarnFormat(
- // "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.",
- // sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
-
- // Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Destination region did not signal teleport completion.");
+ m_log.WarnFormat(
+ "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.",
+ sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
- // return;
- //}
+ Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Destination region did not signal teleport completion.");
+
+ return;
+ }
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
@@ -914,7 +921,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
//
// This sleep can be increased if necessary. However, whilst it's active,
// an agent cannot teleport back to this region if it has teleported away.
- Thread.Sleep(15000);
+ Thread.Sleep(2000);
sp.Scene.IncomingCloseAgent(sp.UUID, false);
}
@@ -925,6 +932,126 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
}
}
+ private void TransferAgent_V2(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
+ IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, string version, out string reason)
+ {
+ ulong destinationHandle = finalDestination.RegionHandle;
+ AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
+
+ // Let's create an agent there if one doesn't exist yet.
+ // NOTE: logout will always be false for a non-HG teleport.
+ bool logout = false;
+ if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
+ {
+ m_interRegionTeleportFailures.Value++;
+
+ sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason));
+
+ m_log.DebugFormat(
+ "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}",
+ sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);
+
+ return;
+ }
+
+ // Past this point we have to attempt clean up if the teleport fails, so update transfer state.
+ m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
+
+ IClientIPEndpoint ipepClient;
+ string capsPath = String.Empty;
+ if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
+ {
+ m_log.DebugFormat(
+ "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}",
+ finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
+
+ //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
+ #region IP Translation for NAT
+ // Uses ipepClient above
+ if (sp.ClientView.TryGet(out ipepClient))
+ {
+ endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
+ }
+ #endregion
+ capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
+ }
+ else
+ {
+ agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
+ capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
+ }
+
+ // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
+ // where that neighbour simulator could otherwise request a child agent create on the source which then
+ // closes our existing agent which is still signalled as root.
+ //sp.IsChildAgent = true;
+
+ // New protocol: send TP Finish directly, without prior ES or EAC. That's what happens in the Linden grid
+ if (m_eqModule != null)
+ m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID);
+ else
+ sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
+ teleportFlags, capsPath);
+
+ m_log.DebugFormat(
+ "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
+ capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
+
+ // Let's send a full update of the agent.
+ AgentData agent = new AgentData();
+ sp.CopyTo(agent);
+ agent.Position = agentCircuit.startpos;
+ agent.SenderWantsToWaitForRoot = true;
+ //SetCallbackURL(agent, sp.Scene.RegionInfo);
+
+ // Send the Update. If this returns true, we know the client has contacted the destination
+ // via CompleteMovementIntoRegion, so we can let go.
+ // If it returns false, something went wrong, and we need to abort.
+ m_log.DebugFormat("[ZZZ]: Sending Update");
+ if (!UpdateAgent(reg, finalDestination, agent, sp))
+ {
+ if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
+ {
+ m_interRegionTeleportAborts.Value++;
+
+ m_log.DebugFormat(
+ "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
+ sp.Name, finalDestination.RegionName, sp.Scene.Name);
+
+ return;
+ }
+
+ m_log.WarnFormat(
+ "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.",
+ sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
+
+ Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
+ return;
+ }
+
+ m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
+
+ // May need to logout or other cleanup
+ AgentHasMovedAway(sp, logout);
+
+ // Well, this is it. The agent is over there.
+ KillEntity(sp.Scene, sp.LocalId);
+
+ // Now let's make it officially a child agent
+ sp.MakeChildAgent();
+
+ // OK, it got this agent. Let's close some child agents
+ sp.CloseChildAgents(newRegionX, newRegionY);
+
+ // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
+
+ if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
+ sp.Scene.IncomingCloseAgent(sp.UUID, false);
+ else
+ // now we have a child agent in this region.
+ sp.Reset();
+ }
+
///
/// Clean up an inter-region teleport that did not complete, either because of simulator failure or cancellation.
///
@@ -938,11 +1065,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
- sp.IsChildAgent = false;
- ReInstantiateScripts(sp);
-
- EnableChildAgents(sp);
+ if (sp.IsChildAgent) // We had set it to child before attempted TP (V1)
+ {
+ sp.IsChildAgent = false;
+ ReInstantiateScripts(sp);
+ EnableChildAgents(sp);
+ }
// Finally, kill the agent we just created at the destination.
// XXX: Possibly this should be done asynchronously.
Scene.SimulationService.CloseAgent(finalDestination, sp.UUID, auth_token);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index 6d5039b6fe..7dd10f78a5 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
///
/// Version of this service
///
- private const string m_Version = "SIMULATION/0.1";
+ private const string m_Version = "SIMULATION/0.2";
///
/// Map region ID to scene.
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 724a2d40b2..75318ffe1e 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -4206,6 +4206,20 @@ namespace OpenSim.Region.Framework.Scenes
m_log.WarnFormat("[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).", childAgentUpdate.UUID, cAgentData.SessionID);
childAgentUpdate.ChildAgentDataUpdate(cAgentData);
+
+ int ntimes = 20;
+ if (cAgentData.SenderWantsToWaitForRoot)
+ {
+ while (childAgentUpdate.IsChildAgent && ntimes-- > 0)
+ Thread.Sleep(500);
+
+ m_log.DebugFormat(
+ "[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits",
+ childAgentUpdate.Name, childAgentUpdate.UUID, childAgentUpdate.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 20 - ntimes);
+
+ if (childAgentUpdate.IsChildAgent)
+ return false;
+ }
return true;
}
return false;
@@ -4263,10 +4277,6 @@ namespace OpenSim.Region.Framework.Scenes
m_log.WarnFormat(
"[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout",
agentID, RegionInfo.RegionName);
-// else
-// m_log.DebugFormat(
-// "[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits",
-// sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 10 - ntimes);
return sp;
}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 33db88bcea..bcb8ef11d3 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -29,7 +29,9 @@ using System;
using System.Xml;
using System.Collections.Generic;
using System.Reflection;
+using System.Threading;
using System.Timers;
+using Timer = System.Timers.Timer;
using OpenMetaverse;
using log4net;
using Nini.Config;
@@ -1292,6 +1294,26 @@ namespace OpenSim.Region.Framework.Scenes
PhysicsActor.Size = new Vector3(0.45f, 0.6f, height);
}
+ private bool WaitForUpdateAgent(IClientAPI client)
+ {
+ // Before UpdateAgent, m_originRegionID is UUID.Zero; after, it's non-Zero
+ int count = 20;
+ while (m_originRegionID.Equals(UUID.Zero) && count-- > 0)
+ {
+ m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.RegionInfo.RegionName);
+ Thread.Sleep(200);
+ }
+
+ if (m_originRegionID.Equals(UUID.Zero))
+ {
+ // Movement into region will fail
+ m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived", client.Name);
+ return false;
+ }
+
+ return true;
+ }
+
///
/// Complete Avatar's movement into the region.
///
@@ -1309,6 +1331,12 @@ namespace OpenSim.Region.Framework.Scenes
"[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
client.Name, Scene.RegionInfo.RegionName, AbsolutePosition);
+ if (m_teleportFlags != TeleportFlags.ViaLogin)
+ // Let's wait until UpdateAgent (called by departing region) is done
+ if (!WaitForUpdateAgent(client))
+ // The sending region never sent the UpdateAgent data, we have to refuse
+ return;
+
Vector3 look = Velocity;
if ((look.X == 0) && (look.Y == 0) && (look.Z == 0))
@@ -1329,10 +1357,11 @@ namespace OpenSim.Region.Framework.Scenes
bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
MakeRootAgent(AbsolutePosition, flying);
+
+ // Tell the client that we're totally ready
ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
+
// Remember in HandleUseCircuitCode, we delayed this to here
- // This will also send the initial data to clients when TP to a neighboring region.
- // Not ideal, but until we know we're TP-ing from a neighboring region, there's not much we can do
if (m_teleportFlags > 0)
SendInitialDataToMe();