aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs')
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs542
1 files changed, 423 insertions, 119 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index cb09047..b70aeb7 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -33,6 +33,7 @@ using System.Threading;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Capabilities; 34using OpenSim.Framework.Capabilities;
35using OpenSim.Framework.Client; 35using OpenSim.Framework.Client;
36using OpenSim.Framework.Monitoring;
36using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
38using OpenSim.Region.Physics.Manager; 39using OpenSim.Region.Physics.Manager;
@@ -66,6 +67,42 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
66 /// </summary> 67 /// </summary>
67 public bool WaitForAgentArrivedAtDestination { get; set; } 68 public bool WaitForAgentArrivedAtDestination { get; set; }
68 69
70 /// <summary>
71 /// If true then we ask the viewer to disable teleport cancellation and ignore teleport requests.
72 /// </summary>
73 /// <remarks>
74 /// This is useful in situations where teleport is very likely to always succeed and we want to avoid a
75 /// situation where avatars can be come 'stuck' due to a failed teleport cancellation. Unfortunately, the
76 /// nature of the teleport protocol makes it extremely difficult (maybe impossible) to make teleport
77 /// cancellation consistently suceed.
78 /// </remarks>
79 public bool DisableInterRegionTeleportCancellation { get; set; }
80
81 /// <summary>
82 /// Number of times inter-region teleport was attempted.
83 /// </summary>
84 private Stat m_interRegionTeleportAttempts;
85
86 /// <summary>
87 /// Number of times inter-region teleport was aborted (due to simultaneous client logout).
88 /// </summary>
89 private Stat m_interRegionTeleportAborts;
90
91 /// <summary>
92 /// Number of times inter-region teleport was successfully cancelled by the client.
93 /// </summary>
94 private Stat m_interRegionTeleportCancels;
95
96 /// <summary>
97 /// Number of times inter-region teleport failed due to server/client/network problems (e.g. viewer failed to
98 /// connect with destination region).
99 /// </summary>
100 /// <remarks>
101 /// This is not necessarily a problem for this simulator - in open-grid/hg conditions, viewer connectivity to
102 /// destination simulator is unknown.
103 /// </remarks>
104 private Stat m_interRegionTeleportFailures;
105
69 protected bool m_Enabled = false; 106 protected bool m_Enabled = false;
70 107
71 public Scene Scene { get; private set; } 108 public Scene Scene { get; private set; }
@@ -80,6 +117,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
80 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); 117 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
81 118
82 private IEventQueue m_eqModule; 119 private IEventQueue m_eqModule;
120 private IRegionCombinerModule m_regionCombinerModule;
83 121
84 #region ISharedRegionModule 122 #region ISharedRegionModule
85 123
@@ -116,6 +154,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
116 IConfig transferConfig = source.Configs["EntityTransfer"]; 154 IConfig transferConfig = source.Configs["EntityTransfer"];
117 if (transferConfig != null) 155 if (transferConfig != null)
118 { 156 {
157 DisableInterRegionTeleportCancellation
158 = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false);
159
119 WaitForAgentArrivedAtDestination 160 WaitForAgentArrivedAtDestination
120 = transferConfig.GetBoolean("wait_for_callback", WaitForAgentArrivedAtDestinationDefault); 161 = transferConfig.GetBoolean("wait_for_callback", WaitForAgentArrivedAtDestinationDefault);
121 162
@@ -142,6 +183,60 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
142 183
143 Scene = scene; 184 Scene = scene;
144 185
186 m_interRegionTeleportAttempts =
187 new Stat(
188 "InterRegionTeleportAttempts",
189 "Number of inter-region teleports attempted.",
190 "This does not count attempts which failed due to pre-conditions (e.g. target simulator refused access).\n"
191 + "You can get successfully teleports by subtracting aborts, cancels and teleport failures from this figure.",
192 "",
193 "entitytransfer",
194 Scene.Name,
195 StatType.Push,
196 null,
197 StatVerbosity.Debug);
198
199 m_interRegionTeleportAborts =
200 new Stat(
201 "InterRegionTeleportAborts",
202 "Number of inter-region teleports aborted due to client actions.",
203 "The chief action is simultaneous logout whilst teleporting.",
204 "",
205 "entitytransfer",
206 Scene.Name,
207 StatType.Push,
208 null,
209 StatVerbosity.Debug);
210
211 m_interRegionTeleportCancels =
212 new Stat(
213 "InterRegionTeleportCancels",
214 "Number of inter-region teleports cancelled by the client.",
215 null,
216 "",
217 "entitytransfer",
218 Scene.Name,
219 StatType.Push,
220 null,
221 StatVerbosity.Debug);
222
223 m_interRegionTeleportFailures =
224 new Stat(
225 "InterRegionTeleportFailures",
226 "Number of inter-region teleports that failed due to server/client/network issues.",
227 "This number may not be very helpful in open-grid/hg situations as the network connectivity/quality of destinations is uncontrollable.",
228 "",
229 "entitytransfer",
230 Scene.Name,
231 StatType.Push,
232 null,
233 StatVerbosity.Debug);
234
235 StatsManager.RegisterStat(m_interRegionTeleportAttempts);
236 StatsManager.RegisterStat(m_interRegionTeleportAborts);
237 StatsManager.RegisterStat(m_interRegionTeleportCancels);
238 StatsManager.RegisterStat(m_interRegionTeleportFailures);
239
145 scene.RegisterModuleInterface<IEntityTransferModule>(this); 240 scene.RegisterModuleInterface<IEntityTransferModule>(this);
146 scene.EventManager.OnNewClient += OnNewClient; 241 scene.EventManager.OnNewClient += OnNewClient;
147 } 242 }
@@ -150,12 +245,25 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
150 { 245 {
151 client.OnTeleportHomeRequest += TriggerTeleportHome; 246 client.OnTeleportHomeRequest += TriggerTeleportHome;
152 client.OnTeleportLandmarkRequest += RequestTeleportLandmark; 247 client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
153 client.OnTeleportCancel += TeleportCancel; 248
249 if (!DisableInterRegionTeleportCancellation)
250 client.OnTeleportCancel += OnClientCancelTeleport;
251
252 client.OnConnectionClosed += OnConnectionClosed;
154 } 253 }
155 254
156 public virtual void Close() {} 255 public virtual void Close() {}
157 256
158 public virtual void RemoveRegion(Scene scene) {} 257 public virtual void RemoveRegion(Scene scene)
258 {
259 if (m_Enabled)
260 {
261 StatsManager.DeregisterStat(m_interRegionTeleportAttempts);
262 StatsManager.DeregisterStat(m_interRegionTeleportAborts);
263 StatsManager.DeregisterStat(m_interRegionTeleportCancels);
264 StatsManager.DeregisterStat(m_interRegionTeleportFailures);
265 }
266 }
159 267
160 public virtual void RegionLoaded(Scene scene) 268 public virtual void RegionLoaded(Scene scene)
161 { 269 {
@@ -163,12 +271,33 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
163 return; 271 return;
164 272
165 m_eqModule = Scene.RequestModuleInterface<IEventQueue>(); 273 m_eqModule = Scene.RequestModuleInterface<IEventQueue>();
274 m_regionCombinerModule = Scene.RequestModuleInterface<IRegionCombinerModule>();
166 } 275 }
167 276
168 #endregion 277 #endregion
169 278
170 #region Agent Teleports 279 #region Agent Teleports
171 280
281 private void OnConnectionClosed(IClientAPI client)
282 {
283 if (client.IsLoggingOut)
284 {
285 m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting);
286
287 m_log.DebugFormat(
288 "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout",
289 client.Name, Scene.Name);
290 }
291 }
292
293 private void OnClientCancelTeleport(IClientAPI client)
294 {
295 m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Cancelling);
296
297 m_log.DebugFormat(
298 "[ENTITY TRANSFER MODULE]: Received teleport cancel request from {0} in {1}", client.Name, Scene.Name);
299 }
300
172 public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags) 301 public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
173 { 302 {
174 if (sp.Scene.Permissions.IsGridGod(sp.UUID)) 303 if (sp.Scene.Permissions.IsGridGod(sp.UUID))
@@ -180,13 +309,24 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
180 if (!sp.Scene.Permissions.CanTeleport(sp.UUID)) 309 if (!sp.Scene.Permissions.CanTeleport(sp.UUID))
181 return; 310 return;
182 311
183 // Reset animations; the viewer does that in teleports.
184 sp.Animator.ResetAnimations();
185
186 string destinationRegionName = "(not found)"; 312 string destinationRegionName = "(not found)";
187 313
314 // Record that this agent is in transit so that we can prevent simultaneous requests and do later detection
315 // of whether the destination region completes the teleport.
316 if (!m_entityTransferStateMachine.SetInTransit(sp.UUID))
317 {
318 m_log.DebugFormat(
319 "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2}@{3} - agent is already in transit.",
320 sp.Name, sp.UUID, position, regionHandle);
321
322 return;
323 }
324
188 try 325 try
189 { 326 {
327 // Reset animations; the viewer does that in teleports.
328 sp.Animator.ResetAnimations();
329
190 if (regionHandle == sp.Scene.RegionInfo.RegionHandle) 330 if (regionHandle == sp.Scene.RegionInfo.RegionHandle)
191 { 331 {
192 destinationRegionName = sp.Scene.RegionInfo.RegionName; 332 destinationRegionName = sp.Scene.RegionInfo.RegionName;
@@ -195,12 +335,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
195 } 335 }
196 else // Another region possibly in another simulator 336 else // Another region possibly in another simulator
197 { 337 {
198 GridRegion finalDestination; 338 GridRegion finalDestination = null;
199 TeleportAgentToDifferentRegion( 339 try
200 sp, regionHandle, position, lookAt, teleportFlags, out finalDestination); 340 {
201 341 TeleportAgentToDifferentRegion(
202 if (finalDestination != null) 342 sp, regionHandle, position, lookAt, teleportFlags, out finalDestination);
203 destinationRegionName = finalDestination.RegionName; 343 }
344 finally
345 {
346 if (finalDestination != null)
347 destinationRegionName = finalDestination.RegionName;
348 }
204 } 349 }
205 } 350 }
206 catch (Exception e) 351 catch (Exception e)
@@ -210,11 +355,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
210 sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName, 355 sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName,
211 e.Message, e.StackTrace); 356 e.Message, e.StackTrace);
212 357
213 // Make sure that we clear the in-transit flag so that future teleport attempts don't always fail.
214 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
215
216 sp.ControllingClient.SendTeleportFailed("Internal error"); 358 sp.ControllingClient.SendTeleportFailed("Internal error");
217 } 359 }
360 finally
361 {
362 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
363 }
218 } 364 }
219 365
220 /// <summary> 366 /// <summary>
@@ -230,23 +376,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
230 "[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}", 376 "[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}",
231 sp.Name, position, sp.Scene.RegionInfo.RegionName); 377 sp.Name, position, sp.Scene.RegionInfo.RegionName);
232 378
233 if (!m_entityTransferStateMachine.SetInTransit(sp.UUID))
234 {
235 m_log.DebugFormat(
236 "[ENTITY TRANSFER MODULE]: Ignoring within region teleport request of {0} {1} to {2} - agent is already in transit.",
237 sp.Name, sp.UUID, position);
238
239 return;
240 }
241
242 // Teleport within the same region 379 // Teleport within the same region
243 if (IsOutsideRegion(sp.Scene, position) || position.Z < 0) 380 if (IsOutsideRegion(sp.Scene, position) || position.Z < 0)
244 { 381 {
245 Vector3 emergencyPos = new Vector3(128, 128, 128); 382 Vector3 emergencyPos = new Vector3(128, 128, 128);
246 383
247 m_log.WarnFormat( 384 m_log.WarnFormat(
248 "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", 385 "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2} in {3}. Substituting {4}",
249 position, sp.Name, sp.UUID, emergencyPos); 386 position, sp.Name, sp.UUID, Scene.Name, emergencyPos);
250 387
251 position = emergencyPos; 388 position = emergencyPos;
252 } 389 }
@@ -287,7 +424,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
287 } 424 }
288 425
289 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); 426 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
290 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
291 } 427 }
292 428
293 /// <summary> 429 /// <summary>
@@ -341,7 +477,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
341 // 477 //
342 // This is it 478 // This is it
343 // 479 //
344 DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags); 480 DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags);
345 // 481 //
346 // 482 //
347 // 483 //
@@ -396,27 +532,54 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
396 && Math.Abs(sourceRegion.RegionLocY - destRegion.RegionCoordY) <= MaxTransferDistance; 532 && Math.Abs(sourceRegion.RegionLocY - destRegion.RegionCoordY) <= MaxTransferDistance;
397 } 533 }
398 534
535 /// <summary>
536 /// Wraps DoTeleportInternal() and manages the transfer state.
537 /// </summary>
399 public void DoTeleport( 538 public void DoTeleport(
400 ScenePresence sp, GridRegion reg, GridRegion finalDestination, 539 ScenePresence sp, GridRegion reg, GridRegion finalDestination,
401 Vector3 position, Vector3 lookAt, uint teleportFlags) 540 Vector3 position, Vector3 lookAt, uint teleportFlags)
402 { 541 {
403 // Record that this agent is in transit so that we can prevent simultaneous requests and do later detection 542 // Record that this agent is in transit so that we can prevent simultaneous requests and do later detection
404 // of whether the destination region completes the teleport. 543 // of whether the destination region completes the teleport.
405 m_entityTransferStateMachine.SetInTransit(sp.UUID); 544 if (!m_entityTransferStateMachine.SetInTransit(sp.UUID))
406// if (!m_entityTransferStateMachine.SetInTransit(sp.UUID)) 545 {
407// { 546 m_log.DebugFormat(
408// m_log.DebugFormat( 547 "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.",
409// "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.", 548 sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position);
410// sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position);
411//
412// return;
413// }
414 549
415 if (reg == null || finalDestination == null) 550 return;
551 }
552
553 try
554 {
555 DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags);
556 }
557 catch (Exception e)
558 {
559 m_log.ErrorFormat(
560 "[ENTITY TRANSFER MODULE]: Exception on teleport of {0} from {1}@{2} to {3}@{4}: {5}{6}",
561 sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, finalDestination.RegionName,
562 e.Message, e.StackTrace);
563
564 sp.ControllingClient.SendTeleportFailed("Internal error");
565 }
566 finally
416 { 567 {
417 sp.ControllingClient.SendTeleportFailed("Unable to locate destination");
418 m_entityTransferStateMachine.ResetFromTransit(sp.UUID); 568 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
569 }
570 }
419 571
572 /// <summary>
573 /// Teleports the agent to another region.
574 /// This method doesn't manage the transfer state; the caller must do that.
575 /// </summary>
576 private void DoTeleportInternal(
577 ScenePresence sp, GridRegion reg, GridRegion finalDestination,
578 Vector3 position, Vector3 lookAt, uint teleportFlags)
579 {
580 if (reg == null || finalDestination == null)
581 {
582 sp.ControllingClient.SendTeleportFailed("Unable to locate destination");
420 return; 583 return;
421 } 584 }
422 585
@@ -436,8 +599,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
436 sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY, 599 sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY,
437 MaxTransferDistance)); 600 MaxTransferDistance));
438 601
439 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
440
441 return; 602 return;
442 } 603 }
443 604
@@ -455,7 +616,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
455 if (endPoint == null || endPoint.Address == null) 616 if (endPoint == null || endPoint.Address == null)
456 { 617 {
457 sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); 618 sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
458 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
459 619
460 return; 620 return;
461 } 621 }
@@ -465,19 +625,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
465 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.", 625 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
466 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName); 626 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName);
467 627
468// if (!sp.ValidateAttachments())
469// {
470// sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
471// return;
472// }
473
474 string reason; 628 string reason;
475 string version; 629 string version;
476 if (!Scene.SimulationService.QueryAccess( 630 if (!Scene.SimulationService.QueryAccess(
477 finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason)) 631 finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason))
478 { 632 {
479 sp.ControllingClient.SendTeleportFailed(reason); 633 sp.ControllingClient.SendTeleportFailed(reason);
480 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
481 634
482 m_log.DebugFormat( 635 m_log.DebugFormat(
483 "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}", 636 "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}",
@@ -486,6 +639,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
486 return; 639 return;
487 } 640 }
488 641
642 // Before this point, teleport 'failure' is due to checkable pre-conditions such as whether the target
643 // simulator can be found and is explicitly prepared to allow access. Therefore, we will not count these
644 // as server attempts.
645 m_interRegionTeleportAttempts.Value++;
646
489 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); 647 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version);
490 648
491 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from 649 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
@@ -495,6 +653,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
495 else if (sp.Flying) 653 else if (sp.Flying)
496 teleportFlags |= (uint)TeleportFlags.IsFlying; 654 teleportFlags |= (uint)TeleportFlags.IsFlying;
497 655
656 if (DisableInterRegionTeleportCancellation)
657 teleportFlags |= (uint)TeleportFlags.DisableCancel;
658
498 // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to 659 // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to
499 // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested). 660 // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested).
500 sp.ControllingClient.SendTeleportStart(teleportFlags); 661 sp.ControllingClient.SendTeleportStart(teleportFlags);
@@ -531,11 +692,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
531 } 692 }
532 693
533 // Let's create an agent there if one doesn't exist yet. 694 // Let's create an agent there if one doesn't exist yet.
695 // NOTE: logout will always be false for a non-HG teleport.
534 bool logout = false; 696 bool logout = false;
535 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) 697 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
536 { 698 {
699 m_interRegionTeleportFailures.Value++;
700
537 sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason)); 701 sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason));
538 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
539 702
540 m_log.DebugFormat( 703 m_log.DebugFormat(
541 "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}", 704 "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}",
@@ -544,6 +707,27 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
544 return; 707 return;
545 } 708 }
546 709
710 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
711 {
712 m_interRegionTeleportCancels.Value++;
713
714 m_log.DebugFormat(
715 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
716 sp.Name, finalDestination.RegionName, sp.Scene.Name);
717
718 return;
719 }
720 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
721 {
722 m_interRegionTeleportAborts.Value++;
723
724 m_log.DebugFormat(
725 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
726 sp.Name, finalDestination.RegionName, sp.Scene.Name);
727
728 return;
729 }
730
547 // Past this point we have to attempt clean up if the teleport fails, so update transfer state. 731 // Past this point we have to attempt clean up if the teleport fails, so update transfer state.
548 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); 732 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
549 733
@@ -553,6 +737,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
553 IClientIPEndpoint ipepClient; 737 IClientIPEndpoint ipepClient;
554 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) 738 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
555 { 739 {
740 m_log.DebugFormat(
741 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
742 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
743
556 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); 744 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
557 #region IP Translation for NAT 745 #region IP Translation for NAT
558 // Uses ipepClient above 746 // Uses ipepClient above
@@ -565,11 +753,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
565 753
566 if (m_eqModule != null) 754 if (m_eqModule != null)
567 { 755 {
756 // The EnableSimulator message makes the client establish a connection with the destination
757 // simulator by sending the initial UseCircuitCode UDP packet to the destination containing the
758 // correct circuit code.
568 m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID); 759 m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID);
569 760
570 // ES makes the client send a UseCircuitCode message to the destination, 761 // XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination
571 // which triggers a bunch of things there. 762 // simulator to confirm that it has established communication with the viewer.
572 // So let's wait
573 Thread.Sleep(200); 763 Thread.Sleep(200);
574 764
575 // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears 765 // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears
@@ -580,6 +770,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
580 } 770 }
581 else 771 else
582 { 772 {
773 // XXX: This is a little misleading since we're information the client of its avatar destination,
774 // which may or may not be a neighbour region of the source region. This path is probably little
775 // used anyway (with EQ being the one used). But it is currently being used for test code.
583 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); 776 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
584 } 777 }
585 } 778 }
@@ -597,23 +790,66 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
597 790
598 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); 791 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
599 792
793 // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to
794 // establish th econnection to the destination which makes it return true.
795 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
796 {
797 m_interRegionTeleportAborts.Value++;
798
799 m_log.DebugFormat(
800 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent",
801 sp.Name, finalDestination.RegionName, sp.Scene.Name);
802
803 return;
804 }
805
806 // A common teleport failure occurs when we can send CreateAgent to the
807 // destination region but the viewer cannot establish the connection (e.g. due to network issues between
808 // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then
809 // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail().
600 if (!UpdateAgent(reg, finalDestination, agent, sp)) 810 if (!UpdateAgent(reg, finalDestination, agent, sp))
601 { 811 {
602 // Region doesn't take it 812 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
813 {
814 m_interRegionTeleportAborts.Value++;
815
816 m_log.DebugFormat(
817 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
818 sp.Name, finalDestination.RegionName, sp.Scene.Name);
819
820 return;
821 }
822
603 m_log.WarnFormat( 823 m_log.WarnFormat(
604 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Returning avatar to source region.", 824 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.",
605 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 825 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
606 826
607 Fail(sp, finalDestination, logout); 827 Fail(sp, finalDestination, logout, "Connection between viewer and destination region could not be established.");
608 return; 828 return;
609 } 829 }
610 830
611 sp.ControllingClient.SendTeleportProgress(teleportFlags | (uint)TeleportFlags.DisableCancel, "sending_dest"); 831 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
832 {
833 m_interRegionTeleportCancels.Value++;
834
835 m_log.DebugFormat(
836 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
837 sp.Name, finalDestination.RegionName, sp.Scene.Name);
838
839 CleanupFailedInterRegionTeleport(sp, finalDestination);
840
841 return;
842 }
612 843
613 m_log.DebugFormat( 844 m_log.DebugFormat(
614 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", 845 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
615 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); 846 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
616 847
848 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
849 // where that neighbour simulator could otherwise request a child agent create on the source which then
850 // closes our existing agent which is still signalled as root.
851 sp.IsChildAgent = true;
852
617 if (m_eqModule != null) 853 if (m_eqModule != null)
618 { 854 {
619 m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID); 855 m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID);
@@ -624,19 +860,28 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
624 teleportFlags, capsPath); 860 teleportFlags, capsPath);
625 } 861 }
626 862
627 // Let's set this to true tentatively. This does not trigger OnChildAgent
628 sp.IsChildAgent = true;
629
630 // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which 863 // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
631 // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation 864 // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
632 // that the client contacted the destination before we close things here. 865 // that the client contacted the destination before we close things here.
633 if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID)) 866 if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID))
634 { 867 {
868 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
869 {
870 m_interRegionTeleportAborts.Value++;
871
872 m_log.DebugFormat(
873 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.",
874 sp.Name, finalDestination.RegionName, sp.Scene.Name);
875
876 return;
877 }
878
635 m_log.WarnFormat( 879 m_log.WarnFormat(
636 "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", 880 "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.",
637 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 881 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
638 882
639 Fail(sp, finalDestination, logout); 883 Fail(sp, finalDestination, logout, "Destination region did not signal teleport completion.");
884
640 return; 885 return;
641 } 886 }
642 887
@@ -659,8 +904,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
659 // Now let's make it officially a child agent 904 // Now let's make it officially a child agent
660 sp.MakeChildAgent(); 905 sp.MakeChildAgent();
661 906
662// sp.Scene.CleanDroppedAttachments();
663
664 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 907 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
665 908
666 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 909 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
@@ -680,27 +923,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
680 // now we have a child agent in this region. 923 // now we have a child agent in this region.
681 sp.Reset(); 924 sp.Reset();
682 } 925 }
683
684 // Commented pending deletion since this method no longer appears to do anything at all
685// // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
686// if (sp.Scene.NeedSceneCacheClear(sp.UUID))
687// {
688// m_log.DebugFormat(
689// "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
690// sp.UUID);
691// }
692
693 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
694 } 926 }
695 927
696 protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout) 928 /// <summary>
929 /// Clean up an inter-region teleport that did not complete, either because of simulator failure or cancellation.
930 /// </summary>
931 /// <remarks>
932 /// All operations here must be idempotent so that we can call this method at any point in the teleport process
933 /// up until we send the TeleportFinish event quene event to the viewer.
934 /// <remarks>
935 /// <param name='sp'> </param>
936 /// <param name='finalDestination'></param>
937 protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination)
697 { 938 {
698 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); 939 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
699 940
700 // Client never contacted destination. Let's restore everything back
701 sp.ControllingClient.SendTeleportFailed("Problems connecting to destination.");
702
703 // Fail. Reset it back
704 sp.IsChildAgent = false; 941 sp.IsChildAgent = false;
705 ReInstantiateScripts(sp); 942 ReInstantiateScripts(sp);
706 943
@@ -708,10 +945,26 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
708 945
709 // Finally, kill the agent we just created at the destination. 946 // Finally, kill the agent we just created at the destination.
710 Scene.SimulationService.CloseAgent(finalDestination, sp.UUID); 947 Scene.SimulationService.CloseAgent(finalDestination, sp.UUID);
948 }
711 949
712 sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout); 950 /// <summary>
951 /// Signal that the inter-region teleport failed and perform cleanup.
952 /// </summary>
953 /// <param name='sp'></param>
954 /// <param name='finalDestination'></param>
955 /// <param name='logout'></param>
956 /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param>
957 protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason)
958 {
959 CleanupFailedInterRegionTeleport(sp, finalDestination);
960
961 m_interRegionTeleportFailures.Value++;
713 962
714 m_entityTransferStateMachine.ResetFromTransit(sp.UUID); 963 sp.ControllingClient.SendTeleportFailed(
964 string.Format(
965 "Problems connecting to destination {0}, reason: {1}", finalDestination.RegionName, reason));
966
967 sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout);
715 } 968 }
716 969
717 protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) 970 protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout)
@@ -762,7 +1015,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
762 1015
763 protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY) 1016 protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY)
764 { 1017 {
765 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); 1018 if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
1019 {
1020 Vector2 swCorner, neCorner;
1021 GetMegaregionViewRange(out swCorner, out neCorner);
1022
1023 m_log.DebugFormat(
1024 "[ENTITY TRANSFER MODULE]: Megaregion view of {0} is from {1} to {2} with new agent check for {3},{4}",
1025 Scene.Name, swCorner, neCorner, newRegionX, newRegionY);
1026
1027 return !(newRegionX >= swCorner.X && newRegionX <= neCorner.X && newRegionY >= swCorner.Y && newRegionY <= neCorner.Y);
1028 }
1029 else
1030 {
1031 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY);
1032 }
766 } 1033 }
767 1034
768 protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) 1035 protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg)
@@ -866,6 +1133,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
866 { 1133 {
867 version = String.Empty; 1134 version = String.Empty;
868 newpos = new Vector3(pos.X, pos.Y, pos.Z); 1135 newpos = new Vector3(pos.X, pos.Y, pos.Z);
1136
1137// m_log.DebugFormat(
1138// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
1139
869 uint neighbourx = scene.RegionInfo.RegionLocX; 1140 uint neighbourx = scene.RegionInfo.RegionLocX;
870 uint neighboury = scene.RegionInfo.RegionLocY; 1141 uint neighboury = scene.RegionInfo.RegionLocY;
871 const float boundaryDistance = 1.7f; 1142 const float boundaryDistance = 1.7f;
@@ -995,11 +1266,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
995 return neighbourRegion; 1266 return neighbourRegion;
996 } 1267 }
997 1268
998 private void TeleportCancel(IClientAPI remoteClient)
999 {
1000 m_entityTransferStateMachine.ResetFromTransit(remoteClient.AgentId);
1001 }
1002
1003 public bool Cross(ScenePresence agent, bool isFlying) 1269 public bool Cross(ScenePresence agent, bool isFlying)
1004 { 1270 {
1005 uint x; 1271 uint x;
@@ -1023,16 +1289,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1023 } 1289 }
1024 1290
1025 1291
1026 public delegate void InformClientToInitateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY, 1292 public delegate void InformClientToInitiateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY,
1027 Vector3 position, 1293 Vector3 position,
1028 Scene initiatingScene); 1294 Scene initiatingScene);
1029 1295
1030 private void InformClientToInitateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene) 1296 private void InformClientToInitiateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene)
1031 { 1297 {
1032 1298
1033 // This assumes that we know what our neighbours are. 1299 // This assumes that we know what our neighbours are.
1034 1300
1035 InformClientToInitateTeleportToLocationDelegate d = InformClientToInitiateTeleportToLocationAsync; 1301 InformClientToInitiateTeleportToLocationDelegate d = InformClientToInitiateTeleportToLocationAsync;
1036 d.BeginInvoke(agent, regionX, regionY, position, initiatingScene, 1302 d.BeginInvoke(agent, regionX, regionY, position, initiatingScene,
1037 InformClientToInitiateTeleportToLocationCompleted, 1303 InformClientToInitiateTeleportToLocationCompleted,
1038 d); 1304 d);
@@ -1042,7 +1308,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1042 Scene initiatingScene) 1308 Scene initiatingScene)
1043 { 1309 {
1044 Thread.Sleep(10000); 1310 Thread.Sleep(10000);
1045 1311
1312 m_log.DebugFormat(
1313 "[ENTITY TRANSFER MODULE]: Auto-reteleporting {0} to correct megaregion location {1},{2},{3} from {4}",
1314 agent.Name, regionX, regionY, position, initiatingScene.Name);
1315
1316 agent.Scene.RequestTeleportLocation(
1317 agent.ControllingClient,
1318 Utils.UIntsToLong(regionX * (uint)Constants.RegionSize, regionY * (uint)Constants.RegionSize),
1319 position,
1320 agent.Lookat,
1321 (uint)Constants.TeleportFlags.ViaLocation);
1322
1323 /*
1046 IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>(); 1324 IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>();
1047 if (im != null) 1325 if (im != null)
1048 { 1326 {
@@ -1077,12 +1355,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1077 }); 1355 });
1078 1356
1079 } 1357 }
1358 */
1080 } 1359 }
1081 1360
1082 private void InformClientToInitiateTeleportToLocationCompleted(IAsyncResult iar) 1361 private void InformClientToInitiateTeleportToLocationCompleted(IAsyncResult iar)
1083 { 1362 {
1084 InformClientToInitateTeleportToLocationDelegate icon = 1363 InformClientToInitiateTeleportToLocationDelegate icon =
1085 (InformClientToInitateTeleportToLocationDelegate)iar.AsyncState; 1364 (InformClientToInitiateTeleportToLocationDelegate)iar.AsyncState;
1086 icon.EndInvoke(iar); 1365 icon.EndInvoke(iar);
1087 } 1366 }
1088 1367
@@ -1107,10 +1386,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1107 bool isFlying, string version) 1386 bool isFlying, string version)
1108 { 1387 {
1109 if (!CrossAgentToNewRegionPrep(agent, neighbourRegion)) 1388 if (!CrossAgentToNewRegionPrep(agent, neighbourRegion))
1389 {
1390 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1110 return agent; 1391 return agent;
1392 }
1111 1393
1112 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying)) 1394 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying))
1395 {
1396 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1113 return agent; 1397 return agent;
1398 }
1114 1399
1115 CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, version); 1400 CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, version);
1116 return agent; 1401 return agent;
@@ -1137,9 +1422,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1137 // region doesn't take it 1422 // region doesn't take it
1138 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); 1423 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
1139 1424
1425 m_log.WarnFormat(
1426 "[ENTITY TRANSFER MODULE]: Region {0} would not accept update for agent {1} on cross attempt. Returning to original region.",
1427 neighbourRegion.RegionName, agent.Name);
1428
1140 ReInstantiateScripts(agent); 1429 ReInstantiateScripts(agent);
1141 agent.AddToPhysicalScene(isFlying); 1430 agent.AddToPhysicalScene(isFlying);
1142 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1143 1431
1144 return false; 1432 return false;
1145 } 1433 }
@@ -1576,6 +1864,37 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1576 } 1864 }
1577 1865
1578 /// <summary> 1866 /// <summary>
1867 /// Gets the range considered in view of this megaregion (assuming this is a megaregion).
1868 /// </summary>
1869 /// <remarks>Expressed in 256m units</remarks>
1870 /// <param name='swCorner'></param>
1871 /// <param name='neCorner'></param>
1872 private void GetMegaregionViewRange(out Vector2 swCorner, out Vector2 neCorner)
1873 {
1874 Border[] northBorders = Scene.NorthBorders.ToArray();
1875 Border[] eastBorders = Scene.EastBorders.ToArray();
1876
1877 Vector2 extent = Vector2.Zero;
1878 for (int i = 0; i < eastBorders.Length; i++)
1879 {
1880 extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X;
1881 }
1882 for (int i = 0; i < northBorders.Length; i++)
1883 {
1884 extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y;
1885 }
1886
1887 // Loss of fraction on purpose
1888 extent.X = ((int)extent.X / (int)Constants.RegionSize);
1889 extent.Y = ((int)extent.Y / (int)Constants.RegionSize);
1890
1891 swCorner.X = Scene.RegionInfo.RegionLocX - 1;
1892 swCorner.Y = Scene.RegionInfo.RegionLocY - 1;
1893 neCorner.X = Scene.RegionInfo.RegionLocX + extent.X;
1894 neCorner.Y = Scene.RegionInfo.RegionLocY + extent.Y;
1895 }
1896
1897 /// <summary>
1579 /// Return the list of regions that are considered to be neighbours to the given scene. 1898 /// Return the list of regions that are considered to be neighbours to the given scene.
1580 /// </summary> 1899 /// </summary>
1581 /// <param name="pScene"></param> 1900 /// <param name="pScene"></param>
@@ -1587,15 +1906,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1587 Scene pScene = avatar.Scene; 1906 Scene pScene = avatar.Scene;
1588 RegionInfo m_regionInfo = pScene.RegionInfo; 1907 RegionInfo m_regionInfo = pScene.RegionInfo;
1589 1908
1590 Border[] northBorders = pScene.NorthBorders.ToArray();
1591 Border[] southBorders = pScene.SouthBorders.ToArray();
1592 Border[] eastBorders = pScene.EastBorders.ToArray();
1593 Border[] westBorders = pScene.WestBorders.ToArray();
1594
1595 // Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't 1909 // Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't
1596 // clear what should be done with a "far view" given that megaregions already extended the 1910 // clear what should be done with a "far view" given that megaregions already extended the
1597 // view to include everything in the megaregion 1911 // view to include everything in the megaregion
1598 if (northBorders.Length <= 1 && southBorders.Length <= 1 && eastBorders.Length <= 1 && westBorders.Length <= 1) 1912 if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
1599 { 1913 {
1600 int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance; 1914 int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance;
1601 1915
@@ -1613,27 +1927,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1613 } 1927 }
1614 else 1928 else
1615 { 1929 {
1616 Vector2 extent = Vector2.Zero; 1930 Vector2 swCorner, neCorner;
1617 for (int i = 0; i < eastBorders.Length; i++) 1931 GetMegaregionViewRange(out swCorner, out neCorner);
1618 {
1619 extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X;
1620 }
1621 for (int i = 0; i < northBorders.Length; i++)
1622 {
1623 extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y;
1624 }
1625
1626 // Loss of fraction on purpose
1627 extent.X = ((int)extent.X / (int)Constants.RegionSize) + 1;
1628 extent.Y = ((int)extent.Y / (int)Constants.RegionSize) + 1;
1629
1630 int startX = (int)(pRegionLocX - 1) * (int)Constants.RegionSize;
1631 int startY = (int)(pRegionLocY - 1) * (int)Constants.RegionSize;
1632 1932
1633 int endX = ((int)pRegionLocX + (int)extent.X) * (int)Constants.RegionSize; 1933 List<GridRegion> neighbours
1634 int endY = ((int)pRegionLocY + (int)extent.Y) * (int)Constants.RegionSize; 1934 = pScene.GridService.GetRegionRange(
1935 m_regionInfo.ScopeID,
1936 (int)swCorner.X * (int)Constants.RegionSize,
1937 (int)neCorner.X * (int)Constants.RegionSize,
1938 (int)swCorner.Y * (int)Constants.RegionSize,
1939 (int)neCorner.Y * (int)Constants.RegionSize);
1635 1940
1636 List<GridRegion> neighbours = pScene.GridService.GetRegionRange(m_regionInfo.ScopeID, startX, endX, startY, endY);
1637 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; }); 1941 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
1638 1942
1639 return neighbours; 1943 return neighbours;
@@ -2054,7 +2358,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2054 2358
2055 public bool IsInTransit(UUID id) 2359 public bool IsInTransit(UUID id)
2056 { 2360 {
2057 return m_entityTransferStateMachine.IsInTransit(id); 2361 return m_entityTransferStateMachine.GetAgentTransferState(id) != null;
2058 } 2362 }
2059 2363
2060 protected void ReInstantiateScripts(ScenePresence sp) 2364 protected void ReInstantiateScripts(ScenePresence sp)