29 using System.Collections.Generic;
31 using System.Reflection;
32 using System.Threading;
33 using OpenSim.Framework;
34 using OpenSim.Framework.Capabilities;
35 using OpenSim.Framework.Client;
36 using OpenSim.Framework.Monitoring;
37 using OpenSim.Region.Framework.Interfaces;
38 using OpenSim.Region.Framework.Scenes;
39 using OpenSim.Region.PhysicsModules.SharedBase;
40 using OpenSim.Services.Interfaces;
51 [Extension(Path =
"/OpenSim/RegionModules", NodeName =
"RegionModule", Id =
"EntityTransferModule")]
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private static readonly
string LogHeader =
"[ENTITY TRANSFER MODULE]";
57 public const int DefaultMaxTransferDistance = 4095;
58 public const bool WaitForAgentArrivedAtDestinationDefault =
true;
63 public int MaxTransferDistance {
get; set; }
69 public bool WaitForAgentArrivedAtDestination {
get; set; }
80 public bool DisableInterRegionTeleportCancellation {
get; set; }
85 private Stat m_interRegionTeleportAttempts;
90 private Stat m_interRegionTeleportAborts;
95 private Stat m_interRegionTeleportCancels;
105 private Stat m_interRegionTeleportFailures;
110 protected bool m_Enabled =
false;
122 private class BannedRegionCache
124 private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions =
125 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
126 ExpiringCache<ulong, DateTime> m_idCache;
128 public BannedRegionCache()
132 public bool IfBanned(ulong pRegionHandle, UUID pAgentID)
135 if (m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
137 if (m_idCache.TryGetValue(pRegionHandle, out m_banUntil))
139 if (DateTime.Now < m_banUntil)
148 public void Add(ulong pRegionHandle, UUID pAgentID)
150 this.Add(pRegionHandle, pAgentID, 45, 15);
153 public void Add(ulong pRegionHandle, UUID pAgentID,
double newTime,
double extendTime)
155 if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
157 m_idCache =
new ExpiringCache<ulong, DateTime>();
158 m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(newTime));
160 m_idCache.Add(pRegionHandle, DateTime.Now + TimeSpan.FromSeconds(extendTime), TimeSpan.FromSeconds(extendTime));
164 public void Remove(ulong pRegionHandle, UUID pAgentID)
166 if (m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
168 m_idCache.Remove(pRegionHandle);
173 private BannedRegionCache m_bannedRegionCache =
new BannedRegionCache();
178 #region ISharedRegionModule
180 public Type ReplaceableInterface
185 public virtual string Name
187 get {
return "BasicEntityTransferModule"; }
192 IConfig moduleConfig = source.Configs[
"Modules"];
193 if (moduleConfig != null)
195 string name = moduleConfig.GetString(
"EntityTransferModule",
"");
198 InitialiseCommon(source);
199 m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: {0} enabled.", Name);
210 IConfig hypergridConfig = source.Configs[
"Hypergrid"];
211 if (hypergridConfig != null)
213 m_ThisHomeURI = hypergridConfig.GetString(
"HomeURI", string.Empty);
214 if (m_ThisHomeURI !=
string.Empty && !m_ThisHomeURI.EndsWith(
"/"))
215 m_ThisHomeURI +=
'/';
217 m_GatekeeperURI = hypergridConfig.GetString(
"GatekeeperURI", string.Empty);
218 if (m_GatekeeperURI !=
string.Empty && !m_GatekeeperURI.EndsWith(
"/"))
219 m_GatekeeperURI +=
'/';
222 IConfig transferConfig = source.Configs[
"EntityTransfer"];
223 if (transferConfig != null)
225 DisableInterRegionTeleportCancellation
226 = transferConfig.GetBoolean(
"DisableInterRegionTeleportCancellation",
false);
228 WaitForAgentArrivedAtDestination
229 = transferConfig.GetBoolean(
"wait_for_callback", WaitForAgentArrivedAtDestinationDefault);
231 MaxTransferDistance = transferConfig.GetInt(
"max_distance", DefaultMaxTransferDistance);
235 MaxTransferDistance = DefaultMaxTransferDistance;
254 m_interRegionTeleportAttempts =
256 "InterRegionTeleportAttempts",
257 "Number of inter-region teleports attempted.",
258 "This does not count attempts which failed due to pre-conditions (e.g. target simulator refused access).\n"
259 +
"You can get successfully teleports by subtracting aborts, cancels and teleport failures from this figure.",
267 m_interRegionTeleportAborts =
269 "InterRegionTeleportAborts",
270 "Number of inter-region teleports aborted due to client actions.",
271 "The chief action is simultaneous logout whilst teleporting.",
279 m_interRegionTeleportCancels =
281 "InterRegionTeleportCancels",
282 "Number of inter-region teleports cancelled by the client.",
291 m_interRegionTeleportFailures =
293 "InterRegionTeleportFailures",
294 "Number of inter-region teleports that failed due to server/client/network issues.",
295 "This number may not be very helpful in open-grid/hg situations as the network connectivity/quality of destinations is uncontrollable.",
303 StatsManager.RegisterStat(m_interRegionTeleportAttempts);
304 StatsManager.RegisterStat(m_interRegionTeleportAborts);
305 StatsManager.RegisterStat(m_interRegionTeleportCancels);
306 StatsManager.RegisterStat(m_interRegionTeleportFailures);
309 scene.EventManager.OnNewClient += OnNewClient;
314 client.OnTeleportHomeRequest += TriggerTeleportHome;
315 client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
317 if (!DisableInterRegionTeleportCancellation)
318 client.OnTeleportCancel += OnClientCancelTeleport;
320 client.OnConnectionClosed += OnConnectionClosed;
329 StatsManager.DeregisterStat(m_interRegionTeleportAttempts);
330 StatsManager.DeregisterStat(m_interRegionTeleportAborts);
331 StatsManager.DeregisterStat(m_interRegionTeleportCancels);
332 StatsManager.DeregisterStat(m_interRegionTeleportFailures);
341 m_eqModule = Scene.RequestModuleInterface<
IEventQueue>();
347 #region Agent Teleports
349 private void OnConnectionClosed(
IClientAPI client)
354 "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout",
355 client.Name, Scene.Name);
359 private void OnClientCancelTeleport(
IClientAPI client)
361 m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Cancelling);
364 "[ENTITY TRANSFER MODULE]: Received teleport cancel request from {0} in {1}", client.Name, Scene.Name);
379 string destinationRegionName =
"(not found)";
383 if (!m_entityTransferStateMachine.SetInTransit(sp.
UUID))
386 "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2}@{3} - agent is already in transit.",
387 sp.Name, sp.UUID, position, regionHandle);
389 sp.ControllingClient.SendTeleportFailed(
"Previous teleport process incomplete. Please retry shortly.");
397 sp.Animator.ResetAnimations();
401 destinationRegionName = sp.Scene.RegionInfo.RegionName;
403 TeleportAgentWithinRegion(sp, position, lookAt, teleportFlags);
410 TeleportAgentToDifferentRegion(
411 sp, regionHandle, position, lookAt, teleportFlags, out finalDestination);
415 if (finalDestination != null)
416 destinationRegionName = finalDestination.RegionName;
423 "[ENTITY TRANSFER MODULE]: Exception on teleport of {0} from {1}@{2} to {3}@{4}: {5}{6}",
424 sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName,
425 e.Message, e.StackTrace);
427 sp.ControllingClient.SendTeleportFailed(
"Internal error");
431 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
442 private void TeleportAgentWithinRegion(
ScenePresence sp, Vector3 position, Vector3 lookAt, uint teleportFlags)
445 "[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}",
446 sp.Name, position, sp.Scene.RegionInfo.RegionName);
451 Vector3 emergencyPos =
new Vector3(128, 128, 128);
454 "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2} in {3}. Substituting {4}",
455 position, sp.Name, sp.UUID, Scene.Name, emergencyPos);
457 position = emergencyPos;
461 float localHalfAVHeight = 0.8f;
463 localHalfAVHeight = sp.Appearance.AvatarHeight / 2;
465 float posZLimit = 22;
468 posZLimit = (float)sp.
Scene.
Heightmap[(
int)position.X, (int)position.Y];
470 posZLimit += localHalfAVHeight + 0.1f;
472 if ((position.Z < posZLimit) && !(Single.IsInfinity(posZLimit) || Single.IsNaN(posZLimit)))
474 position.Z = posZLimit;
482 sp.ControllingClient.SendTeleportStart(teleportFlags);
484 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
486 sp.Velocity = Vector3.Zero;
487 sp.Teleport(position);
489 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.ReceivedAtDestination);
493 sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)
Changed.TELEPORT);
496 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
508 private void TeleportAgentToDifferentRegion(
510 Vector3 lookAt, uint teleportFlags, out
GridRegion finalDestination)
518 string homeURI = Scene.GetAgentHomeURI(sp.ControllingClient.AgentId);
523 if (finalDestination == null)
525 m_log.WarnFormat(
"{0} Final destination is having problems. Unable to teleport {1} {2}: {3}",
526 LogHeader, sp.Name, sp.UUID, message);
528 sp.ControllingClient.SendTeleportFailed(message);
537 sp.ControllingClient.SendTeleportFailed(
"Space warp! You would crash. Move to a different region and try again.");
542 string reason = string.Empty;
543 if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason))
545 sp.ControllingClient.SendTeleportFailed(reason);
550 sp.ControllingClient.SendAgentAlertMessage(message,
true);
555 DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags);
562 finalDestination = null;
566 sp.ControllingClient.SendTeleportFailed(
"The region you tried to teleport to doesn't exist anymore");
570 Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY);
573 block.X = (ushort)(regX);
574 block.Y = (ushort)(regY);
575 block.Access = (byte)SimAccess.Down;
577 List<MapBlockData> blocks =
new List<MapBlockData>();
579 sp.ControllingClient.SendMapBlock(blocks, 0);
586 private GridRegion GetTeleportDestinationRegion(
IGridService gridService, UUID scope, ulong regionHandle, ref Vector3 position)
589 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
592 double worldX = (double)x + position.X;
593 double worldY = (
double)y + position.Y;
596 GridRegion reg = GetRegionContainingWorldLocation(gridService, scope, worldX, worldY);
601 position.X += x - reg.RegionLocX;
602 position.Y += y - reg.RegionLocY;
611 reason = String.Empty;
625 if(MaxTransferDistance == 0)
634 return Math.Abs(sourceRegion.RegionLocX - destRegion.RegionCoordX) <= MaxTransferDistance
643 Vector3 position, Vector3 lookAt, uint teleportFlags)
647 if (!m_entityTransferStateMachine.SetInTransit(sp.
UUID))
650 "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.",
651 sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position);
652 sp.ControllingClient.SendTeleportFailed(
"Agent is already in transit.");
658 DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags);
663 "[ENTITY TRANSFER MODULE]: Exception on teleport of {0} from {1}@{2} to {3}@{4}: {5}{6}",
664 sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, finalDestination.RegionName,
665 e.Message, e.StackTrace);
667 sp.ControllingClient.SendTeleportFailed(
"Internal error");
671 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
679 private void DoTeleportInternal(
681 Vector3 position, Vector3 lookAt, uint teleportFlags)
683 if (reg == null || finalDestination == null)
685 sp.ControllingClient.SendTeleportFailed(
"Unable to locate destination");
689 string homeURI = Scene.GetAgentHomeURI(sp.ControllingClient.AgentId);
692 "[ENTITY TRANSFER MODULE]: Teleporting {0} {1} from {2} to {3} ({4}) {5}/{6}",
693 sp.Name, sp.UUID, sp.Scene.RegionInfo.RegionName,
694 reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position);
698 if (!IsWithinMaxTeleportDistance(sourceRegion, finalDestination))
700 sp.ControllingClient.SendTeleportFailed(
702 "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way",
703 finalDestination.RegionName, finalDestination.RegionCoordX, finalDestination.RegionCoordY,
704 sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY,
705 MaxTransferDistance));
710 ulong destinationHandle = finalDestination.RegionHandle;
715 IPEndPoint endPoint = finalDestination.ExternalEndPoint;
716 if (endPoint == null || endPoint.Address == null)
718 sp.ControllingClient.SendTeleportFailed(
"Remote Region appears to be down");
725 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
734 sp.ControllingClient.SendTeleportFailed(reason);
737 "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because: {3}",
738 sp.Name, sp.Scene.Name, finalDestination.RegionName, reason);
746 m_interRegionTeleportAttempts.Value++;
749 "[ENTITY TRANSFER MODULE]: {0} transfer protocol version to {1} is {2} / {3}",
750 sp.Scene.Name, finalDestination.RegionName, ctx.OutboundVersion, ctx.InboundVersion);
759 if (DisableInterRegionTeleportCancellation)
774 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
776 agentCircuit.startpos = position;
777 agentCircuit.child =
true;
782 agentCircuit.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
784 if (currentAgentCircuit != null)
786 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
787 agentCircuit.IPAddress = currentAgentCircuit.IPAddress;
788 agentCircuit.Viewer = currentAgentCircuit.Viewer;
789 agentCircuit.Channel = currentAgentCircuit.Channel;
790 agentCircuit.Mac = currentAgentCircuit.Mac;
791 agentCircuit.Id0 = currentAgentCircuit.Id0;
796 uint newRegionX, newRegionY, oldRegionX, oldRegionY;
797 Util.RegionHandleToRegionLoc(destinationHandle, out newRegionX, out newRegionY);
798 Util.RegionHandleToRegionLoc(sourceRegion.RegionHandle, out oldRegionX, out oldRegionY);
799 int oldSizeX = (int)sourceRegion.RegionSizeX;
800 int oldSizeY = (
int)sourceRegion.RegionSizeY;
801 int newSizeX = finalDestination.RegionSizeX;
802 int newSizeY = finalDestination.RegionSizeY;
804 bool OutSideViewRange = NeedsNewAgent(sp.
RegionViewDistance, oldRegionX, newRegionX, oldRegionY, newRegionY,
805 oldSizeX, oldSizeY, newSizeX, newSizeY);
807 if (OutSideViewRange)
810 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}",
811 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
814 #region IP Translation for NAT
818 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
821 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
825 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
826 if (agentCircuit.CapsPath == null)
827 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
832 TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, OutSideViewRange , ctx, out reason);
834 TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, OutSideViewRange, ctx, out reason);
838 IPEndPoint endPoint, uint teleportFlags,
bool OutSideViewRange,
EntityTransferContext ctx, out
string reason)
840 ulong destinationHandle = finalDestination.RegionHandle;
841 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
844 "[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}",
845 sp.Name, Scene.Name, finalDestination.RegionName);
847 string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
852 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, ctx, out reason, out logout))
854 m_interRegionTeleportFailures.Value++;
857 "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}",
858 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);
860 sp.ControllingClient.SendTeleportFailed(reason);
865 if (m_entityTransferStateMachine.GetAgentTransferState(sp.
UUID) == AgentTransferState.Cancelling)
867 m_interRegionTeleportCancels.Value++;
870 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
871 sp.Name, finalDestination.RegionName, sp.Scene.Name);
875 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.
UUID) == AgentTransferState.Aborting)
877 m_interRegionTeleportAborts.Value++;
880 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
881 sp.Name, finalDestination.RegionName, sp.Scene.Name);
887 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
891 if (OutSideViewRange)
893 if (m_eqModule != null)
898 m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID,
899 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
900 m_log.DebugFormat(
"{0} Sent EnableSimulator. regName={1}, size=<{2},{3}>", LogHeader,
901 finalDestination.RegionName, finalDestination.RegionSizeX, finalDestination.RegionSizeY);
911 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, finalDestination.RegionHandle,
912 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
919 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
928 agent.
ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
930 agent.Position = agentCircuit.startpos;
936 if (m_entityTransferStateMachine.GetAgentTransferState(sp.
UUID) == AgentTransferState.Aborting)
938 m_interRegionTeleportAborts.Value++;
941 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent",
942 sp.Name, finalDestination.RegionName, sp.Scene.Name);
951 if (!
UpdateAgent(reg, finalDestination, agent, sp, ctx))
953 if (m_entityTransferStateMachine.GetAgentTransferState(sp.
UUID) == AgentTransferState.Aborting)
955 m_interRegionTeleportAborts.Value++;
958 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
959 sp.Name, finalDestination.RegionName, sp.Scene.Name);
965 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
966 sp.Name, finalDestination.RegionName, sp.Scene.Name);
968 Fail(sp, finalDestination, logout, currentAgentCircuit.
SessionID.ToString(),
"Connection between viewer and destination region could not be established.");
972 if (m_entityTransferStateMachine.GetAgentTransferState(sp.
UUID) == AgentTransferState.Cancelling)
974 m_interRegionTeleportCancels.Value++;
977 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
978 sp.Name, finalDestination.RegionName, sp.Scene.Name);
980 CleanupFailedInterRegionTeleport(sp, currentAgentCircuit.
SessionID.ToString(), finalDestination);
986 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
987 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
992 sp.IsChildAgent =
true;
995 if (m_eqModule != null)
997 m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID,
998 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
1002 sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
1003 teleportFlags, capsPath);
1009 if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.
UUID))
1011 if (m_entityTransferStateMachine.GetAgentTransferState(sp.
UUID) == AgentTransferState.Aborting)
1013 m_interRegionTeleportAborts.Value++;
1016 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.",
1017 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1023 "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.",
1024 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
1026 Fail(sp, finalDestination, logout, currentAgentCircuit.
SessionID.ToString(),
"Destination region did not signal teleport completion.");
1043 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
1045 sp.CloseChildAgents(logout, destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY);
1048 AgentHasMovedAway(sp, logout);
1050 sp.HasMovedAway(!(OutSideViewRange || logout));
1055 sp.MakeChildAgent(destinationHandle);
1059 if (NeedsClosing(reg, OutSideViewRange))
1074 sp.Scene.CloseAgent(sp.UUID,
false);
1079 IPEndPoint endPoint, uint teleportFlags,
bool OutSideViewRange,
EntityTransferContext ctx, out
string reason)
1081 ulong destinationHandle = finalDestination.RegionHandle;
1082 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1084 string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);;
1088 bool logout =
false;
1089 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, ctx, out reason, out logout))
1091 m_interRegionTeleportFailures.Value++;
1094 "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}",
1095 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);
1097 sp.ControllingClient.SendTeleportFailed(reason);
1102 if (m_entityTransferStateMachine.GetAgentTransferState(sp.
UUID) == AgentTransferState.Cancelling)
1104 m_interRegionTeleportCancels.Value++;
1107 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
1108 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1112 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.
UUID) == AgentTransferState.Aborting)
1114 m_interRegionTeleportAborts.Value++;
1117 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
1118 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1124 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
1132 if (m_eqModule != null)
1133 m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID,
1134 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
1136 sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
1137 teleportFlags, capsPath);
1140 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
1141 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
1146 agent.Position = agentCircuit.startpos;
1149 agent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
1151 agent.SenderWantsToWaitForRoot =
true;
1158 sp.DoNotCloseAfterTeleport =
false;
1163 if (!
UpdateAgent(reg, finalDestination, agent, sp, ctx))
1165 if (m_entityTransferStateMachine.GetAgentTransferState(sp.
UUID) == AgentTransferState.Aborting)
1167 m_interRegionTeleportAborts.Value++;
1170 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
1171 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1177 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
1178 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1180 Fail(sp, finalDestination, logout, currentAgentCircuit.
SessionID.ToString(),
"Connection between viewer and destination region could not be established.");
1184 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
1192 sp.CloseChildAgents(logout, destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY);
1194 sp.HasMovedAway(!(OutSideViewRange || logout));
1197 AgentHasMovedAway(sp, logout);
1202 sp.MakeChildAgent(destinationHandle);
1206 if (NeedsClosing(reg, OutSideViewRange))
1218 Thread.Sleep(15000);
1227 "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name);
1229 sp.Scene.CloseAgent(sp.UUID,
false);
1251 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
1255 sp.IsChildAgent =
false;
1256 ReInstantiateScripts(sp);
1258 EnableChildAgents(sp);
1262 Scene.SimulationService.CloseAgent(finalDestination, sp.UUID, auth_token);
1274 CleanupFailedInterRegionTeleport(sp, auth_code, finalDestination);
1276 m_interRegionTeleportFailures.Value++;
1278 sp.ControllingClient.SendTeleportFailed(
1280 "Problems connecting to destination {0}, reason: {1}", finalDestination.RegionName, reason));
1282 sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout);
1288 source.RawServerURI = m_GatekeeperURI;
1291 bool success = Scene.SimulationService.CreateAgent(source, finalDestination, agentCircuit, teleportFlags, ctx, out reason);
1294 sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout);
1301 return Scene.SimulationService.UpdateAgent(finalDestination, agent, ctx);
1306 agent.CallbackURI = region.ServerURI +
"agent/" + agent.AgentID.ToString() +
"/" + region.
RegionID.ToString() +
"/release/";
1309 "[ENTITY TRANSFER MODULE]: Set release callback URL to {0} in {1}",
1310 agent.CallbackURI, region.RegionName);
1328 scene.SendKillObject(
new List<uint> { localID });
1341 protected virtual bool NeedsNewAgent(
float viewdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY,
1342 int oldsizeX,
int oldsizeY,
int newsizeX,
int newsizeY)
1346 Vector2 swCorner, neCorner;
1347 GetMegaregionViewRange(out swCorner, out neCorner);
1350 "[ENTITY TRANSFER MODULE]: Megaregion view of {0} is from {1} to {2} with new agent check for {3},{4}",
1351 Scene.Name, swCorner, neCorner, newRegionX, newRegionY);
1353 return !(newRegionX >= swCorner.X && newRegionX <= neCorner.X && newRegionY >= swCorner.Y && newRegionY <= neCorner.Y);
1356 return Util.IsOutsideView(viewdist, oldRegionX, newRegionX, oldRegionY, newRegionY,
1357 oldsizeX, oldsizeY, newsizeX, newsizeY);
1364 return OutViewRange;
1369 #region Landmark Teleport
1378 GridRegion info = Scene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
1383 remoteClient.SendTeleportFailed(
"The teleport destination could not be found.");
1387 Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark));
1392 #region Teleport Home
1396 TeleportHome(
id, client);
1402 "[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.Name, client.AgentId);
1405 GridUserInfo uinfo = Scene.GridUserService.GetGridUserInfo(client.AgentId.ToString());
1409 if (uinfo.HomeRegionID ==
UUID.Zero)
1412 m_log.ErrorFormat(
"{0} No grid user info found for {1} {2}. Cannot send home.",
1413 LogHeader, client.Name, client.AgentId);
1414 client.SendTeleportFailed(
"You don't have a home position set.");
1417 GridRegion regionInfo = Scene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID);
1418 if (regionInfo == null)
1421 client.SendTeleportFailed(
"Your home region could not be found.");
1425 m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Home region of {0} is {1} ({2}-{3})",
1426 client.Name, regionInfo.RegionName, regionInfo.RegionCoordX, regionInfo.RegionCoordY);
1429 ((
Scene)(client.
Scene)).RequestTeleportLocation(
1430 client, regionInfo.
RegionHandle, uinfo.HomePosition, uinfo.HomeLookAt,
1431 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
1437 client.SendTeleportFailed(
"Your home region could not be found.");
1445 #region Agent Crossings
1450 reason = String.Empty;
1452 UUID agentID = agent.UUID;
1453 ulong destinyHandle = destiny.RegionHandle;
1455 if (m_bannedRegionCache.IfBanned(destinyHandle, agentID))
1460 Scene ascene = agent.Scene;
1461 string homeURI = ascene.GetAgentHomeURI(agentID);
1467 m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0);
1475 string r = String.Empty;
1476 return GetDestination(scene, agentID, pos, ctx, out newpos, out r);
1489 failureReason = string.Empty;
1496 double presenceWorldY = (
double)scene.RegionInfo.WorldLocY + pos.Y;
1499 GridRegion neighbourRegion = GetRegionContainingWorldLocation(
1501 presenceWorldX, presenceWorldY,
1504 if (neighbourRegion == null)
1508 if (m_bannedRegionCache.IfBanned(neighbourRegion.
RegionHandle, agentID))
1513 m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID);
1516 newpos =
new Vector3((
float)(presenceWorldX - (
double)neighbourRegion.
RegionLocX),
1517 (
float)(presenceWorldY - (
double)neighbourRegion.
RegionLocY),
1520 string homeURI = scene.GetAgentHomeURI(agentID);
1523 neighbourRegion, agentID, homeURI,
false, newpos,
1527 m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
1531 return neighbourRegion;
1536 agent.IsInTransit =
true;
1538 d.BeginInvoke(agent, isFlying, CrossCompleted, d);
1542 private void CrossCompleted(IAsyncResult iar)
1547 m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
1549 if(!agent.IsChildAgent)
1552 agent.CrossToNewRegionFail();
1554 agent.IsInTransit =
false;
1563 string failureReason;
1565 Vector3 pos = agent.AbsolutePosition + agent.Velocity;
1568 ctx, out newpos, out failureReason);
1569 if (neighbourRegion == null)
1571 if (failureReason !=
String.Empty)
1572 agent.ControllingClient.SendAlertMessage(failureReason);
1578 CrossAgentToNewRegionAsync(agent, newpos, neighbourRegion, isFlying, ctx);
1579 agent.IsInTransit =
false;
1583 public delegate
void InformClientToInitiateTeleportToLocationDelegate(
ScenePresence agent, uint regionX, uint regionY, Vector3 position,
Scene initiatingScene);
1585 private void InformClientToInitiateTeleportToLocation(
ScenePresence agent, uint regionX, uint regionY, Vector3 position,
Scene initiatingScene)
1590 InformClientToInitiateTeleportToLocationDelegate d = InformClientToInitiateTeleportToLocationAsync;
1591 d.BeginInvoke(agent, regionX, regionY, position, initiatingScene,
1592 InformClientToInitiateTeleportToLocationCompleted,
1597 Scene initiatingScene)
1599 Thread.Sleep(10000);
1602 "[ENTITY TRANSFER MODULE]: Auto-reteleporting {0} to correct megaregion location {1},{2},{3} from {4}",
1603 agent.Name, regionX, regionY, position, initiatingScene.Name);
1605 agent.Scene.RequestTeleportLocation(
1606 agent.ControllingClient,
1607 Util.RegionLocToHandle(regionX, regionY),
1610 (uint)Constants.TeleportFlags.ViaLocation);
1646 private void InformClientToInitiateTeleportToLocationCompleted(IAsyncResult iar)
1648 InformClientToInitiateTeleportToLocationDelegate icon =
1649 (InformClientToInitiateTeleportToLocationDelegate)iar.AsyncState;
1650 icon.EndInvoke(iar);
1655 if (neighbourRegion == null)
1658 m_entityTransferStateMachine.SetInTransit(agent.UUID);
1660 agent.RemoveFromPhysicalScene();
1675 m_log.DebugFormat(
"{0}: CrossAgentToNewRegionAsync: new region={1} at <{2},{3}>. newpos={4}",
1676 LogHeader, neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, pos);
1678 if (!CrossAgentToNewRegionPrep(agent, neighbourRegion))
1680 m_log.DebugFormat(
"{0}: CrossAgentToNewRegionAsync: prep failed. Resetting transfer state", LogHeader);
1681 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1684 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying, ctx))
1686 m_log.DebugFormat(
"{0}: CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader);
1687 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1690 CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, ctx);
1694 m_log.Error(string.Format(
"{0}: CrossAgentToNewRegionAsync: failed with exception ", LogHeader), e);
1702 int ts = Util.EnvironmentTickCount();
1706 agent.CopyTo(cAgent);
1710 cAgent.Position = pos;
1712 cAgent.ChildrenCapSeeds = agent.KnownRegions;
1715 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
1726 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
1729 "[ENTITY TRANSFER MODULE]: Region {0} would not accept update for agent {1} on cross attempt. Returning to original region.",
1730 neighbourRegion.RegionName, agent.Name);
1732 ReInstantiateScripts(agent);
1734 agent.AddToPhysicalScene(isFlying);
1739 m_log.DebugFormat(
"[CrossAgentIntoNewRegionMain] ok, time {0}ms",Util.EnvironmentTickCountSubtract(ts));
1745 "[ENTITY TRANSFER MODULE]: Problem crossing user {0} to new region {1} from {2}. Exception {3}{4}",
1746 agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName, e.Message, e.StackTrace);
1762 m_log.ErrorFormat(
"[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.",
1763 neighbourRegion.RegionHandle);
1769 agent.IsChildAgent =
true;
1771 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps);
1773 m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID);
1777 if (m_eqModule != null)
1779 m_eqModule.CrossRegion(
1780 neighbourRegion.RegionHandle, pos, vel2 ,
1781 neighbourRegion.ExternalEndPoint,
1782 capsPath, agent.UUID, agent.ControllingClient.SessionId,
1783 neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY);
1787 m_log.ErrorFormat(
"{0} Using old CrossRegion packet. Varregion will not work!!", LogHeader);
1788 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
1802 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination);
1805 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
1807 agent.CloseChildAgents(
false, neighbourRegion.RegionHandle, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY);
1811 agent.HasMovedAway(
true);
1813 agent.MakeChildAgent(neighbourRegion.RegionHandle);
1817 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1847 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
1859 agent.IsInTransit =
false;
1861 m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
1866 #region Enable Child Agent
1876 m_log.DebugFormat(
"[ENTITY TRANSFER]: Enabling child agent in new neighbour {0}", region.RegionName);
1878 ulong currentRegionHandler = sp.Scene.RegionInfo.RegionHandle;
1879 ulong regionhandler = region.RegionHandle;
1881 Dictionary<ulong, string> seeds =
new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1883 if (seeds.ContainsKey(regionhandler))
1884 seeds.Remove(regionhandler);
1891 if (!seeds.ContainsKey(currentRegionHandler))
1894 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1896 agent.BaseFolder = UUID.Zero;
1897 agent.InventoryFolder = UUID.Zero;
1898 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, region);
1901 agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
1903 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1905 seeds.Add(regionhandler, agent.CapsPath);
1909 agent.ChildrenCapSeeds = null;
1913 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, seeds);
1916 sp.KnownRegions = seeds;
1917 sp.AddNeighbourRegionSizeInfo(region);
1919 if (currentAgentCircuit != null)
1921 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
1922 agent.IPAddress = currentAgentCircuit.IPAddress;
1923 agent.Viewer = currentAgentCircuit.Viewer;
1924 agent.Channel = currentAgentCircuit.Channel;
1925 agent.Mac = currentAgentCircuit.Mac;
1926 agent.Id0 = currentAgentCircuit.Id0;
1946 IPEndPoint external = region.ExternalEndPoint;
1947 if (external != null)
1949 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
1950 d.BeginInvoke(sp, agent, region, external,
true,
1951 InformClientOfNeighbourCompleted,
1972 #region Enable Child Agents
1974 private delegate
void InformClientOfNeighbourDelegate(
1986 List<GridRegion> neighbours =
new List<GridRegion>();
1987 Scene spScene = sp.Scene;
1990 if (m_regionInfo != null)
1996 m_log.Debug(
"[ENTITY TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?");
1999 ulong currentRegionHandler = m_regionInfo.RegionHandle;
2001 LinkedList<ulong> previousRegionNeighbourHandles;
2002 Dictionary<ulong, string> seeds;
2005 if (capsModule != null)
2007 seeds =
new Dictionary<ulong, string>(capsModule.GetChildrenSeeds(sp.UUID));
2008 previousRegionNeighbourHandles =
new LinkedList<ulong>(seeds.Keys);
2012 seeds =
new Dictionary<ulong, string>();
2013 previousRegionNeighbourHandles =
new LinkedList<ulong>();
2018 if (!seeds.ContainsKey(currentRegionHandler))
2022 spScene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
2024 List<AgentCircuitData> cagents =
new List<AgentCircuitData>();
2025 List<ulong> newneighbours =
new List<ulong>();
2029 ulong handler = neighbour.RegionHandle;
2031 if (previousRegionNeighbourHandles.Contains(handler))
2034 previousRegionNeighbourHandles.Remove(handler);
2038 if (handler == currentRegionHandler)
2043 agent.BaseFolder = UUID.Zero;
2044 agent.InventoryFolder = UUID.Zero;
2045 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, neighbour);
2048 agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
2050 if (currentAgentCircuit != null)
2052 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
2053 agent.IPAddress = currentAgentCircuit.IPAddress;
2054 agent.Viewer = currentAgentCircuit.Viewer;
2055 agent.Channel = currentAgentCircuit.Channel;
2056 agent.Mac = currentAgentCircuit.Mac;
2057 agent.Id0 = currentAgentCircuit.Id0;
2060 newneighbours.Add(handler);
2061 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
2062 seeds.Add(handler, agent.CapsPath);
2064 agent.ChildrenCapSeeds = null;
2068 if (previousRegionNeighbourHandles.Contains(currentRegionHandler))
2069 previousRegionNeighbourHandles.Remove(currentRegionHandler);
2072 foreach (ulong handler
in previousRegionNeighbourHandles)
2073 seeds.Remove(handler);
2079 if (capsModule != null)
2080 capsModule.SetChildrenSeed(sp.UUID, seeds);
2082 sp.KnownRegions = seeds;
2083 sp.SetNeighbourRegionSizeInfo(neighbours);
2086 agentpos.AgentID =
new UUID(sp.
UUID.Guid);
2087 agentpos.SessionID = spClient.SessionId;
2088 agentpos.Size = sp.Appearance.AvatarSize;
2089 agentpos.Center = sp.CameraPosition;
2090 agentpos.Far = sp.DrawDistance;
2091 agentpos.Position = sp.AbsolutePosition;
2092 agentpos.Velocity = sp.Velocity;
2093 agentpos.RegionHandle = currentRegionHandler;
2094 agentpos.Throttles = spClient.GetThrottlesPacked(1);
2097 Util.FireAndForget(delegate
2104 ulong handler = neighbour.RegionHandle;
2107 if (newneighbours.Contains(handler))
2109 InformClientOfNeighbourAsync(sp, cagents[count], neighbour,
2113 else if (!previousRegionNeighbourHandles.Contains(handler))
2115 spScene.SimulationService.UpdateAgent(neighbour, agentpos);
2118 catch (ArgumentOutOfRangeException)
2121 "[ENTITY TRANSFER MODULE]: Neighbour Regions response included the current region in the neighbour list. The following region will not display to the client: {0} for region {1} ({2}, {3}).",
2122 neighbour.ExternalHostName,
2123 neighbour.RegionHandle,
2124 neighbour.RegionLocX,
2125 neighbour.RegionLocY);
2130 "[ENTITY TRANSFER MODULE]: Could not resolve external hostname {0} for region {1} ({2}, {3}). {4}",
2131 neighbour.ExternalHostName,
2132 neighbour.RegionHandle,
2133 neighbour.RegionLocX,
2134 neighbour.RegionLocY,
2158 #region NotFoundLocationCache class
2163 private class NotFoundLocationCache
2165 private struct NotFoundLocation
2167 public double minX, maxX, minY, maxY;
2168 public DateTime expireTime;
2170 private List<NotFoundLocation> m_notFoundLocations =
new List<NotFoundLocation>();
2171 public NotFoundLocationCache()
2176 public void Add(
double pX,
double pY)
2178 lock (m_notFoundLocations)
2180 if (!LockedContains(pX, pY))
2182 NotFoundLocation nfl =
new NotFoundLocation();
2187 nfl.maxY = nfl.minY + (
double)Constants.RegionSize;
2188 nfl.expireTime = DateTime.Now + TimeSpan.FromSeconds(30);
2189 m_notFoundLocations.Add(nfl);
2196 public bool Contains(
double pX,
double pY)
2199 lock (m_notFoundLocations)
2200 ret = LockedContains(pX, pY);
2203 private
bool LockedContains(
double pX,
double pY)
2206 this.DoExpiration();
2207 foreach (NotFoundLocation nfl
in m_notFoundLocations)
2209 if (pX >= nfl.minX && pX < nfl.maxX && pY >= nfl.minY && pY < nfl.maxY)
2217 private void DoExpiration()
2219 List<NotFoundLocation> m_toRemove = null;
2220 DateTime now = DateTime.Now;
2221 foreach (NotFoundLocation nfl
in m_notFoundLocations)
2223 if (nfl.expireTime < now)
2225 if (m_toRemove == null)
2226 m_toRemove =
new List<NotFoundLocation>();
2227 m_toRemove.Add(nfl);
2230 if (m_toRemove != null)
2232 foreach (NotFoundLocation nfl
in m_toRemove)
2233 m_notFoundLocations.Remove(nfl);
2238 #endregion // NotFoundLocationCache class
2239 private NotFoundLocationCache m_notFoundLocationCache =
new NotFoundLocationCache();
2257 double px,
double py, uint pSizeHint)
2259 m_log.DebugFormat(
"{0} GetRegionContainingWorldLocation: call, XY=<{1},{2}>", LogHeader, px, py);
2261 const double fudge = 2.0;
2268 if (m_notFoundLocationCache.Contains(px, py))
2276 uint possibleX = (uint)Math.Floor(px);
2277 possibleX -= possibleX % Constants.RegionSize;
2278 uint possibleY = (uint)Math.Floor(py);
2279 possibleY -= possibleY % Constants.RegionSize;
2280 ret = pGridService.GetRegionByPosition(pScopeID, (int)possibleX, (
int)possibleY);
2283 m_log.DebugFormat(
"{0} GetRegionContainingWorldLocation: Found region using legacy size. rloc=<{1},{2}>. Rname={3}",
2284 LogHeader, possibleX, possibleY, ret.RegionName);
2290 double range = (double)pSizeHint + fudge;
2295 List<GridRegion> possibleRegions = pGridService.GetRegionRange(pScopeID,
2296 (int)(px - range), (int)(px),
2297 (int)(py - range), (int)(py));
2298 m_log.DebugFormat(
"{0} GetRegionContainingWorldLocation: possibleRegions cnt={1}, range={2}",
2299 LogHeader, possibleRegions.Count, range);
2300 if (possibleRegions != null && possibleRegions.Count > 0)
2305 m_log.DebugFormat(
"{0} GetRegionContainingWorldLocation: possibleRegion nm={1}, regionLoc=<{2},{3}>, regionSize=<{4},{5}>",
2306 LogHeader, gr.RegionName, gr.RegionLocX, gr.RegionLocY, gr.RegionSizeX, gr.RegionSizeY);
2308 && py >= (double)gr.
RegionLocY && py < (
double)(gr.RegionLocY + gr.RegionSizeY))
2312 m_log.DebugFormat(
"{0} GetRegionContainingWorldLocation: found. RegionName={1}", LogHeader, ret.RegionName);
2325 m_notFoundLocationCache.Add(px, py);
2326 m_log.DebugFormat(
"{0} GetRegionContainingWorldLocation: Not found. Remembering loc=<{1},{2}>", LogHeader, px, py);
2332 private void InformClientOfNeighbourCompleted(IAsyncResult iar)
2334 InformClientOfNeighbourDelegate icon = (InformClientOfNeighbourDelegate)iar.AsyncState;
2335 icon.EndInvoke(iar);
2350 IPEndPoint endPoint,
bool newAgent)
2355 Scene scene = sp.Scene;
2358 "[ENTITY TRANSFER MODULE]: Informing {0} {1} about neighbour {2} {3} at ({4},{5})",
2359 sp.Name, sp.UUID, reg.RegionName, endPoint, reg.RegionCoordX, reg.RegionCoordY);
2361 string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(a.CapsPath);
2363 string reason = String.Empty;
2366 bool regionAccepted = scene.SimulationService.CreateAgent(reg, reg, a, (uint)
TeleportFlags.Default, ctx, out reason);
2373 if (m_eqModule != null)
2375 #region IP Translation for NAT
2379 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
2383 m_log.DebugFormat(
"{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " +
2384 "and EstablishAgentCommunication with seed cap {8}", LogHeader,
2385 scene.RegionInfo.RegionName, sp.Name,
2386 reg.RegionName, reg.RegionLocX, reg.RegionLocY, reg.RegionSizeX, reg.RegionSizeY, capsPath);
2388 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID, reg.RegionSizeX, reg.RegionSizeY);
2389 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, reg.RegionHandle, reg.RegionSizeX, reg.RegionSizeY);
2393 sp.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
2397 m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Completed inform {0} {1} about neighbour {2}", sp.Name, sp.UUID, endPoint);
2402 sp.RemoveNeighbourRegion(reg.RegionHandle);
2404 "[ENTITY TRANSFER MODULE]: Region {0} did not accept {1} {2}: {3}",
2405 reg.RegionName, sp.Name, sp.UUID, reason);
2417 private void GetMegaregionViewRange(out Vector2 swCorner, out Vector2 neCorner)
2419 Vector2 extent = Vector2.Zero;
2421 if (m_regionCombinerModule != null)
2423 Vector2 megaRegionSize = m_regionCombinerModule.GetSizeOfMegaregion(Scene.RegionInfo.RegionID);
2424 extent.X = (float)Util.WorldToRegionLoc((uint)megaRegionSize.X);
2425 extent.Y = (float)Util.WorldToRegionLoc((uint)megaRegionSize.Y);
2428 swCorner.X = Scene.RegionInfo.RegionLocX - 1;
2429 swCorner.Y = Scene.RegionInfo.RegionLocY - 1;
2430 neCorner.X = Scene.RegionInfo.RegionLocX + extent.X;
2431 neCorner.Y = Scene.RegionInfo.RegionLocY + extent.Y;
2443 Scene pScene = avatar.Scene;
2445 List<GridRegion> neighbours;
2456 uint ddY = Math.Max(dd, Constants.RegionSize);
2462 uint startX = Util.RegionToWorldLoc(pRegionLocX);
2463 uint endX = startX + m_regionInfo.RegionSizeX;
2464 uint startY = Util.RegionToWorldLoc(pRegionLocY);
2465 uint endY = startY + m_regionInfo.RegionSizeY;
2473 = avatar.Scene.GridService.GetRegionRange(
2474 m_regionInfo.ScopeID, (int)startX, (
int)endX, (int)startY, (
int)endY);
2478 Vector2 swCorner, neCorner;
2479 GetMegaregionViewRange(out swCorner, out neCorner);
2482 = pScene.GridService.GetRegionRange(
2483 m_regionInfo.ScopeID,
2484 (int)Util.RegionToWorldLoc((uint)swCorner.X), (int)Util.RegionToWorldLoc((uint)neCorner.X),
2485 (int)Util.RegionToWorldLoc((uint)swCorner.Y), (int)Util.RegionToWorldLoc((uint)neCorner.Y));
2489 neighbours.RemoveAll( r => r.RegionID == m_regionInfo.RegionID );
2495 #region Agent Arrived
2499 m_entityTransferStateMachine.SetAgentArrivedAtDestination(id);
2504 #region Object Transfers
2508 newpos = targetPosition;
2510 Scene scene = grp.Scene;
2514 int x = (int)targetPosition.X + (
int)scene.RegionInfo.WorldLocX;
2515 if (targetPosition.X >= 0)
2520 int y = (int)targetPosition.Y + (
int)scene.RegionInfo.WorldLocY;
2521 if (targetPosition.Y >= 0)
2526 GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID,x,y);
2527 if (neighbourRegion == null)
2532 float newRegionSizeX = neighbourRegion.RegionSizeX;
2533 float newRegionSizeY = neighbourRegion.RegionSizeY;
2534 if (newRegionSizeX == 0)
2535 newRegionSizeX = Constants.RegionSize;
2536 if (newRegionSizeY == 0)
2537 newRegionSizeY = Constants.RegionSize;
2540 newpos.X = targetPosition.X - (neighbourRegion.RegionLocX - (int)scene.
RegionInfo.
WorldLocX);
2541 newpos.Y = targetPosition.Y - (neighbourRegion.RegionLocY - (int)scene.
RegionInfo.
WorldLocY);
2544 const float enterDistance = 0.2f;
2545 newpos.X = Util.Clamp(newpos.X, enterDistance, newRegionSizeX - enterDistance);
2546 newpos.Y = Util.Clamp(newpos.Y, enterDistance, newRegionSizeY - enterDistance);
2548 return neighbourRegion;
2630 bool successYN =
false;
2631 grp.RootPart.ClearUpdateSchedule();
2634 if (destination != null)
2651 successYN = Scene.SimulationService.CreateObject(destination, newPosition, grp,
true);
2658 grp.Scene.DeleteSceneObject(grp, silent, removeScripts);
2663 "[ENTITY TRANSFER MODULE]: Exception deleting the old object left behind on a border crossing for {0}, {1}",
2670 m_log.Error(
"[ENTITY TRANSFER MODULE]: destination was unexpectedly null in Scene.CrossPrimGroupIntoNewRegion()");
2688 List<SceneObjectGroup> attachments = sp.GetAttachments();
2700 clone.RootPart.GroupPosition = gobj.RootPart.AttachedPos;
2701 clone.IsAttachment =
false;
2705 "[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}",
2706 clone.UUID, destination.RegionName);
2708 CrossPrimGroupIntoNewRegion(destination, Vector3.Zero, clone, silent,
true);
2712 sp.ClearAttachments();
2721 return m_entityTransferStateMachine.GetAgentTransferState(id) != null;
2729 List<SceneObjectGroup> attachments = sp.GetAttachments();
2735 sog.SetState(sp.InTransitScriptStates[i++], sp.Scene);
2736 sog.CreateScriptInstances(0,
false, sp.Scene.DefaultScriptEngine, 0);
2737 sog.ResumeScripts();
2741 "[ENTITY TRANSFER MODULE]: InTransitScriptStates.Count={0} smaller than Attachments.Count={1}",
2742 sp.InTransitScriptStates.Count, attachments.Count);
2745 sp.InTransitScriptStates.Clear();
2758 "[ENTITY TRANSFER MODULE]: Denied prim crossing of {0} {1} into {2} for banned avatar {3}",
2759 so.Name, so.UUID, Scene.Name, so.OwnerID);
2764 if (newPosition != Vector3.Zero)
2765 so.RootPart.GroupPosition = newPosition;
2770 "[ENTITY TRANSFER MODULE]: Problem adding scene object {0} {1} into {2} ",
2771 so.Name, so.UUID, Scene.Name);
2784 m_log.Info(
"[ENTITY TRANSFER MODULE]: Denied prim crossing because of parcel settings");
2786 Scene.DeleteSceneObject(so,
false);
2793 so.RootPart.ParentGroup.CreateScriptInstances(
2794 0,
false, Scene.DefaultScriptEngine, GetStateSource(so));
2799 so.RootPart.KeyframeMotion.UpdateSceneObject(so);
2810 return sp.GetStateSource();
void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx)
virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string auth_code, string reason)
Signal that the inter-region teleport failed and perform cleanup.
EstateSettings EstateSettings
IClientAPI ControllingClient
const uint MaximumRegionSize
OpenSim.Framework.Constants.TeleportFlags TeleportFlags
bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent, bool removeScripts)
Move the given scene object into a new region
void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags)
Wraps DoTeleportInternal() and manages the transfer state.
bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, EntityTransferContext ctx, out string reason)
Scene Scene
The scene to which this entity belongs
bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx)
OpenSim.Framework.RegionInfo RegionInfo
GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, EntityTransferContext ctx, out Vector3 newpos)
ITerrainChannel Heightmap
GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
uint RegionSizeX
X dimension of the region.
Contains the Avatar's Appearance and methods to manipulate the appearance.
bool Cross(ScenePresence agent, bool isFlying)
ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx)
This Closes child agents on neighbouring regions Calls an asynchronous method to do so...
bool UpdateAgent(GridRegion destination, AgentData data, EntityTransferContext ctx)
Full child agent update.
AvatarAppearance Appearance
Dictionary< ulong, string > KnownRegions
uint RegionSizeY
X dimension of the region.
bool IsBanned(UUID avatarID)
Holds individual statistic details
A scene object group is conceptually an object in the scene. The object is constituted of SceneObject...
void StandUp()
Perform the logic necessary to stand the avatar up. This method also executes the stand animation...
bool QueryAccess(GridRegion destination, UUID agentID, string agentHomeURI, bool viaTeleport, Vector3 position, List< UUID > features, EntityTransferContext ctx, out string reason)
Returns whether a propspective user is allowed to visit the region.
delegate ScenePresence CrossAsyncDelegate(ScenePresence agent, bool isFlying)
Records user information specific to a grid but which is not part of a user's account.
virtual bool TeleportHome(UUID id, IClientAPI client)
Teleports the agent for the given client to their home destination.
void ReInstantiateScripts(ScenePresence sp)
UUID SessionID
Non secure Session ID
int RegionCoordY
The co-ordinate of this region in region units
List< SceneObjectGroup > GetAttachments()
Get all the presence's attachments.
virtual void SetCallbackURL(AgentData agent, RegionInfo region)
virtual void InitialiseCommon(IConfigSource source)
Initialize config common for this module and any descendents.
bool IsDeleted
Signals whether this entity was in a scene but has since been removed from it.
virtual void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
virtual bool NeedsNewAgent(float viewdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, int oldsizeX, int oldsizeY, int newsizeX, int newsizeY)
void AgentArrivedAtDestination(UUID id)
GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py, uint pSizeHint)
int RegionLocX
The location of this region in meters. DANGER DANGER! Note that this name means something different i...
bool CanObjectEntry(UUID objectID, bool enteringRegion, Vector3 newPoint)
OpenSim.Services.Interfaces.GridRegion GridRegion
bool IsGridGod(UUID user)
override Vector3 Velocity
Current velocity of the avatar.
virtual void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
virtual void Initialise(IConfigSource source)
This is called to initialize the region module. For shared modules, this is called exactly once...
virtual void AgentHasMovedAway(ScenePresence sp, bool logout)
Clean up operations once an agent has moved away through cross or teleport.
Circuit data for an agent. Connection information shared between regions that accept UDP connections ...
ICapabilitiesModule CapsModule
int RegionLocY
The location of this region in meters. DANGER DANGER! Note that this name means something different i...
AgentCircuitData RequestClientInfo()
Return circuit information for this client.
void InformClientToInitiateTeleportToLocationAsync(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene)
List< string > InTransitScriptStates
Copy of the script states while the agent is in transit. This state may need to be placed back in cas...
StatVerbosity
Verbosity of stat.
virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
ScenePermissions Permissions
GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition, out Vector3 newpos)
void KillEntity(Scene scene, uint localID)
delegate void UpdateAgent(IClientAPI remoteClient, AgentUpdateArgs agentData)
ScenePresence CrossAsync(ScenePresence agent, bool isFlying)
Replacement for ChildAgentDataUpdate. Used over RESTComms and LocalComms.
bool IsLoggingOut
Set if the client is closing due to a logout request
virtual void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
void CrossAttachmentsIntoNewRegion(GridRegion destination, ScenePresence sp, bool silent)
Cross the attachments for an avatar into the destination region.
virtual void PostInitialise()
Interactive OpenSim region server
void EnableChildAgent(ScenePresence sp, GridRegion region)
This informs a single neighbouring region about agent "avatar", and avatar about it Calls an asynch...
virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, EntityTransferContext ctx, out string reason, out bool logout)
bool IncomingPreCloseClient(ScenePresence sp)
Tell a single client to prepare to close.
ISimulationService SimulationService
delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx)
virtual void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
IPEndPoint ExternalEndPoint
virtual GridRegion GetFinalDestination(GridRegion region, UUID agentID, string agentHomeURI, out string message)
virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, string auth_token, GridRegion finalDestination)
Clean up an inter-region teleport that did not complete, either because of simulator failure or cance...
bool PositionIsInCurrentRegion(Vector3 pos)
override Vector3 AbsolutePosition
The absolute position of this scene object in the scene
AgentTransferState
The possible states that an agent can be in when its being transferred between regions.
virtual bool NeedsClosing(GridRegion reg, bool OutViewRange)
void EnableChildAgents(ScenePresence sp)
This informs all neighbouring regions about agent "avatar". and as important informs the avatar about...
KeyframeMotion KeyframeMotion
bool CanTeleport(UUID userID)
bool ValidateAttachments()
This is currently just being done for information.
bool IsInTransit(UUID id)
Show whether the given agent is being teleported.
virtual string Name
The name of this entity
GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, EntityTransferContext ctx, out Vector3 newpos, out string failureReason)
List< GridRegion > GetNeighbors(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY)
Return the list of online regions that are considered to be neighbours to the given scene...
virtual RegionInfo RegionInfo
virtual void OnNewClient(IClientAPI client)
virtual ISceneObject CloneForNewScene()
void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
Teleport an agent within the same or to a different region.
List< UUID > GetFormatsOffered()
virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp, EntityTransferContext ctx)
bool CrossAgentToNewRegionPrep(ScenePresence agent, GridRegion neighbourRegion)
uint RegionLocY
The y co-ordinate of this region in map tiles (e.g. 1000). Coordinate is scaled as world coordinates ...
virtual void TriggerTeleportHome(UUID id, IClientAPI client)
uint RegionLocX
The x co-ordinate of this region in map tiles (e.g. 1000). Coordinate is scaled as world coordinates ...
virtual bool HandleIncomingSceneObject(SceneObjectGroup so, Vector3 newPosition)
bool IsAttachment
Is this scene object acting as an attachment?
Records the state of entities when they are in transfer within or between regions (cross or teleport)...
bool AddSceneObject(SceneObjectGroup sceneObject)
Adds a Scene Object group to the Scene. Verifies that the creator of the object is not banned from th...
void SendTeleportStart(uint flags)
uint ParentID
If the avatar is sitting, the local ID of the prim that it's sitting on. If not sitting then zero...