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.cs1709
1 files changed, 866 insertions, 843 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 1b4b5e6..2334e0b 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -54,9 +54,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]"; 55 private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]";
56 56
57 public const int DefaultMaxTransferDistance = 4095;
57 public const bool WaitForAgentArrivedAtDestinationDefault = true; 58 public const bool WaitForAgentArrivedAtDestinationDefault = true;
58 59
59 /// <summary> 60 /// <summary>
61 /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer.
62 /// </summary>
63 public int MaxTransferDistance { get; set; }
64
65 /// <summary>
60 /// If true then on a teleport, the source region waits for a callback from the destination region. If 66 /// If true then on a teleport, the source region waits for a callback from the destination region. If
61 /// a callback fails to arrive within a set time then the user is pulled back into the source region. 67 /// a callback fails to arrive within a set time then the user is pulled back into the source region.
62 /// </summary> 68 /// </summary>
@@ -66,9 +72,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
66 /// If true then we ask the viewer to disable teleport cancellation and ignore teleport requests. 72 /// If true then we ask the viewer to disable teleport cancellation and ignore teleport requests.
67 /// </summary> 73 /// </summary>
68 /// <remarks> 74 /// <remarks>
69 /// This is useful in situations where teleport is very likely to always succeed and we want to avoid a 75 /// This is useful in situations where teleport is very likely to always succeed and we want to avoid a
70 /// situation where avatars can be come 'stuck' due to a failed teleport cancellation. Unfortunately, the 76 /// situation where avatars can be come 'stuck' due to a failed teleport cancellation. Unfortunately, the
71 /// nature of the teleport protocol makes it extremely difficult (maybe impossible) to make teleport 77 /// nature of the teleport protocol makes it extremely difficult (maybe impossible) to make teleport
72 /// cancellation consistently suceed. 78 /// cancellation consistently suceed.
73 /// </remarks> 79 /// </remarks>
74 public bool DisableInterRegionTeleportCancellation { get; set; } 80 public bool DisableInterRegionTeleportCancellation { get; set; }
@@ -130,7 +136,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
130 { 136 {
131 if (m_idCache.TryGetValue(pRegionHandle, out m_banUntil)) 137 if (m_idCache.TryGetValue(pRegionHandle, out m_banUntil))
132 { 138 {
133 if (DateTime.Now < m_banUntil) 139 if (DateTime.UtcNow < m_banUntil)
134 { 140 {
135 ret = true; 141 ret = true;
136 } 142 }
@@ -141,13 +147,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
141 // Add this agent in this region as a banned person 147 // Add this agent in this region as a banned person
142 public void Add(ulong pRegionHandle, UUID pAgentID) 148 public void Add(ulong pRegionHandle, UUID pAgentID)
143 { 149 {
150 this.Add(pRegionHandle, pAgentID, 45, 15);
151 }
152
153 public void Add(ulong pRegionHandle, UUID pAgentID, double newTime, double extendTime)
154 {
144 if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache)) 155 if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
145 { 156 {
146 m_idCache = new ExpiringCache<ulong, DateTime>(); 157 m_idCache = new ExpiringCache<ulong, DateTime>();
147 m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(45)); 158 m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(newTime));
148 } 159 }
149 m_idCache.Add(pRegionHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); 160 m_idCache.Add(pRegionHandle, DateTime.UtcNow + TimeSpan.FromSeconds(extendTime), extendTime);
150 } 161 }
162
151 // Remove the agent from the region's banned list 163 // Remove the agent from the region's banned list
152 public void Remove(ulong pRegionHandle, UUID pAgentID) 164 public void Remove(ulong pRegionHandle, UUID pAgentID)
153 { 165 {
@@ -157,10 +169,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
157 } 169 }
158 } 170 }
159 } 171 }
172
160 private BannedRegionCache m_bannedRegionCache = new BannedRegionCache(); 173 private BannedRegionCache m_bannedRegionCache = new BannedRegionCache();
161 174
162 private IEventQueue m_eqModule; 175 private IEventQueue m_eqModule;
163 private IRegionCombinerModule m_regionCombinerModule;
164 176
165 #region ISharedRegionModule 177 #region ISharedRegionModule
166 178
@@ -209,11 +221,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
209 IConfig transferConfig = source.Configs["EntityTransfer"]; 221 IConfig transferConfig = source.Configs["EntityTransfer"];
210 if (transferConfig != null) 222 if (transferConfig != null)
211 { 223 {
212 DisableInterRegionTeleportCancellation 224 DisableInterRegionTeleportCancellation
213 = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false); 225 = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false);
214 226
215 WaitForAgentArrivedAtDestination 227 WaitForAgentArrivedAtDestination
216 = transferConfig.GetBoolean("wait_for_callback", WaitForAgentArrivedAtDestinationDefault); 228 = transferConfig.GetBoolean("wait_for_callback", WaitForAgentArrivedAtDestinationDefault);
229
230 MaxTransferDistance = transferConfig.GetInt("max_distance", DefaultMaxTransferDistance);
231 }
232 else
233 {
234 MaxTransferDistance = DefaultMaxTransferDistance;
217 } 235 }
218 236
219 m_entityTransferStateMachine = new EntityTransferStateMachine(this); 237 m_entityTransferStateMachine = new EntityTransferStateMachine(this);
@@ -232,7 +250,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
232 250
233 Scene = scene; 251 Scene = scene;
234 252
235 m_interRegionTeleportAttempts = 253 m_interRegionTeleportAttempts =
236 new Stat( 254 new Stat(
237 "InterRegionTeleportAttempts", 255 "InterRegionTeleportAttempts",
238 "Number of inter-region teleports attempted.", 256 "Number of inter-region teleports attempted.",
@@ -245,7 +263,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
245 null, 263 null,
246 StatVerbosity.Debug); 264 StatVerbosity.Debug);
247 265
248 m_interRegionTeleportAborts = 266 m_interRegionTeleportAborts =
249 new Stat( 267 new Stat(
250 "InterRegionTeleportAborts", 268 "InterRegionTeleportAborts",
251 "Number of inter-region teleports aborted due to client actions.", 269 "Number of inter-region teleports aborted due to client actions.",
@@ -257,7 +275,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
257 null, 275 null,
258 StatVerbosity.Debug); 276 StatVerbosity.Debug);
259 277
260 m_interRegionTeleportCancels = 278 m_interRegionTeleportCancels =
261 new Stat( 279 new Stat(
262 "InterRegionTeleportCancels", 280 "InterRegionTeleportCancels",
263 "Number of inter-region teleports cancelled by the client.", 281 "Number of inter-region teleports cancelled by the client.",
@@ -269,7 +287,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
269 null, 287 null,
270 StatVerbosity.Debug); 288 StatVerbosity.Debug);
271 289
272 m_interRegionTeleportFailures = 290 m_interRegionTeleportFailures =
273 new Stat( 291 new Stat(
274 "InterRegionTeleportFailures", 292 "InterRegionTeleportFailures",
275 "Number of inter-region teleports that failed due to server/client/network issues.", 293 "Number of inter-region teleports that failed due to server/client/network issues.",
@@ -303,7 +321,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
303 321
304 public virtual void Close() {} 322 public virtual void Close() {}
305 323
306 public virtual void RemoveRegion(Scene scene) 324 public virtual void RemoveRegion(Scene scene)
307 { 325 {
308 if (m_Enabled) 326 if (m_Enabled)
309 { 327 {
@@ -320,7 +338,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
320 return; 338 return;
321 339
322 m_eqModule = Scene.RequestModuleInterface<IEventQueue>(); 340 m_eqModule = Scene.RequestModuleInterface<IEventQueue>();
323 m_regionCombinerModule = Scene.RequestModuleInterface<IRegionCombinerModule>();
324 } 341 }
325 342
326 #endregion 343 #endregion
@@ -332,7 +349,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
332 if (client.IsLoggingOut && m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting)) 349 if (client.IsLoggingOut && m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting))
333 { 350 {
334 m_log.DebugFormat( 351 m_log.DebugFormat(
335 "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout", 352 "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout",
336 client.Name, Scene.Name); 353 client.Name, Scene.Name);
337 } 354 }
338 } 355 }
@@ -354,7 +371,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
354 teleportFlags |= (uint)TeleportFlags.Godlike; 371 teleportFlags |= (uint)TeleportFlags.Godlike;
355 } 372 }
356 373
357 if (!sp.Scene.Permissions.CanTeleport(sp.UUID)) 374 else if (!sp.Scene.Permissions.CanTeleport(sp.UUID))
358 return; 375 return;
359 376
360 string destinationRegionName = "(not found)"; 377 string destinationRegionName = "(not found)";
@@ -374,17 +391,27 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
374 391
375 try 392 try
376 { 393 {
377 // Reset animations; the viewer does that in teleports.
378 sp.Animator.ResetAnimations();
379 394
380 if (regionHandle == sp.Scene.RegionInfo.RegionHandle) 395 if (regionHandle == sp.Scene.RegionInfo.RegionHandle)
381 { 396 {
397 if(!sp.AllowMovement)
398 {
399 sp.ControllingClient.SendTeleportFailed("You are frozen");
400 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
401 return;
402 }
403
404 // Reset animations; the viewer does that in teleports.
405 sp.Animator.ResetAnimations();
382 destinationRegionName = sp.Scene.RegionInfo.RegionName; 406 destinationRegionName = sp.Scene.RegionInfo.RegionName;
383 407
384 TeleportAgentWithinRegion(sp, position, lookAt, teleportFlags); 408 TeleportAgentWithinRegion(sp, position, lookAt, teleportFlags);
385 } 409 }
386 else // Another region possibly in another simulator 410 else // Another region possibly in another simulator
387 { 411 {
412 // Reset animations; the viewer does that in teleports.
413 sp.Animator.ResetAnimations();
414
388 GridRegion finalDestination = null; 415 GridRegion finalDestination = null;
389 try 416 try
390 { 417 {
@@ -400,12 +427,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
400 } 427 }
401 catch (Exception e) 428 catch (Exception e)
402 { 429 {
430
403 m_log.ErrorFormat( 431 m_log.ErrorFormat(
404 "[ENTITY TRANSFER MODULE]: Exception on teleport of {0} from {1}@{2} to {3}@{4}: {5}{6}", 432 "[ENTITY TRANSFER MODULE]: Exception on teleport of {0} from {1}@{2} to {3}@{4}: {5}{6}",
405 sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName, 433 sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName,
406 e.Message, e.StackTrace); 434 e.Message, e.StackTrace);
407 435 if(sp != null && sp.ControllingClient != null && !sp.IsDeleted)
408 sp.ControllingClient.SendTeleportFailed("Internal error"); 436 sp.ControllingClient.SendTeleportFailed("Internal error");
409 } 437 }
410 finally 438 finally
411 { 439 {
@@ -438,17 +466,25 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
438 position = emergencyPos; 466 position = emergencyPos;
439 } 467 }
440 468
469 // Check Default Location (Also See ScenePresence.CompleteMovement)
470 if (position.X == 128f && position.Y == 128f && position.Z == 22.5f)
471 position = sp.Scene.RegionInfo.DefaultLandingPoint;
472
441 // TODO: Get proper AVG Height 473 // TODO: Get proper AVG Height
442 float localAVHeight = 1.56f; 474 float localHalfAVHeight = 0.8f;
475 if (sp.Appearance != null)
476 localHalfAVHeight = sp.Appearance.AvatarHeight / 2;
477
443 float posZLimit = 22; 478 float posZLimit = 22;
444 479
445 // TODO: Check other Scene HeightField 480 // TODO: Check other Scene HeightField
446 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y]; 481 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
447 482
448 float newPosZ = posZLimit + localAVHeight; 483 posZLimit += localHalfAVHeight + 0.1f;
449 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 484
485 if ((position.Z < posZLimit) && !(Single.IsInfinity(posZLimit) || Single.IsNaN(posZLimit)))
450 { 486 {
451 position.Z = newPosZ; 487 position.Z = posZLimit;
452 } 488 }
453 489
454 if (sp.Flying) 490 if (sp.Flying)
@@ -457,9 +493,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
457 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); 493 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
458 494
459 sp.ControllingClient.SendTeleportStart(teleportFlags); 495 sp.ControllingClient.SendTeleportStart(teleportFlags);
496 lookAt.Z = 0f;
497
498 if(Math.Abs(lookAt.X) < 0.01f && Math.Abs(lookAt.Y) < 0.01f)
499 {
500 lookAt.X = 1.0f;
501 lookAt.Y = 0;
502 }
460 503
461 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags); 504 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
462 sp.TeleportFlags = (Constants.TeleportFlags)teleportFlags; 505 sp.TeleportFlags = (Constants.TeleportFlags)teleportFlags;
506 sp.RotateToLookAt(lookAt);
463 sp.Velocity = Vector3.Zero; 507 sp.Velocity = Vector3.Zero;
464 sp.Teleport(position); 508 sp.Teleport(position);
465 509
@@ -494,15 +538,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
494 { 538 {
495 string homeURI = Scene.GetAgentHomeURI(sp.ControllingClient.AgentId); 539 string homeURI = Scene.GetAgentHomeURI(sp.ControllingClient.AgentId);
496 540
497 string message; 541 string reason = String.Empty;
498 finalDestination = GetFinalDestination(reg, sp.ControllingClient.AgentId, homeURI, out message); 542 finalDestination = GetFinalDestination(reg, sp.ControllingClient.AgentId, homeURI, out reason);
499 543
500 if (finalDestination == null) 544 if (finalDestination == null)
501 { 545 {
502 m_log.WarnFormat( "{0} Final destination is having problems. Unable to teleport {1} {2}: {3}", 546 m_log.WarnFormat( "{0} Final destination is having problems. Unable to teleport {1} {2}: {3}",
503 LogHeader, sp.Name, sp.UUID, message); 547 LogHeader, sp.Name, sp.UUID, reason);
504 548
505 sp.ControllingClient.SendTeleportFailed(message); 549 sp.ControllingClient.SendTeleportFailed(reason);
506 return; 550 return;
507 } 551 }
508 552
@@ -515,17 +559,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
515 return; 559 return;
516 } 560 }
517 561
518 // Validate assorted conditions
519 string reason = string.Empty;
520 if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason)) 562 if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason))
521 { 563 {
522 sp.ControllingClient.SendTeleportFailed(reason); 564 sp.ControllingClient.SendTeleportFailed(reason);
523 return; 565 return;
524 } 566 }
525 567
526 if (message != null)
527 sp.ControllingClient.SendAgentAlertMessage(message, true);
528
529 // 568 //
530 // This is it 569 // This is it
531 // 570 //
@@ -547,9 +586,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
547 Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY); 586 Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY);
548 587
549 MapBlockData block = new MapBlockData(); 588 MapBlockData block = new MapBlockData();
550 block.X = (ushort)regX; 589 block.X = (ushort)(regX);
551 block.Y = (ushort)regY; 590 block.Y = (ushort)(regY);
552 block.Access = (byte)SimAccess.Down; 591 block.Access = (byte)SimAccess.Down; // == not there
553 592
554 List<MapBlockData> blocks = new List<MapBlockData>(); 593 List<MapBlockData> blocks = new List<MapBlockData>();
555 blocks.Add(block); 594 blocks.Add(block);
@@ -565,12 +604,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
565 uint x = 0, y = 0; 604 uint x = 0, y = 0;
566 Util.RegionHandleToWorldLoc(regionHandle, out x, out y); 605 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
567 606
607 GridRegion reg;
608
609 // handle legacy HG. linked regions are mapped into y = 0 and have no size information
610 // so we can only search by base handle
611 if( y == 0)
612 {
613 reg = gridService.GetRegionByPosition(scope, (int)x, (int)y);
614 return reg;
615 }
616
568 // Compute the world location we're teleporting to 617 // Compute the world location we're teleporting to
569 double worldX = (double)x + position.X; 618 double worldX = (double)x + position.X;
570 double worldY = (double)y + position.Y; 619 double worldY = (double)y + position.Y;
571 620
572 // Find the region that contains the position 621 // Find the region that contains the position
573 GridRegion reg = GetRegionContainingWorldLocation(gridService, scope, worldX, worldY); 622 reg = GetRegionContainingWorldLocation(gridService, scope, worldX, worldY);
574 623
575 if (reg != null) 624 if (reg != null)
576 { 625 {
@@ -589,6 +638,28 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
589 return true; 638 return true;
590 } 639 }
591 640
641 /// <summary>
642 /// Determines whether this instance is within the max transfer distance.
643 /// </summary>
644 /// <param name="sourceRegion"></param>
645 /// <param name="destRegion"></param>
646 /// <returns>
647 /// <c>true</c> if this instance is within max transfer distance; otherwise, <c>false</c>.
648 /// </returns>
649 private bool IsWithinMaxTeleportDistance(RegionInfo sourceRegion, GridRegion destRegion)
650 {
651 if(MaxTransferDistance == 0)
652 return true;
653
654// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY);
655//
656// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}",
657// destRegionX, destRegionY, finalDestination.RegionID, finalDestination.ServerURI);
658
659 // Insanely, RegionLoc on RegionInfo is the 256m map co-ord whilst GridRegion.RegionLoc is the raw meters position.
660 return Math.Abs(sourceRegion.RegionLocX - destRegion.RegionCoordX) <= MaxTransferDistance
661 && Math.Abs(sourceRegion.RegionLocY - destRegion.RegionCoordY) <= MaxTransferDistance;
662 }
592 663
593 /// <summary> 664 /// <summary>
594 /// Wraps DoTeleportInternal() and manages the transfer state. 665 /// Wraps DoTeleportInternal() and manages the transfer state.
@@ -607,7 +678,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
607 sp.ControllingClient.SendTeleportFailed("Agent is already in transit."); 678 sp.ControllingClient.SendTeleportFailed("Agent is already in transit.");
608 return; 679 return;
609 } 680 }
610 681
611 try 682 try
612 { 683 {
613 DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags); 684 DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags);
@@ -650,10 +721,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
650 721
651 RegionInfo sourceRegion = sp.Scene.RegionInfo; 722 RegionInfo sourceRegion = sp.Scene.RegionInfo;
652 723
724 if (!IsWithinMaxTeleportDistance(sourceRegion, finalDestination))
725 {
726 sp.ControllingClient.SendTeleportFailed(
727 string.Format(
728 "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way",
729 finalDestination.RegionName, finalDestination.RegionCoordX, finalDestination.RegionCoordY,
730 sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY,
731 MaxTransferDistance));
653 732
654 uint newRegionX, newRegionY, oldRegionX, oldRegionY; 733 return;
655 Util.RegionHandleToRegionLoc(reg.RegionHandle, out newRegionX, out newRegionY); 734 }
656 Util.RegionHandleToRegionLoc(sp.Scene.RegionInfo.RegionHandle, out oldRegionX, out oldRegionY);
657 735
658 ulong destinationHandle = finalDestination.RegionHandle; 736 ulong destinationHandle = finalDestination.RegionHandle;
659 737
@@ -663,8 +741,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
663 IPEndPoint endPoint = finalDestination.ExternalEndPoint; 741 IPEndPoint endPoint = finalDestination.ExternalEndPoint;
664 if (endPoint == null || endPoint.Address == null) 742 if (endPoint == null || endPoint.Address == null)
665 { 743 {
666 sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); 744 sp.ControllingClient.SendTeleportFailed("Could not resolve destination Address");
667
668 return; 745 return;
669 } 746 }
670 747
@@ -694,7 +771,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
694 m_interRegionTeleportAttempts.Value++; 771 m_interRegionTeleportAttempts.Value++;
695 772
696 m_log.DebugFormat( 773 m_log.DebugFormat(
697 "[ENTITY TRANSFER MODULE]: {0} transfer protocol version to {1} is {2} / {3}", 774 "[ENTITY TRANSFER MODULE]: {0} transfer protocol version to {1} is {2} / {3}",
698 sp.Scene.Name, finalDestination.RegionName, ctx.OutboundVersion, ctx.InboundVersion); 775 sp.Scene.Name, finalDestination.RegionName, ctx.OutboundVersion, ctx.InboundVersion);
699 776
700 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from 777 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
@@ -704,27 +781,25 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
704 else if (sp.Flying) 781 else if (sp.Flying)
705 teleportFlags |= (uint)TeleportFlags.IsFlying; 782 teleportFlags |= (uint)TeleportFlags.IsFlying;
706 783
784 sp.IsInLocalTransit = finalDestination.RegionLocY != 0; // HG
785 sp.IsInTransit = true;
786
787
707 if (DisableInterRegionTeleportCancellation) 788 if (DisableInterRegionTeleportCancellation)
708 teleportFlags |= (uint)TeleportFlags.DisableCancel; 789 teleportFlags |= (uint)TeleportFlags.DisableCancel;
709 790
710 // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to 791 // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to
711 // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested). 792 // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested).
712 sp.ControllingClient.SendTeleportStart(teleportFlags); 793 sp.ControllingClient.SendTeleportStart(teleportFlags);
713 794
714 // the avatar.Close below will clear the child region list. We need this below for (possibly)
715 // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
716 //List<ulong> childRegions = avatar.KnownRegionHandles;
717 // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
718 // failure at this point (unlike a border crossing failure). So perhaps this can never fail
719 // once we reach here...
720 //avatar.Scene.RemoveCapsHandler(avatar.UUID);
721
722 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 795 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
723 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo(); 796 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
724 agentCircuit.startpos = position; 797 agentCircuit.startpos = position;
725 agentCircuit.child = true; 798 agentCircuit.child = true;
799
726 agentCircuit.Appearance = new AvatarAppearance(); 800 agentCircuit.Appearance = new AvatarAppearance();
727 agentCircuit.Appearance.PackLegacyWearables = true; 801 agentCircuit.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
802
728 if (currentAgentCircuit != null) 803 if (currentAgentCircuit != null)
729 { 804 {
730 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs; 805 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
@@ -735,36 +810,64 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
735 agentCircuit.Id0 = currentAgentCircuit.Id0; 810 agentCircuit.Id0 = currentAgentCircuit.Id0;
736 } 811 }
737 812
738 // if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) 813 uint newRegionX, newRegionY, oldRegionX, oldRegionY;
739 float dist = (float)Math.Max(sp.Scene.DefaultDrawDistance, 814 Util.RegionHandleToRegionLoc(destinationHandle, out newRegionX, out newRegionY);
740 (float)Math.Max(sp.Scene.RegionInfo.RegionSizeX, sp.Scene.RegionInfo.RegionSizeY)); 815 Util.RegionHandleToRegionLoc(sourceRegion.RegionHandle, out oldRegionX, out oldRegionY);
741 if (NeedsNewAgent(dist, oldRegionX, newRegionX, oldRegionY, newRegionY)) 816 int oldSizeX = (int)sourceRegion.RegionSizeX;
817 int oldSizeY = (int)sourceRegion.RegionSizeY;
818 int newSizeX = finalDestination.RegionSizeX;
819 int newSizeY = finalDestination.RegionSizeY;
820
821 bool OutSideViewRange = NeedsNewAgent(sp.RegionViewDistance, oldRegionX, newRegionX, oldRegionY, newRegionY,
822 oldSizeX, oldSizeY, newSizeX, newSizeY);
823
824 if (OutSideViewRange)
742 { 825 {
743 // brand new agent, let's create a new caps seed 826 m_log.DebugFormat(
827 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} size {3},{4} needs new child agent for agent {5} from {6}",
828 finalDestination.RegionName, newRegionX, newRegionY,newSizeX, newSizeY, sp.Name, Scene.Name);
829
830 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
744 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 831 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
745 } 832 }
833 else
834 {
835 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
836 if (agentCircuit.CapsPath == null)
837 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
838 }
746 839
747 // We're going to fallback to V1 if the destination gives us anything smaller than 0.2 840 // We're going to fallback to V1 if the destination gives us anything smaller than 0.2
748 if (ctx.OutboundVersion >= 0.2f) 841 if (ctx.OutboundVersion >= 0.2f)
749 TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, ctx, out reason); 842 TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, OutSideViewRange , ctx, out reason);
750 else 843 else
751 TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, ctx, out reason); 844 TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, OutSideViewRange, ctx, out reason);
752 } 845 }
753 846
754 private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination, 847 private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
755 IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, EntityTransferContext ctx, out string reason) 848 IPEndPoint endPoint, uint teleportFlags, bool OutSideViewRange, EntityTransferContext ctx, out string reason)
756 { 849 {
757 ulong destinationHandle = finalDestination.RegionHandle; 850 ulong destinationHandle = finalDestination.RegionHandle;
758 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 851 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
759 852
760 m_log.DebugFormat( 853 m_log.DebugFormat(
761 "[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}", 854 "[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}",
762 sp.Name, Scene.Name, finalDestination.RegionName); 855 sp.Name, Scene.Name, finalDestination.RegionName);
763 856
764 // Let's create an agent there if one doesn't exist yet. 857 string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
858 List<ulong> childRegionsToClose = sp.GetChildAgentsToClose(destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY);
859 if(agentCircuit.ChildrenCapSeeds != null)
860 {
861 foreach(ulong handler in childRegionsToClose)
862 {
863 agentCircuit.ChildrenCapSeeds.Remove(handler);
864 }
865 }
866
867 // Let's create an agent there if one doesn't exist yet.
765 // NOTE: logout will always be false for a non-HG teleport. 868 // NOTE: logout will always be false for a non-HG teleport.
766 bool logout = false; 869 bool logout = false;
767 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) 870 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, ctx, out reason, out logout))
768 { 871 {
769 m_interRegionTeleportFailures.Value++; 872 m_interRegionTeleportFailures.Value++;
770 873
@@ -773,7 +876,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
773 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason); 876 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);
774 877
775 sp.ControllingClient.SendTeleportFailed(reason); 878 sp.ControllingClient.SendTeleportFailed(reason);
776 879 sp.IsInTransit = false;
777 return; 880 return;
778 } 881 }
779 882
@@ -784,7 +887,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
784 m_log.DebugFormat( 887 m_log.DebugFormat(
785 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", 888 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
786 sp.Name, finalDestination.RegionName, sp.Scene.Name); 889 sp.Name, finalDestination.RegionName, sp.Scene.Name);
787 890 sp.IsInTransit = false;
788 return; 891 return;
789 } 892 }
790 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 893 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
@@ -794,7 +897,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
794 m_log.DebugFormat( 897 m_log.DebugFormat(
795 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.", 898 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
796 sp.Name, finalDestination.RegionName, sp.Scene.Name); 899 sp.Name, finalDestination.RegionName, sp.Scene.Name);
797 900 sp.IsInTransit = false;
798 return; 901 return;
799 } 902 }
800 903
@@ -802,28 +905,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
802 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); 905 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
803 906
804 // OK, it got this agent. Let's close some child agents 907 // OK, it got this agent. Let's close some child agents
805 sp.CloseChildAgents(newRegionX, newRegionY);
806 908
807 IClientIPEndpoint ipepClient; 909 if (OutSideViewRange)
808 string capsPath = String.Empty;
809 float dist = (float)Math.Max(sp.Scene.DefaultDrawDistance,
810 (float)Math.Max(sp.Scene.RegionInfo.RegionSizeX, sp.Scene.RegionInfo.RegionSizeY));
811 if (NeedsNewAgent(dist, oldRegionX, newRegionX, oldRegionY, newRegionY))
812 { 910 {
813 m_log.DebugFormat(
814 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
815 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
816
817 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
818 #region IP Translation for NAT
819 // Uses ipepClient above
820 if (sp.ClientView.TryGet(out ipepClient))
821 {
822 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
823 }
824 #endregion
825 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
826
827 if (m_eqModule != null) 911 if (m_eqModule != null)
828 { 912 {
829 // The EnableSimulator message makes the client establish a connection with the destination 913 // The EnableSimulator message makes the client establish a connection with the destination
@@ -853,22 +937,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
853 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); 937 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
854 } 938 }
855 } 939 }
856 else
857 {
858 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
859 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
860 }
861 940
862 // Let's send a full update of the agent. This is a synchronous call. 941 // Let's send a full update of the agent. This is a synchronous call.
863 AgentData agent = new AgentData(); 942 AgentData agent = new AgentData();
864 sp.CopyTo(agent); 943 sp.CopyTo(agent,false);
865 if (ctx.OutboundVersion < 0.5f) 944
866 agent.Appearance.PackLegacyWearables = true; 945 if ((teleportFlags & (uint)TeleportFlags.IsFlying) != 0)
946 agent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
947
867 agent.Position = agentCircuit.startpos; 948 agent.Position = agentCircuit.startpos;
868 SetCallbackURL(agent, sp.Scene.RegionInfo); 949 SetCallbackURL(agent, sp.Scene.RegionInfo);
869 950
870 951 // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to
871 // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to
872 // establish th econnection to the destination which makes it return true. 952 // establish th econnection to the destination which makes it return true.
873 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 953 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
874 { 954 {
@@ -877,15 +957,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
877 m_log.DebugFormat( 957 m_log.DebugFormat(
878 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent", 958 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent",
879 sp.Name, finalDestination.RegionName, sp.Scene.Name); 959 sp.Name, finalDestination.RegionName, sp.Scene.Name);
880 960 sp.IsInTransit = false;
881 return; 961 return;
882 } 962 }
883 963
884 // A common teleport failure occurs when we can send CreateAgent to the 964 // A common teleport failure occurs when we can send CreateAgent to the
885 // destination region but the viewer cannot establish the connection (e.g. due to network issues between 965 // destination region but the viewer cannot establish the connection (e.g. due to network issues between
886 // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then 966 // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then
887 // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail(). 967 // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail().
888 if (!UpdateAgent(reg, finalDestination, agent, sp)) 968 if (!UpdateAgent(reg, finalDestination, agent, sp, ctx))
889 { 969 {
890 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 970 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
891 { 971 {
@@ -894,7 +974,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
894 m_log.DebugFormat( 974 m_log.DebugFormat(
895 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.", 975 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
896 sp.Name, finalDestination.RegionName, sp.Scene.Name); 976 sp.Name, finalDestination.RegionName, sp.Scene.Name);
897 977 sp.IsInTransit = false;
898 return; 978 return;
899 } 979 }
900 980
@@ -903,6 +983,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
903 sp.Name, finalDestination.RegionName, sp.Scene.Name); 983 sp.Name, finalDestination.RegionName, sp.Scene.Name);
904 984
905 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); 985 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
986 sp.IsInTransit = false;
906 return; 987 return;
907 } 988 }
908 989
@@ -915,7 +996,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
915 sp.Name, finalDestination.RegionName, sp.Scene.Name); 996 sp.Name, finalDestination.RegionName, sp.Scene.Name);
916 997
917 CleanupFailedInterRegionTeleport(sp, currentAgentCircuit.SessionID.ToString(), finalDestination); 998 CleanupFailedInterRegionTeleport(sp, currentAgentCircuit.SessionID.ToString(), finalDestination);
918 999 sp.IsInTransit = false;
919 return; 1000 return;
920 } 1001 }
921 1002
@@ -924,7 +1005,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
924 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); 1005 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
925 1006
926 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator, 1007 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
927 // where that neighbour simulator could otherwise request a child agent create on the source which then 1008 // where that neighbour simulator could otherwise request a child agent create on the source which then
928 // closes our existing agent which is still signalled as root. 1009 // closes our existing agent which is still signalled as root.
929 sp.IsChildAgent = true; 1010 sp.IsChildAgent = true;
930 1011
@@ -952,7 +1033,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
952 m_log.DebugFormat( 1033 m_log.DebugFormat(
953 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.", 1034 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.",
954 sp.Name, finalDestination.RegionName, sp.Scene.Name); 1035 sp.Name, finalDestination.RegionName, sp.Scene.Name);
955 1036 sp.IsInTransit = false;
956 return; 1037 return;
957 } 1038 }
958 1039
@@ -961,12 +1042,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
961 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 1042 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
962 1043
963 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Destination region did not signal teleport completion."); 1044 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Destination region did not signal teleport completion.");
964 1045 sp.IsInTransit = false;
965 return; 1046 return;
966 } 1047 }
967 1048
968 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
969
970/* 1049/*
971 // TODO: This may be 0.6. Check if still needed 1050 // TODO: This may be 0.6. Check if still needed
972 // For backwards compatibility 1051 // For backwards compatibility
@@ -978,18 +1057,26 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
978 } 1057 }
979*/ 1058*/
980 1059
981 // May need to logout or other cleanup 1060 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
1061
1062 if(logout)
1063 sp.closeAllChildAgents();
1064 else
1065 sp.CloseChildAgents(childRegionsToClose);
1066
1067 // call HG hook
982 AgentHasMovedAway(sp, logout); 1068 AgentHasMovedAway(sp, logout);
983 1069
984 // Well, this is it. The agent is over there. 1070 sp.HasMovedAway(!(OutSideViewRange || logout));
985 KillEntity(sp.Scene, sp.LocalId);
986 1071
987 // Now let's make it officially a child agent 1072// ulong sourceRegionHandle = sp.RegionHandle;
988 sp.MakeChildAgent(); 1073
1074 // Now let's make it officially a child agent
1075 sp.MakeChildAgent(destinationHandle);
989 1076
990 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 1077 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
991 1078
992 if (NeedsClosing(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 1079 if (NeedsClosing(reg, OutSideViewRange))
993 { 1080 {
994 if (!sp.Scene.IncomingPreCloseClient(sp)) 1081 if (!sp.Scene.IncomingPreCloseClient(sp))
995 return; 1082 return;
@@ -1001,26 +1088,32 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1001 // This sleep can be increased if necessary. However, whilst it's active, 1088 // This sleep can be increased if necessary. However, whilst it's active,
1002 // an agent cannot teleport back to this region if it has teleported away. 1089 // an agent cannot teleport back to this region if it has teleported away.
1003 Thread.Sleep(2000); 1090 Thread.Sleep(2000);
1004
1005 sp.Scene.CloseAgent(sp.UUID, false); 1091 sp.Scene.CloseAgent(sp.UUID, false);
1006 } 1092 }
1007 else 1093 sp.IsInTransit = false;
1008 {
1009 // now we have a child agent in this region.
1010 sp.Reset();
1011 }
1012 } 1094 }
1013 1095
1014 private void TransferAgent_V2(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination, 1096 private void TransferAgent_V2(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
1015 IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, EntityTransferContext ctx, out string reason) 1097 IPEndPoint endPoint, uint teleportFlags, bool OutSideViewRange, EntityTransferContext ctx, out string reason)
1016 { 1098 {
1017 ulong destinationHandle = finalDestination.RegionHandle; 1099 ulong destinationHandle = finalDestination.RegionHandle;
1018 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1019 1100
1020 // Let's create an agent there if one doesn't exist yet. 1101 List<ulong> childRegionsToClose = sp.GetChildAgentsToClose(destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY);
1102
1103 if(agentCircuit.ChildrenCapSeeds != null)
1104 {
1105 foreach(ulong handler in childRegionsToClose)
1106 {
1107 agentCircuit.ChildrenCapSeeds.Remove(handler);
1108 }
1109 }
1110
1111 string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);;
1112
1113 // Let's create an agent there if one doesn't exist yet.
1021 // NOTE: logout will always be false for a non-HG teleport. 1114 // NOTE: logout will always be false for a non-HG teleport.
1022 bool logout = false; 1115 bool logout = false;
1023 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) 1116 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, ctx, out reason, out logout))
1024 { 1117 {
1025 m_interRegionTeleportFailures.Value++; 1118 m_interRegionTeleportFailures.Value++;
1026 1119
@@ -1029,7 +1122,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1029 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason); 1122 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);
1030 1123
1031 sp.ControllingClient.SendTeleportFailed(reason); 1124 sp.ControllingClient.SendTeleportFailed(reason);
1032 1125 sp.IsInTransit = false;
1033 return; 1126 return;
1034 } 1127 }
1035 1128
@@ -1041,6 +1134,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1041 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", 1134 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
1042 sp.Name, finalDestination.RegionName, sp.Scene.Name); 1135 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1043 1136
1137 sp.IsInTransit = false;
1044 return; 1138 return;
1045 } 1139 }
1046 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 1140 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
@@ -1051,40 +1145,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1051 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.", 1145 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
1052 sp.Name, finalDestination.RegionName, sp.Scene.Name); 1146 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1053 1147
1148 sp.IsInTransit = false;
1054 return; 1149 return;
1055 } 1150 }
1056 1151
1057 // Past this point we have to attempt clean up if the teleport fails, so update transfer state. 1152 // Past this point we have to attempt clean up if the teleport fails, so update transfer state.
1058 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); 1153 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
1059 1154
1060 IClientIPEndpoint ipepClient;
1061 string capsPath = String.Empty;
1062 float dist = (float)Math.Max(sp.Scene.DefaultDrawDistance,
1063 (float)Math.Max(sp.Scene.RegionInfo.RegionSizeX, sp.Scene.RegionInfo.RegionSizeY));
1064 if (NeedsNewAgent(dist, oldRegionX, newRegionX, oldRegionY, newRegionY))
1065 {
1066 m_log.DebugFormat(
1067 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}",
1068 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
1069
1070 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
1071 #region IP Translation for NAT
1072 // Uses ipepClient above
1073 if (sp.ClientView.TryGet(out ipepClient))
1074 {
1075 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
1076 }
1077 #endregion
1078 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1079 }
1080 else
1081 {
1082 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
1083 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1084 }
1085
1086 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator, 1155 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
1087 // where that neighbour simulator could otherwise request a child agent create on the source which then 1156 // where that neighbour simulator could otherwise request a child agent create on the source which then
1088 // closes our existing agent which is still signalled as root. 1157 // closes our existing agent which is still signalled as root.
1089 //sp.IsChildAgent = true; 1158 //sp.IsChildAgent = true;
1090 1159
@@ -1100,13 +1169,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1100 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", 1169 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
1101 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); 1170 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
1102 1171
1103 // Let's send a full update of the agent. 1172 // Let's send a full update of the agent.
1104 AgentData agent = new AgentData(); 1173 AgentData agent = new AgentData();
1105 sp.CopyTo(agent); 1174 sp.CopyTo(agent,false);
1106 if (ctx.OutboundVersion < 0.5f)
1107 agent.Appearance.PackLegacyWearables = true;
1108 agent.Position = agentCircuit.startpos; 1175 agent.Position = agentCircuit.startpos;
1176
1177 if ((teleportFlags & (uint)TeleportFlags.IsFlying) != 0)
1178 agent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
1179
1109 agent.SenderWantsToWaitForRoot = true; 1180 agent.SenderWantsToWaitForRoot = true;
1181
1110 //SetCallbackURL(agent, sp.Scene.RegionInfo); 1182 //SetCallbackURL(agent, sp.Scene.RegionInfo);
1111 1183
1112 // Reset the do not close flag. This must be done before the destination opens child connections (here 1184 // Reset the do not close flag. This must be done before the destination opens child connections (here
@@ -1118,7 +1190,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1118 // Send the Update. If this returns true, we know the client has contacted the destination 1190 // Send the Update. If this returns true, we know the client has contacted the destination
1119 // via CompleteMovementIntoRegion, so we can let go. 1191 // via CompleteMovementIntoRegion, so we can let go.
1120 // If it returns false, something went wrong, and we need to abort. 1192 // If it returns false, something went wrong, and we need to abort.
1121 if (!UpdateAgent(reg, finalDestination, agent, sp)) 1193 if (!UpdateAgent(reg, finalDestination, agent, sp, ctx))
1122 { 1194 {
1123 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 1195 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
1124 { 1196 {
@@ -1127,7 +1199,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1127 m_log.DebugFormat( 1199 m_log.DebugFormat(
1128 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.", 1200 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
1129 sp.Name, finalDestination.RegionName, sp.Scene.Name); 1201 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1130 1202 sp.IsInTransit = false;
1131 return; 1203 return;
1132 } 1204 }
1133 1205
@@ -1135,31 +1207,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1135 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}", 1207 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
1136 sp.Name, finalDestination.RegionName, sp.Scene.Name); 1208 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1137 1209
1138 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); 1210 Fail(sp, finalDestination, logout, agentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
1211 sp.IsInTransit = false;
1139 return; 1212 return;
1140 } 1213 }
1141 1214
1142 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); 1215 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
1143 1216
1144 // Need to signal neighbours whether child agents may need closing irrespective of whether this 1217 if(logout)
1145 // one needed closing. We also need to close child agents as quickly as possible to avoid complicated 1218 sp.closeAllChildAgents();
1146 // race conditions with rapid agent releporting (e.g. from A1 to a non-neighbour B, back 1219 else
1147 // to a neighbour A2 then off to a non-neighbour C). Closing child agents any later requires complex 1220 sp.CloseChildAgents(childRegionsToClose);
1148 // distributed checks to avoid problems in rapid reteleporting scenarios and where child agents are
1149 // abandoned without proper close by viewer but then re-used by an incoming connection.
1150 sp.CloseChildAgents(newRegionX, newRegionY);
1151 1221
1152 // May need to logout or other cleanup 1222 sp.HasMovedAway(!(OutSideViewRange || logout));
1223
1224 //HG hook
1153 AgentHasMovedAway(sp, logout); 1225 AgentHasMovedAway(sp, logout);
1154 1226
1155 // Well, this is it. The agent is over there. 1227// ulong sourceRegionHandle = sp.RegionHandle;
1156 KillEntity(sp.Scene, sp.LocalId);
1157 1228
1158 // Now let's make it officially a child agent 1229 // Now let's make it officially a child agent
1159 sp.MakeChildAgent(); 1230 sp.MakeChildAgent(destinationHandle);
1160 1231
1161 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 1232 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1162 if (NeedsClosing(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 1233 // go by HG hook
1234 if (NeedsClosing(reg, OutSideViewRange))
1163 { 1235 {
1164 if (!sp.Scene.IncomingPreCloseClient(sp)) 1236 if (!sp.Scene.IncomingPreCloseClient(sp))
1165 return; 1237 return;
@@ -1170,21 +1242,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1170 // BEFORE THEY SETTLE IN THE NEW REGION. 1242 // BEFORE THEY SETTLE IN THE NEW REGION.
1171 // DECREASING THE WAIT TIME HERE WILL EITHER RESULT IN A VIEWER CRASH OR 1243 // DECREASING THE WAIT TIME HERE WILL EITHER RESULT IN A VIEWER CRASH OR
1172 // IN THE AVIE BEING PLACED IN INFINITY FOR A COUPLE OF SECONDS. 1244 // IN THE AVIE BEING PLACED IN INFINITY FOR A COUPLE OF SECONDS.
1245
1173 Thread.Sleep(15000); 1246 Thread.Sleep(15000);
1174 1247
1175 // OK, it got this agent. Let's close everything 1248 // OK, it got this agent. Let's close everything
1176 // If we shouldn't close the agent due to some other region renewing the connection 1249 // If we shouldn't close the agent due to some other region renewing the connection
1177 // then this will be handled in IncomingCloseAgent under lock conditions 1250 // then this will be handled in IncomingCloseAgent under lock conditions
1178 m_log.DebugFormat( 1251 m_log.DebugFormat(
1179 "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name); 1252 "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name);
1180 1253
1181 sp.Scene.CloseAgent(sp.UUID, false); 1254 sp.Scene.CloseAgent(sp.UUID, false);
1182 } 1255 }
1183 else 1256 sp.IsInTransit = false;
1184 {
1185 // now we have a child agent in this region.
1186 sp.Reset();
1187 }
1188 } 1257 }
1189 1258
1190 /// <summary> 1259 /// <summary>
@@ -1232,13 +1301,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1232 sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout); 1301 sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout);
1233 } 1302 }
1234 1303
1235 protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) 1304 protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, EntityTransferContext ctx, out string reason, out bool logout)
1236 { 1305 {
1237 GridRegion source = new GridRegion(Scene.RegionInfo); 1306 GridRegion source = new GridRegion(Scene.RegionInfo);
1238 source.RawServerURI = m_GatekeeperURI; 1307 source.RawServerURI = m_GatekeeperURI;
1239 1308
1240 logout = false; 1309 logout = false;
1241 bool success = Scene.SimulationService.CreateAgent(source, finalDestination, agentCircuit, teleportFlags, out reason); 1310 bool success = Scene.SimulationService.CreateAgent(source, finalDestination, agentCircuit, teleportFlags, ctx, out reason);
1242 1311
1243 if (success) 1312 if (success)
1244 sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout); 1313 sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout);
@@ -1246,9 +1315,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1246 return success; 1315 return success;
1247 } 1316 }
1248 1317
1249 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp) 1318 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp, EntityTransferContext ctx)
1250 { 1319 {
1251 return Scene.SimulationService.UpdateAgent(finalDestination, agent); 1320 return Scene.SimulationService.UpdateAgent(finalDestination, agent, ctx);
1252 } 1321 }
1253 1322
1254 protected virtual void SetCallbackURL(AgentData agent, RegionInfo region) 1323 protected virtual void SetCallbackURL(AgentData agent, RegionInfo region)
@@ -1265,10 +1334,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1265 /// </summary> 1334 /// </summary>
1266 /// <param name='sp'></param> 1335 /// <param name='sp'></param>
1267 /// <param name='logout'></param> 1336 /// <param name='logout'></param>
1337 ///
1338 /// now just a HG hook
1268 protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout) 1339 protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout)
1269 { 1340 {
1270 if (sp.Scene.AttachmentsModule != null) 1341// if (sp.Scene.AttachmentsModule != null)
1271 sp.Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, true); 1342// sp.Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, logout);
1272 } 1343 }
1273 1344
1274 protected void KillEntity(Scene scene, uint localID) 1345 protected void KillEntity(Scene scene, uint localID)
@@ -1276,6 +1347,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1276 scene.SendKillObject(new List<uint> { localID }); 1347 scene.SendKillObject(new List<uint> { localID });
1277 } 1348 }
1278 1349
1350 // HG hook
1279 protected virtual GridRegion GetFinalDestination(GridRegion region, UUID agentID, string agentHomeURI, out string message) 1351 protected virtual GridRegion GetFinalDestination(GridRegion region, UUID agentID, string agentHomeURI, out string message)
1280 { 1352 {
1281 message = null; 1353 message = null;
@@ -1285,28 +1357,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1285 // This returns 'true' if the new region already has a child agent for our 1357 // This returns 'true' if the new region already has a child agent for our
1286 // incoming agent. The implication is that, if 'false', we have to create the 1358 // incoming agent. The implication is that, if 'false', we have to create the
1287 // child and then teleport into the region. 1359 // child and then teleport into the region.
1288 protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY) 1360 protected virtual bool NeedsNewAgent(float viewdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY,
1361 int oldsizeX, int oldsizeY, int newsizeX, int newsizeY)
1289 { 1362 {
1290 if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) 1363 return Util.IsOutsideView(viewdist, oldRegionX, newRegionX, oldRegionY, newRegionY,
1291 { 1364 oldsizeX, oldsizeY, newsizeX, newsizeY);
1292 Vector2 swCorner, neCorner;
1293 GetMegaregionViewRange(out swCorner, out neCorner);
1294
1295 m_log.DebugFormat(
1296 "[ENTITY TRANSFER MODULE]: Megaregion view of {0} is from {1} to {2} with new agent check for {3},{4}",
1297 Scene.Name, swCorner, neCorner, newRegionX, newRegionY);
1298
1299 return !(newRegionX >= swCorner.X && newRegionX <= neCorner.X && newRegionY >= swCorner.Y && newRegionY <= neCorner.Y);
1300 }
1301 else
1302 {
1303 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY);
1304 }
1305 } 1365 }
1306 1366
1307 protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) 1367 // HG Hook
1368 protected virtual bool NeedsClosing(GridRegion reg, bool OutViewRange)
1369
1308 { 1370 {
1309 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); 1371 return OutViewRange;
1310 } 1372 }
1311 1373
1312 #endregion 1374 #endregion
@@ -1328,11 +1390,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1328 remoteClient.SendTeleportFailed("The teleport destination could not be found."); 1390 remoteClient.SendTeleportFailed("The teleport destination could not be found.");
1329 return; 1391 return;
1330 } 1392 }
1331 ((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position, 1393 ((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position,
1332 Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark)); 1394 Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark));
1333 } 1395 }
1334 1396
1335 #endregion 1397 #endregion
1336 1398
1337 #region Teleport Home 1399 #region Teleport Home
1338 1400
@@ -1366,7 +1428,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1366 client.SendTeleportFailed("Your home region could not be found."); 1428 client.SendTeleportFailed("Your home region could not be found.");
1367 return false; 1429 return false;
1368 } 1430 }
1369 1431
1370 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Home region of {0} is {1} ({2}-{3})", 1432 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Home region of {0} is {1} ({2}-{3})",
1371 client.Name, regionInfo.RegionName, regionInfo.RegionCoordX, regionInfo.RegionCoordY); 1433 client.Name, regionInfo.RegionName, regionInfo.RegionCoordX, regionInfo.RegionCoordY);
1372 1434
@@ -1389,105 +1451,146 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1389 1451
1390 #region Agent Crossings 1452 #region Agent Crossings
1391 1453
1392 // Given a position relative to the current region (which has previously been tested to 1454 public bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position,
1393 // see that it is actually outside the current region), find the new region that the 1455 EntityTransferContext ctx, out string reason)
1394 // point is actually in. 1456 {
1395 // Returns the coordinates and information of the new region or 'null' of it doesn't exist. 1457 reason = String.Empty;
1458
1459 UUID agentID = agent.UUID;
1460 ulong destinyHandle = destiny.RegionHandle;
1461
1462 if (m_bannedRegionCache.IfBanned(destinyHandle, agentID))
1463 {
1464 return false;
1465 }
1466
1467 Scene ascene = agent.Scene;
1468 string homeURI = ascene.GetAgentHomeURI(agentID);
1469
1470
1471 if (!ascene.SimulationService.QueryAccess(destiny, agentID, homeURI, false, position,
1472 agent.Scene.GetFormatsOffered(), ctx, out reason))
1473 {
1474 m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0);
1475 return false;
1476 }
1477 return true;
1478 }
1479
1480
1481 // Given a position relative to the current region and outside of it
1482 // find the new region that the point is actually in.
1483 // returns 'null' if new region not found or if information
1484 // and new position relative to it
1485 // now only works for crossings
1486
1396 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, 1487 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos,
1397 EntityTransferContext ctx, out Vector3 newpos, out string failureReason) 1488 EntityTransferContext ctx, out Vector3 newpos, out string failureReason)
1398 { 1489 {
1399 newpos = pos; 1490 newpos = pos;
1400 failureReason = string.Empty; 1491 failureReason = string.Empty;
1401 string homeURI = scene.GetAgentHomeURI(agentID);
1402 1492
1403// m_log.DebugFormat( 1493// m_log.DebugFormat(
1404// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); 1494// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
1405 1495
1406 // Compute world location of the object's position 1496 // Compute world location of the agent's position
1407 double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X; 1497 double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X;
1408 double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y; 1498 double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y;
1409 1499
1410 // Call the grid service to lookup the region containing the new position. 1500 // Call the grid service to lookup the region containing the new position.
1411 GridRegion neighbourRegion = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID, 1501 GridRegion neighbourRegion = GetRegionContainingWorldLocation(
1412 presenceWorldX, presenceWorldY, 1502 scene.GridService, scene.RegionInfo.ScopeID,
1413 Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY)); 1503 presenceWorldX, presenceWorldY,
1504 Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY));
1505
1506 if (neighbourRegion == null)
1507 return null;
1414 1508
1415 if (neighbourRegion != null) 1509 if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID))
1416 { 1510 {
1417 // Compute the entity's position relative to the new region 1511 failureReason = "Access Denied or Temporary not possible";
1418 newpos = new Vector3((float)(presenceWorldX - (double)neighbourRegion.RegionLocX), 1512 return null;
1513 }
1514
1515 m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID);
1516
1517 // Compute the entity's position relative to the new region
1518 newpos = new Vector3((float)(presenceWorldX - (double)neighbourRegion.RegionLocX),
1419 (float)(presenceWorldY - (double)neighbourRegion.RegionLocY), 1519 (float)(presenceWorldY - (double)neighbourRegion.RegionLocY),
1420 pos.Z); 1520 pos.Z);
1421 1521
1422 if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID)) 1522 string homeURI = scene.GetAgentHomeURI(agentID);
1423 { 1523
1424 failureReason = "Cannot region cross into banned parcel"; 1524 if (!scene.SimulationService.QueryAccess(
1425 neighbourRegion = null; 1525 neighbourRegion, agentID, homeURI, false, newpos,
1426 } 1526 scene.GetFormatsOffered(), ctx, out failureReason))
1427 else 1527 {
1428 { 1528 // remember the fail
1429 // If not banned, make sure this agent is not in the list. 1529 m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
1430 m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID); 1530 if(String.IsNullOrWhiteSpace(failureReason))
1431 } 1531 failureReason = "Access Denied";
1432 1532 return null;
1433 // Check to see if we have access to the target region.
1434 if (neighbourRegion != null
1435 && !scene.SimulationService.QueryAccess(neighbourRegion, agentID, homeURI, false, newpos, scene.GetFormatsOffered(), ctx, out failureReason))
1436 {
1437 // remember banned
1438 m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
1439 neighbourRegion = null;
1440 }
1441 } 1533 }
1442 else 1534
1535 return neighbourRegion;
1536 }
1537
1538 public bool Cross(ScenePresence agent, bool isFlying)
1539 {
1540 agent.IsInLocalTransit = true;
1541 agent.IsInTransit = true;
1542 CrossAsyncDelegate d = CrossAsync;
1543 d.BeginInvoke(agent, isFlying, CrossCompleted, d);
1544 return true;
1545 }
1546
1547 private void CrossCompleted(IAsyncResult iar)
1548 {
1549 CrossAsyncDelegate icon = (CrossAsyncDelegate)iar.AsyncState;
1550 ScenePresence agent = icon.EndInvoke(iar);
1551
1552 if(agent == null || agent.IsDeleted)
1553 return;
1554
1555 if(!agent.IsChildAgent)
1443 { 1556 {
1444 // The destination region just doesn't exist 1557 // crossing failed
1445 failureReason = "Cannot cross into non-existent region"; 1558 agent.CrossToNewRegionFail();
1446 } 1559 }
1447
1448 if (neighbourRegion == null)
1449 m_log.DebugFormat("{0} GetDestination: region not found. Old region name={1} at <{2},{3}> of size <{4},{5}>. Old pos={6}",
1450 LogHeader, scene.RegionInfo.RegionName,
1451 scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY,
1452 scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY,
1453 pos);
1454 else 1560 else
1455 m_log.DebugFormat("{0} GetDestination: new region={1} at <{2},{3}> of size <{4},{5}>, newpos=<{6},{7}>", 1561 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
1456 LogHeader, neighbourRegion.RegionName,
1457 neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY,
1458 newpos.X, newpos.Y);
1459 1562
1460 return neighbourRegion; 1563 agent.IsInTransit = false;
1461 } 1564 }
1462 1565
1463 public bool Cross(ScenePresence agent, bool isFlying) 1566 public ScenePresence CrossAsync(ScenePresence agent, bool isFlying)
1464 { 1567 {
1465 Vector3 newpos; 1568 Vector3 newpos;
1466 EntityTransferContext ctx = new EntityTransferContext(); 1569 EntityTransferContext ctx = new EntityTransferContext();
1467 string failureReason; 1570 string failureReason;
1468 1571
1469 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, 1572 // We need this because of decimal number parsing of the protocols.
1573 Culture.SetCurrentCulture();
1574
1575 Vector3 pos = agent.AbsolutePosition + agent.Velocity * 0.2f;
1576
1577 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, pos,
1470 ctx, out newpos, out failureReason); 1578 ctx, out newpos, out failureReason);
1471 if (neighbourRegion == null) 1579 if (neighbourRegion == null)
1472 { 1580 {
1473 agent.ControllingClient.SendAlertMessage(failureReason); 1581 if (!agent.IsDeleted && failureReason != String.Empty && agent.ControllingClient != null)
1474 return false; 1582 agent.ControllingClient.SendAlertMessage(failureReason);
1583 return agent;
1475 } 1584 }
1476 1585
1477 agent.IsInTransit = true; 1586// agent.IsInTransit = true;
1478
1479 CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync;
1480 d.BeginInvoke(agent, newpos, neighbourRegion, isFlying, ctx, CrossAgentToNewRegionCompleted, d);
1481
1482 Scene.EventManager.TriggerCrossAgentToNewRegion(agent, isFlying, neighbourRegion);
1483 1587
1484 return true; 1588 CrossAgentToNewRegionAsync(agent, newpos, neighbourRegion, isFlying, ctx);
1589 agent.IsInTransit = false;
1590 return agent;
1485 } 1591 }
1486 1592
1487 1593 public delegate void InformClientToInitiateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene);
1488 public delegate void InformClientToInitiateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY,
1489 Vector3 position,
1490 Scene initiatingScene);
1491 1594
1492 private void InformClientToInitiateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene) 1595 private void InformClientToInitiateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene)
1493 { 1596 {
@@ -1506,14 +1609,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1506 Thread.Sleep(10000); 1609 Thread.Sleep(10000);
1507 1610
1508 m_log.DebugFormat( 1611 m_log.DebugFormat(
1509 "[ENTITY TRANSFER MODULE]: Auto-reteleporting {0} to correct megaregion location {1},{2},{3} from {4}", 1612 "[ENTITY TRANSFER MODULE]: Auto-reteleporting {0} to correct megaregion location {1},{2},{3} from {4}",
1510 agent.Name, regionX, regionY, position, initiatingScene.Name); 1613 agent.Name, regionX, regionY, position, initiatingScene.Name);
1511 1614
1512 agent.Scene.RequestTeleportLocation( 1615 agent.Scene.RequestTeleportLocation(
1513 agent.ControllingClient, 1616 agent.ControllingClient,
1514 Util.RegionLocToHandle(regionX, regionY), 1617 Util.RegionGridLocToHandle(regionX, regionY),
1515 position, 1618 position,
1516 agent.Lookat, 1619 agent.Lookat,
1517 (uint)Constants.TeleportFlags.ViaLocation); 1620 (uint)Constants.TeleportFlags.ViaLocation);
1518 1621
1519 /* 1622 /*
@@ -1557,15 +1660,71 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1557 icon.EndInvoke(iar); 1660 icon.EndInvoke(iar);
1558 } 1661 }
1559 1662
1560 public bool CrossAgentToNewRegionPrep(ScenePresence agent, GridRegion neighbourRegion) 1663 public bool CrossAgentCreateFarChild(ScenePresence agent, GridRegion neighbourRegion, Vector3 pos, EntityTransferContext ctx)
1561 { 1664 {
1562 if (neighbourRegion == null) 1665 ulong regionhandler = neighbourRegion.RegionHandle;
1666
1667 if(agent.knowsNeighbourRegion(regionhandler))
1668 return true;
1669
1670 string reason;
1671 ulong currentRegionHandler = agent.Scene.RegionInfo.RegionHandle;
1672 GridRegion source = new GridRegion(agent.Scene.RegionInfo);
1673
1674 AgentCircuitData currentAgentCircuit =
1675 agent.Scene.AuthenticateHandler.GetAgentCircuitData(agent.ControllingClient.CircuitCode);
1676 AgentCircuitData agentCircuit = agent.ControllingClient.RequestClientInfo();
1677 agentCircuit.startpos = pos;
1678 agentCircuit.child = true;
1679
1680 agentCircuit.Appearance = new AvatarAppearance();
1681 agentCircuit.Appearance.AvatarHeight = agent.Appearance.AvatarHeight;
1682
1683 if (currentAgentCircuit != null)
1684 {
1685 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
1686 agentCircuit.IPAddress = currentAgentCircuit.IPAddress;
1687 agentCircuit.Viewer = currentAgentCircuit.Viewer;
1688 agentCircuit.Channel = currentAgentCircuit.Channel;
1689 agentCircuit.Mac = currentAgentCircuit.Mac;
1690 agentCircuit.Id0 = currentAgentCircuit.Id0;
1691 }
1692
1693 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1694 agent.AddNeighbourRegion(neighbourRegion, agentCircuit.CapsPath);
1695
1696 IPEndPoint endPoint = neighbourRegion.ExternalEndPoint;
1697 if(endPoint == null)
1698 {
1699 m_log.DebugFormat("CrossAgentCreateFarChild failed to resolve neighbour address {0}", neighbourRegion.ExternalHostName);
1563 return false; 1700 return false;
1564 1701 }
1565 m_entityTransferStateMachine.SetInTransit(agent.UUID); 1702 if (!Scene.SimulationService.CreateAgent(source, neighbourRegion, agentCircuit, (int)TeleportFlags.Default, ctx, out reason))
1703 {
1704 agent.RemoveNeighbourRegion(regionhandler);
1705 return false;
1706 }
1707
1708 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1709 int newSizeX = neighbourRegion.RegionSizeX;
1710 int newSizeY = neighbourRegion.RegionSizeY;
1566 1711
1567 agent.RemoveFromPhysicalScene(); 1712 if (m_eqModule != null)
1713 {
1714 m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " +
1715 "and EstablishAgentCommunication with seed cap {8}", LogHeader,
1716 source.RegionName, agent.Name,
1717 neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, newSizeX, newSizeY , capsPath);
1568 1718
1719 m_eqModule.EnableSimulator(regionhandler,
1720 endPoint, agent.UUID, newSizeX, newSizeY);
1721 m_eqModule.EstablishAgentCommunication(agent.UUID, endPoint, capsPath,
1722 regionhandler, newSizeX, newSizeY);
1723 }
1724 else
1725 {
1726 agent.ControllingClient.InformClientOfNeighbour(regionhandler, endPoint);
1727 }
1569 return true; 1728 return true;
1570 } 1729 }
1571 1730
@@ -1582,37 +1741,56 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1582 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: new region={1} at <{2},{3}>. newpos={4}", 1741 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: new region={1} at <{2},{3}>. newpos={4}",
1583 LogHeader, neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, pos); 1742 LogHeader, neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, pos);
1584 1743
1585 if (!CrossAgentToNewRegionPrep(agent, neighbourRegion)) 1744 if (neighbourRegion == null)
1586 { 1745 {
1587 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: prep failed. Resetting transfer state", LogHeader); 1746 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: invalid destiny", LogHeader);
1588 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1747 return agent;
1748 }
1749
1750 IPEndPoint endpoint = neighbourRegion.ExternalEndPoint;
1751 if(endpoint == null)
1752 {
1753 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: failed to resolve neighbour address {0} ",neighbourRegion.ExternalHostName);
1754 return agent;
1589 } 1755 }
1590 1756
1591 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying, ctx)) 1757 m_entityTransferStateMachine.SetInTransit(agent.UUID);
1758 agent.RemoveFromPhysicalScene();
1759
1760 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, endpoint, isFlying, ctx))
1592 { 1761 {
1593 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader); 1762 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader);
1594 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1763 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1595 } 1764 }
1596
1597 CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, ctx);
1598 } 1765 }
1599 catch (Exception e) 1766 catch (Exception e)
1600 { 1767 {
1601 m_log.Error(string.Format("{0}: CrossAgentToNewRegionAsync: failed with exception ", LogHeader), e); 1768 m_log.Error(string.Format("{0}: CrossAgentToNewRegionAsync: failed with exception ", LogHeader), e);
1602 } 1769 }
1603
1604 return agent; 1770 return agent;
1605 } 1771 }
1606 1772
1607 public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx) 1773 public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
1774 IPEndPoint endpoint, bool isFlying, EntityTransferContext ctx)
1608 { 1775 {
1776 int ts = Util.EnvironmentTickCount();
1777 bool sucess = true;
1778 string reason = String.Empty;
1779 List<ulong> childRegionsToClose = null;
1609 try 1780 try
1610 { 1781 {
1611 AgentData cAgent = new AgentData(); 1782 AgentData cAgent = new AgentData();
1612 agent.CopyTo(cAgent); 1783 agent.CopyTo(cAgent,true);
1613 if (ctx.OutboundVersion < 0.5f) 1784
1614 cAgent.Appearance.PackLegacyWearables = true;
1615 cAgent.Position = pos; 1785 cAgent.Position = pos;
1786 cAgent.ChildrenCapSeeds = agent.KnownRegions;
1787
1788 childRegionsToClose = agent.GetChildAgentsToClose(neighbourRegion.RegionHandle, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY);
1789 if(cAgent.ChildrenCapSeeds != null)
1790 {
1791 foreach(ulong regh in childRegionsToClose)
1792 cAgent.ChildrenCapSeeds.Remove(regh);
1793 }
1616 1794
1617 if (isFlying) 1795 if (isFlying)
1618 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; 1796 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
@@ -1623,21 +1801,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1623 // Beyond this point, extra cleanup is needed beyond removing transit state 1801 // Beyond this point, extra cleanup is needed beyond removing transit state
1624 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring); 1802 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring);
1625 1803
1626 if (!agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) 1804 if (sucess && !agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent, ctx))
1805 {
1806 sucess = false;
1807 reason = "agent update failed";
1808 }
1809
1810 if(!sucess)
1627 { 1811 {
1628 // region doesn't take it 1812 // region doesn't take it
1629 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); 1813 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
1630 1814
1631 m_log.WarnFormat( 1815 m_log.WarnFormat(
1632 "[ENTITY TRANSFER MODULE]: Region {0} would not accept update for agent {1} on cross attempt. Returning to original region.", 1816 "[ENTITY TRANSFER MODULE]: agent {0} crossing to {1} failed: {2}",
1633 neighbourRegion.RegionName, agent.Name); 1817 agent.Name, neighbourRegion.RegionName, reason);
1634 1818
1635 ReInstantiateScripts(agent); 1819 ReInstantiateScripts(agent);
1636 agent.AddToPhysicalScene(isFlying); 1820 if(agent.ParentID == 0 && agent.ParentUUID == UUID.Zero)
1821 {
1822 agent.AddToPhysicalScene(isFlying);
1823 }
1637 1824
1638 return false; 1825 return false;
1639 } 1826 }
1640 1827
1828 m_log.DebugFormat("[CrossAgentIntoNewRegionMain] ok, time {0}ms",Util.EnvironmentTickCountSubtract(ts));
1641 } 1829 }
1642 catch (Exception e) 1830 catch (Exception e)
1643 { 1831 {
@@ -1649,44 +1837,38 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1649 return false; 1837 return false;
1650 } 1838 }
1651 1839
1652 return true;
1653 }
1654
1655 public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
1656 bool isFlying, EntityTransferContext ctx)
1657 {
1658 agent.ControllingClient.RequestClientInfo();
1659
1660 string agentcaps; 1840 string agentcaps;
1661 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps)) 1841 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
1662 { 1842 {
1663 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.", 1843 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.",
1664 neighbourRegion.RegionHandle); 1844 neighbourRegion.RegionHandle);
1665 return; 1845 return false;
1666 } 1846 }
1667 1847
1668 // No turning back 1848 // No turning back
1849
1669 agent.IsChildAgent = true; 1850 agent.IsChildAgent = true;
1670 1851
1671 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); 1852 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps);
1672 1853
1673 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); 1854 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID);
1674 1855
1675 Vector3 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0); 1856 Vector3 vel2 = Vector3.Zero;
1857 if((agent.crossingFlags & 2) != 0)
1858 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0);
1676 1859
1677 if (m_eqModule != null) 1860 if (m_eqModule != null)
1678 { 1861 {
1679 m_eqModule.CrossRegion( 1862 m_eqModule.CrossRegion(
1680 neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */, 1863 neighbourRegion.RegionHandle, pos, vel2 /* agent.Velocity */,
1681 neighbourRegion.ExternalEndPoint, 1864 endpoint, capsPath, agent.UUID, agent.ControllingClient.SessionId,
1682 capsPath, agent.UUID, agent.ControllingClient.SessionId,
1683 neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY); 1865 neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY);
1684 } 1866 }
1685 else 1867 else
1686 { 1868 {
1687 m_log.ErrorFormat("{0} Using old CrossRegion packet. Varregion will not work!!", LogHeader); 1869 m_log.ErrorFormat("{0} Using old CrossRegion packet. Varregion will not work!!", LogHeader);
1688 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint, 1870 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos, agent.Velocity,
1689 capsPath); 1871 endpoint,capsPath);
1690 } 1872 }
1691 1873
1692 // SUCCESS! 1874 // SUCCESS!
@@ -1695,51 +1877,23 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1695 // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. 1877 // Unlike a teleport, here we do not wait for the destination region to confirm the receipt.
1696 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); 1878 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
1697 1879
1698 agent.MakeChildAgent(); 1880 if(childRegionsToClose != null)
1881 agent.CloseChildAgents(childRegionsToClose);
1699 1882
1700 // FIXME: Possibly this should occur lower down after other commands to close other agents, 1883 if((agent.crossingFlags & 8) == 0)
1701 // but not sure yet what the side effects would be. 1884 agent.ClearControls(); // don't let attachments delete (called in HasMovedAway) disturb taken controls on viewers
1702 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1703
1704 // now we have a child agent in this region. Request all interesting data about other (root) agents
1705 agent.SendOtherAgentsAvatarDataToClient();
1706 agent.SendOtherAgentsAppearanceToClient();
1707
1708 // TODO: Check since what version this wasn't needed anymore. May be as old as 0.6
1709/*
1710 // Backwards compatibility. Best effort
1711 if (version == 0f)
1712 {
1713 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one...");
1714 Thread.Sleep(3000); // wait a little now that we're not waiting for the callback
1715 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
1716 }
1717*/
1718 // Next, let's close the child agent connections that are too far away.
1719 uint neighbourx;
1720 uint neighboury;
1721 Util.RegionHandleToRegionLoc(neighbourRegion.RegionHandle, out neighbourx, out neighboury);
1722 1885
1723 agent.CloseChildAgents(neighbourx, neighboury); 1886 agent.HasMovedAway((agent.crossingFlags & 8) == 0);
1724 1887
1725 AgentHasMovedAway(agent, false); 1888 agent.MakeChildAgent(neighbourRegion.RegionHandle);
1726 1889
1727 // the user may change their profile information in other region, 1890 // FIXME: Possibly this should occur lower down after other commands to close other agents,
1728 // so the userinfo in UserProfileCache is not reliable any more, delete it 1891 // but not sure yet what the side effects would be.
1729 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! 1892 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1730// if (agent.Scene.NeedSceneCacheClear(agent.UUID))
1731// {
1732// m_log.DebugFormat(
1733// "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID);
1734// }
1735
1736 //m_log.Debug("AFTER CROSS");
1737 //Scene.DumpChildrenSeeds(UUID);
1738 //DumpKnownRegions();
1739 1893
1740 return; 1894 return true;
1741 } 1895 }
1742 1896
1743 private void CrossAgentToNewRegionCompleted(IAsyncResult iar) 1897 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
1744 { 1898 {
1745 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState; 1899 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
@@ -1754,7 +1908,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1754 // In any case 1908 // In any case
1755 agent.IsInTransit = false; 1909 agent.IsInTransit = false;
1756 1910
1757 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); 1911// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
1758 } 1912 }
1759 1913
1760 #endregion 1914 #endregion
@@ -1762,7 +1916,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1762 #region Enable Child Agent 1916 #region Enable Child Agent
1763 1917
1764 /// <summary> 1918 /// <summary>
1765 /// This informs a single neighbouring region about agent "avatar". 1919 /// This informs a single neighbouring region about agent "avatar", and avatar about it
1766 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 1920 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
1767 /// </summary> 1921 /// </summary>
1768 /// <param name="sp"></param> 1922 /// <param name="sp"></param>
@@ -1771,42 +1925,46 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1771 { 1925 {
1772 m_log.DebugFormat("[ENTITY TRANSFER]: Enabling child agent in new neighbour {0}", region.RegionName); 1926 m_log.DebugFormat("[ENTITY TRANSFER]: Enabling child agent in new neighbour {0}", region.RegionName);
1773 1927
1928 ulong currentRegionHandler = sp.Scene.RegionInfo.RegionHandle;
1929 ulong regionhandler = region.RegionHandle;
1930
1931 Dictionary<ulong, string> seeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1932
1933 if (seeds.ContainsKey(regionhandler))
1934 seeds.Remove(regionhandler);
1935/*
1936 List<ulong> oldregions = new List<ulong>(seeds.Keys);
1937
1938 if (oldregions.Contains(currentRegionHandler))
1939 oldregions.Remove(currentRegionHandler);
1940*/
1941 if (!seeds.ContainsKey(currentRegionHandler))
1942 seeds.Add(currentRegionHandler, sp.ControllingClient.RequestClientInfo().CapsPath);
1943
1774 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 1944 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1775 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo(); 1945 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo();
1776 agent.BaseFolder = UUID.Zero; 1946 agent.BaseFolder = UUID.Zero;
1777 agent.InventoryFolder = UUID.Zero; 1947 agent.InventoryFolder = UUID.Zero;
1778 agent.startpos = new Vector3(128, 128, 70); 1948 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, region);
1779 agent.child = true; 1949 agent.child = true;
1780 agent.Appearance = new AvatarAppearance(); 1950 agent.Appearance = new AvatarAppearance();
1781 agent.Appearance.PackLegacyWearables = true; 1951 agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
1782 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1783
1784 agent.ChildrenCapSeeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1785 //m_log.DebugFormat("[XXX] Seeds 1 {0}", agent.ChildrenCapSeeds.Count);
1786 1952
1787 if (!agent.ChildrenCapSeeds.ContainsKey(sp.Scene.RegionInfo.RegionHandle)) 1953 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1788 agent.ChildrenCapSeeds.Add(sp.Scene.RegionInfo.RegionHandle, sp.ControllingClient.RequestClientInfo().CapsPath);
1789 //m_log.DebugFormat("[XXX] Seeds 2 {0}", agent.ChildrenCapSeeds.Count);
1790 1954
1791 sp.AddNeighbourRegion(region.RegionHandle, agent.CapsPath); 1955 seeds.Add(regionhandler, agent.CapsPath);
1792 //foreach (ulong h in agent.ChildrenCapSeeds.Keys)
1793 // m_log.DebugFormat("[XXX] --> {0}", h);
1794 //m_log.DebugFormat("[XXX] Adding {0}", region.RegionHandle);
1795 if (agent.ChildrenCapSeeds.ContainsKey(region.RegionHandle))
1796 {
1797 m_log.WarnFormat(
1798 "[ENTITY TRANSFER]: Overwriting caps seed {0} with {1} for region {2} (handle {3}) for {4} in {5}",
1799 agent.ChildrenCapSeeds[region.RegionHandle], agent.CapsPath,
1800 region.RegionName, region.RegionHandle, sp.Name, Scene.Name);
1801 }
1802 1956
1803 agent.ChildrenCapSeeds[region.RegionHandle] = agent.CapsPath; 1957// agent.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
1958 agent.ChildrenCapSeeds = null;
1804 1959
1805 if (sp.Scene.CapsModule != null) 1960 if (sp.Scene.CapsModule != null)
1806 { 1961 {
1807 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, agent.ChildrenCapSeeds); 1962 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, seeds);
1808 } 1963 }
1809 1964
1965 sp.KnownRegions = seeds;
1966 sp.AddNeighbourRegionSizeInfo(region);
1967
1810 if (currentAgentCircuit != null) 1968 if (currentAgentCircuit != null)
1811 { 1969 {
1812 agent.ServiceURLs = currentAgentCircuit.ServiceURLs; 1970 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
@@ -1816,7 +1974,24 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1816 agent.Mac = currentAgentCircuit.Mac; 1974 agent.Mac = currentAgentCircuit.Mac;
1817 agent.Id0 = currentAgentCircuit.Id0; 1975 agent.Id0 = currentAgentCircuit.Id0;
1818 } 1976 }
1819 1977/*
1978 AgentPosition agentpos = null;
1979
1980 if (oldregions.Count > 0)
1981 {
1982 agentpos = new AgentPosition();
1983 agentpos.AgentID = new UUID(sp.UUID.Guid);
1984 agentpos.SessionID = sp.ControllingClient.SessionId;
1985 agentpos.Size = sp.Appearance.AvatarSize;
1986 agentpos.Center = sp.CameraPosition;
1987 agentpos.Far = sp.DrawDistance;
1988 agentpos.Position = sp.AbsolutePosition;
1989 agentpos.Velocity = sp.Velocity;
1990 agentpos.RegionHandle = currentRegionHandler;
1991 agentpos.Throttles = sp.ControllingClient.GetThrottlesPacked(1);
1992 agentpos.ChildrenCapSeeds = seeds;
1993 }
1994*/
1820 IPEndPoint external = region.ExternalEndPoint; 1995 IPEndPoint external = region.ExternalEndPoint;
1821 if (external != null) 1996 if (external != null)
1822 { 1997 {
@@ -1825,7 +2000,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1825 InformClientOfNeighbourCompleted, 2000 InformClientOfNeighbourCompleted,
1826 d); 2001 d);
1827 } 2002 }
2003/*
2004 if(oldregions.Count >0)
2005 {
2006 uint neighbourx;
2007 uint neighboury;
2008 UUID scope = sp.Scene.RegionInfo.ScopeID;
2009 foreach (ulong handler in oldregions)
2010 {
2011 Utils.LongToUInts(handler, out neighbourx, out neighboury);
2012 GridRegion neighbour = sp.Scene.GridService.GetRegionByPosition(scope, (int)neighbourx, (int)neighboury);
2013 sp.Scene.SimulationService.UpdateAgent(neighbour, agentpos);
2014 }
2015 }
2016 */
1828 } 2017 }
2018
1829 #endregion 2019 #endregion
1830 2020
1831 #region Enable Child Agents 2021 #region Enable Child Agents
@@ -1835,167 +2025,175 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1835 2025
1836 /// <summary> 2026 /// <summary>
1837 /// This informs all neighbouring regions about agent "avatar". 2027 /// This informs all neighbouring regions about agent "avatar".
2028 /// and as important informs the avatar about then
1838 /// </summary> 2029 /// </summary>
1839 /// <param name="sp"></param> 2030 /// <param name="sp"></param>
1840 public void EnableChildAgents(ScenePresence sp) 2031 public void EnableChildAgents(ScenePresence sp)
1841 { 2032 {
2033 // assumes that out of view range regions are disconnected by the previus region
2034
1842 List<GridRegion> neighbours = new List<GridRegion>(); 2035 List<GridRegion> neighbours = new List<GridRegion>();
1843 RegionInfo m_regionInfo = sp.Scene.RegionInfo; 2036 Scene spScene = sp.Scene;
2037 RegionInfo m_regionInfo = spScene.RegionInfo;
1844 2038
1845 if (m_regionInfo != null) 2039 if (m_regionInfo != null)
1846 { 2040 {
1847 neighbours = GetNeighbours(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); 2041 neighbours = GetNeighbors(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
1848 } 2042 }
1849 else 2043 else
1850 { 2044 {
1851 m_log.Debug("[ENTITY TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?"); 2045 m_log.Debug("[ENTITY TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?");
1852 } 2046 }
1853 2047
1854 /// We need to find the difference between the new regions where there are no child agents 2048 ulong currentRegionHandler = m_regionInfo.RegionHandle;
1855 /// and the regions where there are already child agents. We only send notification to the former.
1856 List<ulong> neighbourHandles = NeighbourHandles(neighbours); // on this region
1857 neighbourHandles.Add(sp.Scene.RegionInfo.RegionHandle); // add this region too
1858 List<ulong> previousRegionNeighbourHandles;
1859 2049
1860 if (sp.Scene.CapsModule != null) 2050 LinkedList<ulong> previousRegionNeighbourHandles;
2051 Dictionary<ulong, string> seeds;
2052 ICapabilitiesModule capsModule = spScene.CapsModule;
2053
2054 if (capsModule != null)
1861 { 2055 {
1862 previousRegionNeighbourHandles = 2056 seeds = new Dictionary<ulong, string>(capsModule.GetChildrenSeeds(sp.UUID));
1863 new List<ulong>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID).Keys); 2057 previousRegionNeighbourHandles = new LinkedList<ulong>(seeds.Keys);
1864 } 2058 }
1865 else 2059 else
1866 { 2060 {
1867 previousRegionNeighbourHandles = new List<ulong>(); 2061 seeds = new Dictionary<ulong, string>();
2062 previousRegionNeighbourHandles = new LinkedList<ulong>();
1868 } 2063 }
1869 2064
1870 List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles); 2065 IClientAPI spClient = sp.ControllingClient;
1871 List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles);
1872
1873// Dump("Current Neighbors", neighbourHandles);
1874// Dump("Previous Neighbours", previousRegionNeighbourHandles);
1875// Dump("New Neighbours", newRegions);
1876// Dump("Old Neighbours", oldRegions);
1877 2066
1878 /// Update the scene presence's known regions here on this region 2067 // This will fail if the user aborts login
1879 sp.DropOldNeighbours(oldRegions); 2068 try
1880 2069 {
1881 /// Collect as many seeds as possible 2070 if (!seeds.ContainsKey(currentRegionHandler))
1882 Dictionary<ulong, string> seeds; 2071 seeds.Add(currentRegionHandler, spClient.RequestClientInfo().CapsPath);
1883 if (sp.Scene.CapsModule != null) 2072 }
1884 seeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID)); 2073 catch
1885 else 2074 {
1886 seeds = new Dictionary<ulong, string>(); 2075 return;
2076 }
1887 2077
1888 //m_log.Debug(" !!! No. of seeds: " + seeds.Count); 2078 AgentCircuitData currentAgentCircuit =
1889 if (!seeds.ContainsKey(sp.Scene.RegionInfo.RegionHandle)) 2079 spScene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1890 seeds.Add(sp.Scene.RegionInfo.RegionHandle, sp.ControllingClient.RequestClientInfo().CapsPath);
1891 2080
1892 /// Create the necessary child agents
1893 List<AgentCircuitData> cagents = new List<AgentCircuitData>(); 2081 List<AgentCircuitData> cagents = new List<AgentCircuitData>();
2082 List<ulong> newneighbours = new List<ulong>();
2083
1894 foreach (GridRegion neighbour in neighbours) 2084 foreach (GridRegion neighbour in neighbours)
1895 { 2085 {
1896 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) 2086 ulong handler = neighbour.RegionHandle;
2087
2088 if (previousRegionNeighbourHandles.Contains(handler))
1897 { 2089 {
1898 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 2090 // agent already knows this region
1899 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo(); 2091 previousRegionNeighbourHandles.Remove(handler);
1900 agent.BaseFolder = UUID.Zero; 2092 continue;
1901 agent.InventoryFolder = UUID.Zero; 2093 }
1902 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, neighbour);
1903 agent.child = true;
1904 agent.Appearance = new AvatarAppearance();
1905 agent.Appearance.PackLegacyWearables = true;
1906 if (currentAgentCircuit != null)
1907 {
1908 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
1909 agent.IPAddress = currentAgentCircuit.IPAddress;
1910 agent.Viewer = currentAgentCircuit.Viewer;
1911 agent.Channel = currentAgentCircuit.Channel;
1912 agent.Mac = currentAgentCircuit.Mac;
1913 agent.Id0 = currentAgentCircuit.Id0;
1914 }
1915 2094
1916 if (newRegions.Contains(neighbour.RegionHandle)) 2095 if (handler == currentRegionHandler)
1917 { 2096 continue;
1918 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1919 sp.AddNeighbourRegion(neighbour.RegionHandle, agent.CapsPath);
1920 seeds.Add(neighbour.RegionHandle, agent.CapsPath);
1921 }
1922 else
1923 {
1924 agent.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, neighbour.RegionHandle);
1925 }
1926 2097
1927 cagents.Add(agent); 2098 // a new region to add
2099 AgentCircuitData agent = spClient.RequestClientInfo();
2100 agent.BaseFolder = UUID.Zero;
2101 agent.InventoryFolder = UUID.Zero;
2102 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, neighbour);
2103 agent.child = true;
2104 agent.Appearance = new AvatarAppearance();
2105 agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
2106
2107 if (currentAgentCircuit != null)
2108 {
2109 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
2110 agent.IPAddress = currentAgentCircuit.IPAddress;
2111 agent.Viewer = currentAgentCircuit.Viewer;
2112 agent.Channel = currentAgentCircuit.Channel;
2113 agent.Mac = currentAgentCircuit.Mac;
2114 agent.Id0 = currentAgentCircuit.Id0;
1928 } 2115 }
1929 }
1930 2116
1931 /// Update all child agent with everyone's seeds 2117 newneighbours.Add(handler);
1932 foreach (AgentCircuitData a in cagents) 2118 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1933 { 2119 seeds.Add(handler, agent.CapsPath);
1934 a.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
1935 }
1936 2120
1937 if (sp.Scene.CapsModule != null) 2121 agent.ChildrenCapSeeds = null;
1938 { 2122 cagents.Add(agent);
1939 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, seeds);
1940 } 2123 }
1941 sp.KnownRegions = seeds;
1942 //avatar.Scene.DumpChildrenSeeds(avatar.UUID);
1943 //avatar.DumpKnownRegions();
1944 2124
1945 bool newAgent = false; 2125 if (previousRegionNeighbourHandles.Contains(currentRegionHandler))
1946 int count = 0; 2126 previousRegionNeighbourHandles.Remove(currentRegionHandler);
1947 foreach (GridRegion neighbour in neighbours)
1948 {
1949 //m_log.WarnFormat("--> Going to send child agent to {0}", neighbour.RegionName);
1950 // Don't do it if there's already an agent in that region
1951 if (newRegions.Contains(neighbour.RegionHandle))
1952 newAgent = true;
1953 else
1954 newAgent = false;
1955// continue;
1956 2127
1957 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) 2128 // previousRegionNeighbourHandles now contains regions to forget
1958 { 2129 foreach (ulong handler in previousRegionNeighbourHandles)
1959 try 2130 seeds.Remove(handler);
1960 {
1961 // Let's put this back at sync, so that it doesn't clog
1962 // the network, especially for regions in the same physical server.
1963 // We're really not in a hurry here.
1964 InformClientOfNeighbourAsync(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent);
1965 //InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
1966 //d.BeginInvoke(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent,
1967 // InformClientOfNeighbourCompleted,
1968 // d);
1969 }
1970 2131
1971 catch (ArgumentOutOfRangeException) 2132 /// Update all child agent with everyone's seeds
1972 { 2133 // foreach (AgentCircuitData a in cagents)
1973 m_log.ErrorFormat( 2134 // a.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
1974 "[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}).",
1975 neighbour.ExternalHostName,
1976 neighbour.RegionHandle,
1977 neighbour.RegionLocX,
1978 neighbour.RegionLocY);
1979 }
1980 catch (Exception e)
1981 {
1982 m_log.ErrorFormat(
1983 "[ENTITY TRANSFER MODULE]: Could not resolve external hostname {0} for region {1} ({2}, {3}). {4}",
1984 neighbour.ExternalHostName,
1985 neighbour.RegionHandle,
1986 neighbour.RegionLocX,
1987 neighbour.RegionLocY,
1988 e);
1989 2135
1990 // FIXME: Okay, even though we've failed, we're still going to throw the exception on, 2136 if (capsModule != null)
1991 // since I don't know what will happen if we just let the client continue 2137 capsModule.SetChildrenSeed(sp.UUID, seeds);
1992 2138
1993 // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes. 2139 sp.KnownRegions = seeds;
1994 // throw e; 2140 sp.SetNeighbourRegionSizeInfo(neighbours);
2141
2142 if(newneighbours.Count > 0 || previousRegionNeighbourHandles.Count > 0)
2143 {
2144 AgentPosition agentpos = new AgentPosition();
2145 agentpos.AgentID = new UUID(sp.UUID.Guid);
2146 agentpos.SessionID = spClient.SessionId;
2147 agentpos.Size = sp.Appearance.AvatarSize;
2148 agentpos.Center = sp.CameraPosition;
2149 agentpos.Far = sp.DrawDistance;
2150 agentpos.Position = sp.AbsolutePosition;
2151 agentpos.Velocity = sp.Velocity;
2152 agentpos.RegionHandle = currentRegionHandler;
2153 //agentpos.GodLevel = sp.GodLevel;
2154 agentpos.GodData = sp.GodController.State();
2155 agentpos.Throttles = spClient.GetThrottlesPacked(1);
2156 // agentpos.ChildrenCapSeeds = seeds;
2157
2158 Util.FireAndForget(delegate
2159 {
2160 Thread.Sleep(200); // the original delay that was at InformClientOfNeighbourAsync start
2161 int count = 0;
2162 IPEndPoint ipe;
1995 2163
2164 foreach (GridRegion neighbour in neighbours)
2165 {
2166 ulong handler = neighbour.RegionHandle;
2167 try
2168 {
2169 if (newneighbours.Contains(handler))
2170 {
2171 ipe = neighbour.ExternalEndPoint;
2172 if (ipe != null)
2173 InformClientOfNeighbourAsync(sp, cagents[count], neighbour, ipe, true);
2174 else
2175 {
2176 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: lost DNS resolution for neighbour {0}", neighbour.ExternalHostName);
2177 }
2178 count++;
2179 }
2180 else if (!previousRegionNeighbourHandles.Contains(handler))
2181 {
2182 spScene.SimulationService.UpdateAgent(neighbour, agentpos);
2183 }
2184 }
2185 catch (Exception e)
2186 {
2187 m_log.ErrorFormat(
2188 "[ENTITY TRANSFER MODULE]: Error creating child agent at {0} ({1} ({2}, {3}). {4}",
2189 neighbour.ExternalHostName,
2190 neighbour.RegionHandle,
2191 neighbour.RegionLocX,
2192 neighbour.RegionLocY,
2193 e);
2194 }
1996 } 2195 }
1997 } 2196 });
1998 count++;
1999 } 2197 }
2000 } 2198 }
2001 2199
@@ -2004,26 +2202,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2004 // The first region is the home region of the passed scene presence. 2202 // The first region is the home region of the passed scene presence.
2005 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour) 2203 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour)
2006 { 2204 {
2007 /* 2205 return new Vector3(sp.Scene.RegionInfo.WorldLocX - neighbour.RegionLocX,
2008 int rRegionX = (int)sp.Scene.RegionInfo.LegacyRegionLocX;
2009 int rRegionY = (int)sp.Scene.RegionInfo.LegacyRegionLocY;
2010 int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize;
2011 int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize;
2012 int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize;
2013 int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize;
2014 return new Vector3(shiftx, shifty, 0f);
2015 */
2016 return new Vector3( sp.Scene.RegionInfo.WorldLocX - neighbour.RegionLocX,
2017 sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY, 2206 sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY,
2018 0f); 2207 0f);
2019 } 2208 }
2020 2209 #endregion
2021 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
2022 {
2023 // Since we don't know how big the regions could be, we have to search a very large area
2024 // to find possible regions.
2025 return GetRegionContainingWorldLocation(pGridService, pScopeID, px, py, Constants.MaximumRegionSize);
2026 }
2027 2210
2028 #region NotFoundLocationCache class 2211 #region NotFoundLocationCache class
2029 // A collection of not found locations to make future lookups 'not found' lookups quick. 2212 // A collection of not found locations to make future lookups 'not found' lookups quick.
@@ -2032,162 +2215,131 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2032 // contains that point. A conservitive estimate. 2215 // contains that point. A conservitive estimate.
2033 private class NotFoundLocationCache 2216 private class NotFoundLocationCache
2034 { 2217 {
2035 private struct NotFoundLocation 2218 private Dictionary<ulong, DateTime> m_notFoundLocations = new Dictionary<ulong, DateTime>();
2036 {
2037 public double minX, maxX, minY, maxY;
2038 public DateTime expireTime;
2039 }
2040 private List<NotFoundLocation> m_notFoundLocations = new List<NotFoundLocation>();
2041 public NotFoundLocationCache() 2219 public NotFoundLocationCache()
2042 { 2220 {
2043 } 2221 }
2044 // Add an area to the list of 'not found' places. The area is the snapped region 2222 // just use normal regions handlers and sizes
2045 // area around the added point.
2046 public void Add(double pX, double pY) 2223 public void Add(double pX, double pY)
2047 { 2224 {
2225 ulong psh = (ulong)pX & 0xffffff00ul;
2226 psh <<= 32;
2227 psh |= (ulong)pY & 0xffffff00ul;
2228
2048 lock (m_notFoundLocations) 2229 lock (m_notFoundLocations)
2049 { 2230 m_notFoundLocations[psh] = DateTime.UtcNow + TimeSpan.FromSeconds(30);
2050 if (!LockedContains(pX, pY))
2051 {
2052 NotFoundLocation nfl = new NotFoundLocation();
2053 // A not found location is not found for at least a whole region sized area
2054 nfl.minX = pX - (pX % (double)Constants.RegionSize);
2055 nfl.minY = pY - (pY % (double)Constants.RegionSize);
2056 nfl.maxX = nfl.minX + (double)Constants.RegionSize;
2057 nfl.maxY = nfl.minY + (double)Constants.RegionSize;
2058 nfl.expireTime = DateTime.Now + TimeSpan.FromSeconds(30);
2059 m_notFoundLocations.Add(nfl);
2060 }
2061 }
2062
2063 } 2231 }
2064 // Test to see of this point is in any of the 'not found' areas. 2232 // Test to see of this point is in any of the 'not found' areas.
2065 // Return 'true' if the point is found inside the 'not found' areas. 2233 // Return 'true' if the point is found inside the 'not found' areas.
2066 public bool Contains(double pX, double pY) 2234 public bool Contains(double pX, double pY)
2067 { 2235 {
2068 bool ret = false; 2236 ulong psh = (ulong)pX & 0xffffff00ul;
2237 psh <<= 32;
2238 psh |= (ulong)pY & 0xffffff00ul;
2239
2069 lock (m_notFoundLocations) 2240 lock (m_notFoundLocations)
2070 ret = LockedContains(pX, pY);
2071 return ret;
2072 }
2073 private bool LockedContains(double pX, double pY)
2074 {
2075 bool ret = false;
2076 this.DoExpiration();
2077 foreach (NotFoundLocation nfl in m_notFoundLocations)
2078 { 2241 {
2079 if (pX >= nfl.minX && pX < nfl.maxX && pY >= nfl.minY && pY < nfl.maxY) 2242 if(m_notFoundLocations.ContainsKey(psh))
2080 { 2243 {
2081 ret = true; 2244 if(m_notFoundLocations[psh] > DateTime.UtcNow)
2082 break; 2245 return true;
2246 m_notFoundLocations.Remove(psh);
2083 } 2247 }
2248 return false;
2084 } 2249 }
2085 return ret;
2086 } 2250 }
2251
2087 private void DoExpiration() 2252 private void DoExpiration()
2088 { 2253 {
2089 List<NotFoundLocation> m_toRemove = null; 2254 List<ulong> m_toRemove = new List<ulong>();;
2090 DateTime now = DateTime.Now; 2255 DateTime now = DateTime.UtcNow;
2091 foreach (NotFoundLocation nfl in m_notFoundLocations) 2256 lock (m_notFoundLocations)
2092 { 2257 {
2093 if (nfl.expireTime < now) 2258 foreach (KeyValuePair<ulong, DateTime> kvp in m_notFoundLocations)
2094 { 2259 {
2095 if (m_toRemove == null) 2260 if (kvp.Value < now)
2096 m_toRemove = new List<NotFoundLocation>(); 2261 m_toRemove.Add(kvp.Key);
2097 m_toRemove.Add(nfl); 2262 }
2263
2264 if (m_toRemove.Count > 0)
2265 {
2266 foreach (ulong u in m_toRemove)
2267 m_notFoundLocations.Remove(u);
2268 m_toRemove.Clear();
2098 } 2269 }
2099 }
2100 if (m_toRemove != null)
2101 {
2102 foreach (NotFoundLocation nfl in m_toRemove)
2103 m_notFoundLocations.Remove(nfl);
2104 m_toRemove.Clear();
2105 } 2270 }
2106 } 2271 }
2107 } 2272 }
2273
2108 #endregion // NotFoundLocationCache class 2274 #endregion // NotFoundLocationCache class
2275 #region getregions
2109 private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache(); 2276 private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache();
2110 2277
2111 // Given a world position (fractional meter coordinate), get the GridRegion info for 2278 protected GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
2279 {
2280 // Since we don't know how big the regions could be, we have to search a very large area
2281 // to find possible regions.
2282 return GetRegionContainingWorldLocation(pGridService, pScopeID, px, py, Constants.MaximumRegionSize);
2283 }
2284
2285 // Given a world position, get the GridRegion info for
2112 // the region containing that point. 2286 // the region containing that point.
2113 // Someday this should be a method on GridService. 2287 // for compatibility with old grids it does a scan to find large regions
2114 // 'pSizeHint' is the size of the source region but since the destination point can be anywhere 2288 // 0.9 grids to that
2115 // the size of the target region is unknown thus the search area might have to be very large. 2289
2116 // Return 'null' if no such region exists. 2290 protected GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID,
2117 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID,
2118 double px, double py, uint pSizeHint) 2291 double px, double py, uint pSizeHint)
2119 { 2292 {
2120 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: query, loc=<{1},{2}>", LogHeader, px, py); 2293// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: call, XY=<{1},{2}>", LogHeader, px, py);
2121 GridRegion ret = null; 2294 GridRegion ret = null;
2122 const double fudge = 2.0;
2123 2295
2124 // One problem with this routine is negative results. That is, this can be called lots of times
2125 // for regions that don't exist. m_notFoundLocationCache remembers 'not found' results so they
2126 // will be quick 'not found's next time.
2127 // NotFoundLocationCache is an expiring cache so it will eventually forget about 'not found' and
2128 // thus re-ask the GridService about the location.
2129 if (m_notFoundLocationCache.Contains(px, py)) 2296 if (m_notFoundLocationCache.Contains(px, py))
2130 { 2297 {
2131 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py); 2298// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py);
2132 return null; 2299 return null;
2133 } 2300 }
2134 2301
2135 // As an optimization, since most regions will be legacy sized regions (256x256), first try to get 2302 // As an optimization, since most regions will be legacy sized regions (256x256), first try to get
2136 // the region at the appropriate legacy region location. 2303 // the region at the appropriate legacy region location.
2137 uint possibleX = (uint)Math.Floor(px); 2304 // this is all that is needed on 0.9 grids
2138 possibleX -= possibleX % Constants.RegionSize; 2305 uint possibleX = (uint)px & 0xffffff00u;
2139 uint possibleY = (uint)Math.Floor(py); 2306 uint possibleY = (uint)py & 0xffffff00u;
2140 possibleY -= possibleY % Constants.RegionSize;
2141 ret = pGridService.GetRegionByPosition(pScopeID, (int)possibleX, (int)possibleY); 2307 ret = pGridService.GetRegionByPosition(pScopeID, (int)possibleX, (int)possibleY);
2142 if (ret != null) 2308 if (ret != null)
2143 { 2309 {
2144 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Found region using legacy size. rloc=<{1},{2}>. Rname={3}", 2310// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Found region using legacy size. rloc=<{1},{2}>. Rname={3}",
2145 LogHeader, possibleX, possibleY, ret.RegionName); 2311// LogHeader, possibleX, possibleY, ret.RegionName);
2312 return ret;
2146 } 2313 }
2147 2314
2148 if (ret == null) 2315 // for 0.8 regions just make a BIG area request. old code whould do it plus 4 more smaller on region open edges
2316 // this is what 0.9 grids now do internally
2317 List<GridRegion> possibleRegions = pGridService.GetRegionRange(pScopeID,
2318 (int)(px - Constants.MaximumRegionSize), (int)(px + 1), // +1 bc left mb not part of range
2319 (int)(py - Constants.MaximumRegionSize), (int)(py + 1));
2320// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegions cnt={1}, range={2}",
2321// LogHeader, possibleRegions.Count, range);
2322 if (possibleRegions != null && possibleRegions.Count > 0)
2149 { 2323 {
2150 // If the simple lookup failed, search the larger area for a region that contains this point 2324 // If we found some regions, check to see if the point is within
2151 double range = (double)pSizeHint + fudge; 2325 foreach (GridRegion gr in possibleRegions)
2152 while (ret == null && range <= (Constants.MaximumRegionSize + Constants.RegionSize))
2153 { 2326 {
2154 // Get from the grid service a list of regions that might contain this point. 2327// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegion nm={1}, regionLoc=<{2},{3}>, regionSize=<{4},{5}>",
2155 // The region origin will be in the zero direction so only subtract the range. 2328// LogHeader, gr.RegionName, gr.RegionLocX, gr.RegionLocY, gr.RegionSizeX, gr.RegionSizeY);
2156 List<GridRegion> possibleRegions = pGridService.GetRegionRange(pScopeID, 2329 if (px >= (double)gr.RegionLocX && px < (double)(gr.RegionLocX + gr.RegionSizeX)
2157 (int)(px - range), (int)(px),
2158 (int)(py - range), (int)(py));
2159 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegions cnt={1}, range={2}",
2160 LogHeader, possibleRegions.Count, range);
2161 if (possibleRegions != null && possibleRegions.Count > 0)
2162 {
2163 // If we found some regions, check to see if the point is within
2164 foreach (GridRegion gr in possibleRegions)
2165 {
2166 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegion nm={1}, regionLoc=<{2},{3}>, regionSize=<{4},{5}>",
2167 LogHeader, gr.RegionName, gr.RegionLocX, gr.RegionLocY, gr.RegionSizeX, gr.RegionSizeY);
2168 if (px >= (double)gr.RegionLocX && px < (double)(gr.RegionLocX + gr.RegionSizeX)
2169 && py >= (double)gr.RegionLocY && py < (double)(gr.RegionLocY + gr.RegionSizeY)) 2330 && py >= (double)gr.RegionLocY && py < (double)(gr.RegionLocY + gr.RegionSizeY))
2170 { 2331 {
2171 // Found a region that contains the point 2332 // Found a region that contains the point
2172 ret = gr; 2333 return gr;
2173 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: found. RegionName={1}", LogHeader, ret.RegionName); 2334// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: found. RegionName={1}", LogHeader, ret.RegionName);
2174 break;
2175 }
2176 }
2177 } 2335 }
2178 // Larger search area for next time around if not found
2179 range *= 2;
2180 } 2336 }
2181 } 2337 }
2182 2338
2183 if (ret == null) 2339 // remember this location was not found so we can quickly not find it next time
2184 { 2340 m_notFoundLocationCache.Add(px, py);
2185 // remember this location was not found so we can quickly not find it next time 2341// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found. Remembering loc=<{1},{2}>", LogHeader, px, py);
2186 m_notFoundLocationCache.Add(px, py); 2342 return null;
2187 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found. Remembering loc=<{1},{2}>", LogHeader, px, py);
2188 }
2189
2190 return ret;
2191 } 2343 }
2192 2344
2193 private void InformClientOfNeighbourCompleted(IAsyncResult iar) 2345 private void InformClientOfNeighbourCompleted(IAsyncResult iar)
@@ -2207,81 +2359,65 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2207 /// <param name="a"></param> 2359 /// <param name="a"></param>
2208 /// <param name="regionHandle"></param> 2360 /// <param name="regionHandle"></param>
2209 /// <param name="endPoint"></param> 2361 /// <param name="endPoint"></param>
2210 private void InformClientOfNeighbourAsync(ScenePresence sp, AgentCircuitData a, GridRegion reg, 2362 private void InformClientOfNeighbourAsync(ScenePresence sp, AgentCircuitData agentCircData, GridRegion reg,
2211 IPEndPoint endPoint, bool newAgent) 2363 IPEndPoint endPoint, bool newAgent)
2212 { 2364 {
2213 // Let's wait just a little to give time to originating regions to catch up with closing child agents
2214 // after a cross here
2215 Thread.Sleep(500);
2216 2365
2217 Scene scene = sp.Scene; 2366 if (newAgent)
2218 2367 {
2219 m_log.DebugFormat( 2368 // we may already had lost this sp
2220 "[ENTITY TRANSFER MODULE]: Informing {0} {1} about neighbour {2} {3} at ({4},{5})", 2369 if(sp == null || sp.IsDeleted || sp.ClientView == null) // something bad already happened
2221 sp.Name, sp.UUID, reg.RegionName, endPoint, reg.RegionCoordX, reg.RegionCoordY); 2370 return;
2222 2371
2223 string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(a.CapsPath); 2372 Scene scene = sp.Scene;
2224 2373
2225 string reason = String.Empty; 2374 m_log.DebugFormat(
2375 "[ENTITY TRANSFER MODULE]: Informing {0} {1} about neighbour {2} {3} at ({4},{5})",
2376 sp.Name, sp.UUID, reg.RegionName, endPoint, reg.RegionCoordX, reg.RegionCoordY);
2226 2377
2227 bool regionAccepted = scene.SimulationService.CreateAgent(null, reg, a, (uint)TeleportFlags.Default, out reason); 2378 string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(agentCircData.CapsPath);
2228 2379
2229 if (regionAccepted && newAgent) 2380 string reason = String.Empty;
2230 { 2381
2231 if (m_eqModule != null) 2382 EntityTransferContext ctx = new EntityTransferContext();
2383 bool regionAccepted = scene.SimulationService.CreateAgent(reg, reg, agentCircData, (uint)TeleportFlags.Default, ctx, out reason);
2384
2385 if (regionAccepted)
2232 { 2386 {
2233 #region IP Translation for NAT 2387 // give time for createAgent to finish, since it is async and does grid services access
2234 IClientIPEndpoint ipepClient; 2388 Thread.Sleep(500);
2235 if (sp.ClientView.TryGet(out ipepClient)) 2389
2390 if (m_eqModule != null)
2236 { 2391 {
2237 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); 2392 if(sp == null || sp.IsDeleted || sp.ClientView == null) // something bad already happened
2238 } 2393 return;
2239 #endregion
2240 2394
2241 m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " + 2395 m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " +
2242 "and EstablishAgentCommunication with seed cap {8}", LogHeader, 2396 "and EstablishAgentCommunication with seed cap {8}", LogHeader,
2243 scene.RegionInfo.RegionName, sp.Name, 2397 scene.RegionInfo.RegionName, sp.Name,
2244 reg.RegionName, reg.RegionLocX, reg.RegionLocY, reg.RegionSizeX, reg.RegionSizeY , capsPath); 2398 reg.RegionName, reg.RegionLocX, reg.RegionLocY, reg.RegionSizeX, reg.RegionSizeY, capsPath);
2399
2400 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID, reg.RegionSizeX, reg.RegionSizeY);
2401 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, reg.RegionHandle, reg.RegionSizeX, reg.RegionSizeY);
2402 }
2403 else
2404 {
2405 sp.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
2406 // TODO: make Event Queue disablable!
2407 }
2245 2408
2246 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID, reg.RegionSizeX, reg.RegionSizeY); 2409 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Completed inform {0} {1} about neighbour {2}", sp.Name, sp.UUID, endPoint);
2247 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, reg.RegionHandle, reg.RegionSizeX, reg.RegionSizeY);
2248 } 2410 }
2411
2249 else 2412 else
2250 { 2413 {
2251 sp.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint); 2414 sp.RemoveNeighbourRegion(reg.RegionHandle);
2252 // TODO: make Event Queue disablable! 2415 m_log.WarnFormat(
2416 "[ENTITY TRANSFER MODULE]: Region {0} did not accept {1} {2}: {3}",
2417 reg.RegionName, sp.Name, sp.UUID, reason);
2253 } 2418 }
2254
2255 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Completed inform {0} {1} about neighbour {2}", sp.Name, sp.UUID, endPoint);
2256 } 2419 }
2257 2420
2258 if (!regionAccepted)
2259 m_log.WarnFormat(
2260 "[ENTITY TRANSFER MODULE]: Region {0} did not accept {1} {2}: {3}",
2261 reg.RegionName, sp.Name, sp.UUID, reason);
2262 }
2263
2264 /// <summary>
2265 /// Gets the range considered in view of this megaregion (assuming this is a megaregion).
2266 /// </summary>
2267 /// <remarks>Expressed in 256m units</remarks>
2268 /// <param name='swCorner'></param>
2269 /// <param name='neCorner'></param>
2270 private void GetMegaregionViewRange(out Vector2 swCorner, out Vector2 neCorner)
2271 {
2272 Vector2 extent = Vector2.Zero;
2273
2274 if (m_regionCombinerModule != null)
2275 {
2276 Vector2 megaRegionSize = m_regionCombinerModule.GetSizeOfMegaregion(Scene.RegionInfo.RegionID);
2277 extent.X = (float)Util.WorldToRegionLoc((uint)megaRegionSize.X);
2278 extent.Y = (float)Util.WorldToRegionLoc((uint)megaRegionSize.Y);
2279 }
2280
2281 swCorner.X = Scene.RegionInfo.RegionLocX - 1;
2282 swCorner.Y = Scene.RegionInfo.RegionLocY - 1;
2283 neCorner.X = Scene.RegionInfo.RegionLocX + extent.X;
2284 neCorner.Y = Scene.RegionInfo.RegionLocY + extent.Y;
2285 } 2421 }
2286 2422
2287 /// <summary> 2423 /// <summary>
@@ -2290,98 +2426,42 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2290 /// <param name="avatar"></param> 2426 /// <param name="avatar"></param>
2291 /// <param name="pRegionLocX"></param> 2427 /// <param name="pRegionLocX"></param>
2292 /// <param name="pRegionLocY"></param> 2428 /// <param name="pRegionLocY"></param>
2293 /// <returns></returns> 2429 /// <returns></returns>
2294 protected List<GridRegion> GetNeighbours(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY) 2430 protected List<GridRegion> GetNeighbors(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY)
2295 { 2431 {
2296 Scene pScene = avatar.Scene; 2432 Scene pScene = avatar.Scene;
2297 RegionInfo m_regionInfo = pScene.RegionInfo; 2433 RegionInfo m_regionInfo = pScene.RegionInfo;
2298 List<GridRegion> neighbours; 2434 List<GridRegion> neighbours;
2299 2435
2300 // Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't 2436 uint dd = (uint)avatar.RegionViewDistance;
2301 // clear what should be done with a "far view" given that megaregions already extended the
2302 // view to include everything in the megaregion
2303 if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
2304 {
2305 // The area to check is as big as the current region.
2306 // We presume all adjacent regions are the same size as this region.
2307 uint dd = Math.Max((uint)avatar.Scene.DefaultDrawDistance,
2308 Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
2309 2437
2310 uint startX = Util.RegionToWorldLoc(pRegionLocX) - dd + Constants.RegionSize/2; 2438 // until avatar movement updates client connections, we need to seend at least this current region imediate neighbors
2311 uint startY = Util.RegionToWorldLoc(pRegionLocY) - dd + Constants.RegionSize/2; 2439 uint ddX = Math.Max(dd, Constants.RegionSize);
2440 uint ddY = Math.Max(dd, Constants.RegionSize);
2312 2441
2313 uint endX = Util.RegionToWorldLoc(pRegionLocX) + dd + Constants.RegionSize/2; 2442 ddX--;
2314 uint endY = Util.RegionToWorldLoc(pRegionLocY) + dd + Constants.RegionSize/2; 2443 ddY--;
2315 2444
2316 neighbours 2445 // reference to region edges. Should be avatar position
2317 = avatar.Scene.GridService.GetRegionRange( 2446 uint startX = Util.RegionToWorldLoc(pRegionLocX);
2318 m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY); 2447 uint endX = startX + m_regionInfo.RegionSizeX;
2319 } 2448 uint startY = Util.RegionToWorldLoc(pRegionLocY);
2320 else 2449 uint endY = startY + m_regionInfo.RegionSizeY;
2321 {
2322 Vector2 swCorner, neCorner;
2323 GetMegaregionViewRange(out swCorner, out neCorner);
2324 2450
2325 neighbours 2451 startX -= ddX;
2326 = pScene.GridService.GetRegionRange( 2452 startY -= ddY;
2327 m_regionInfo.ScopeID, 2453 endX += ddX;
2328 (int)Util.RegionToWorldLoc((uint)swCorner.X), (int)Util.RegionToWorldLoc((uint)neCorner.X), 2454 endY += ddY;
2329 (int)Util.RegionToWorldLoc((uint)swCorner.Y), (int)Util.RegionToWorldLoc((uint)neCorner.Y));
2330 }
2331 2455
2332// neighbours.ForEach( 2456 neighbours
2333// n => 2457 = avatar.Scene.GridService.GetRegionRange(
2334// m_log.DebugFormat( 2458 m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY);
2335// "[ENTITY TRANSFER MODULE]: Region flags for {0} as seen by {1} are {2}",
2336// n.RegionName, Scene.Name, n.RegionFlags != null ? n.RegionFlags.ToString() : "not present"));
2337 2459
2338 // The r.RegionFlags == null check only needs to be made for simulators before 2015-01-14 (pre 0.8.1). 2460 // The r.RegionFlags == null check only needs to be made for simulators before 2015-01-14 (pre 0.8.1).
2339 neighbours.RemoveAll( 2461 neighbours.RemoveAll( r => r.RegionID == m_regionInfo.RegionID );
2340 r =>
2341 r.RegionID == m_regionInfo.RegionID
2342 || (r.RegionFlags != null && (r.RegionFlags & OpenSim.Framework.RegionFlags.RegionOnline) == 0));
2343 2462
2344 return neighbours; 2463 return neighbours;
2345 } 2464 }
2346
2347 private List<ulong> NewNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
2348 {
2349 return currentNeighbours.FindAll(delegate(ulong handle) { return !previousNeighbours.Contains(handle); });
2350 }
2351
2352 // private List<ulong> CommonNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
2353 // {
2354 // return currentNeighbours.FindAll(delegate(ulong handle) { return previousNeighbours.Contains(handle); });
2355 // }
2356
2357 private List<ulong> OldNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
2358 {
2359 return previousNeighbours.FindAll(delegate(ulong handle) { return !currentNeighbours.Contains(handle); });
2360 }
2361
2362 private List<ulong> NeighbourHandles(List<GridRegion> neighbours)
2363 {
2364 List<ulong> handles = new List<ulong>();
2365 foreach (GridRegion reg in neighbours)
2366 {
2367 handles.Add(reg.RegionHandle);
2368 }
2369 return handles;
2370 }
2371
2372// private void Dump(string msg, List<ulong> handles)
2373// {
2374// m_log.InfoFormat("-------------- HANDLE DUMP ({0}) ---------", msg);
2375// foreach (ulong handle in handles)
2376// {
2377// uint x, y;
2378// Utils.LongToUInts(handle, out x, out y);
2379// x = x / Constants.RegionSize;
2380// y = y / Constants.RegionSize;
2381// m_log.InfoFormat("({0}, {1})", x, y);
2382// }
2383// }
2384
2385 #endregion 2465 #endregion
2386 2466
2387 #region Agent Arrived 2467 #region Agent Arrived
@@ -2395,83 +2475,47 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2395 2475
2396 #region Object Transfers 2476 #region Object Transfers
2397 2477
2398 /// <summary> 2478 public GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition,out Vector3 newpos)
2399 /// Move the given scene object into a new region depending on which region its absolute position has moved
2400 /// into.
2401 ///
2402 /// Using the objects new world location, ask the grid service for a the new region and adjust the prim
2403 /// position to be relative to the new region.
2404 /// </summary>
2405 /// <param name="grp">the scene object that we're crossing</param>
2406 /// <param name="attemptedPosition">the attempted out of region position of the scene object. This position is
2407 /// relative to the region the object currently is in.</param>
2408 /// <param name="silent">if 'true', the deletion of the client from the region is not broadcast to the clients</param>
2409 public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent)
2410 { 2479 {
2411 if (grp == null) 2480 newpos = targetPosition;
2412 return;
2413 if (grp.IsDeleted)
2414 return;
2415 2481
2416 Scene scene = grp.Scene; 2482 Scene scene = grp.Scene;
2417 if (scene == null) 2483 if (scene == null)
2418 return; 2484 return null;
2419
2420 if (grp.RootPart.DIE_AT_EDGE)
2421 {
2422 // We remove the object here
2423 try
2424 {
2425 scene.DeleteSceneObject(grp, false);
2426 }
2427 catch (Exception)
2428 {
2429 m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border.");
2430 }
2431 return;
2432 }
2433
2434 // Remember the old group position in case the region lookup fails so position can be restored.
2435 Vector3 oldGroupPosition = grp.RootPart.GroupPosition;
2436 2485
2437 // Compute the absolute position of the object. 2486 int x = (int)targetPosition.X + (int)scene.RegionInfo.WorldLocX;
2438 double objectWorldLocX = (double)scene.RegionInfo.WorldLocX + attemptedPosition.X; 2487 if (targetPosition.X >= 0)
2439 double objectWorldLocY = (double)scene.RegionInfo.WorldLocY + attemptedPosition.Y; 2488 x++;
2489 else
2490 x--;
2440 2491
2441 // Ask the grid service for the region that contains the passed address 2492 int y = (int)targetPosition.Y + (int)scene.RegionInfo.WorldLocY;
2442 GridRegion destination = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID, 2493 if (targetPosition.Y >= 0)
2443 objectWorldLocX, objectWorldLocY); 2494 y++;
2495 else
2496 y--;
2444 2497
2445 Vector3 pos = Vector3.Zero; 2498 GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID,x,y);
2446 if (destination != null) 2499 if (neighbourRegion == null)
2447 { 2500 {
2448 // Adjust the object's relative position from the old region (attemptedPosition) 2501 return null;
2449 // to be relative to the new region (pos).
2450 pos = new Vector3( (float)(objectWorldLocX - (double)destination.RegionLocX),
2451 (float)(objectWorldLocY - (double)destination.RegionLocY),
2452 attemptedPosition.Z);
2453 } 2502 }
2454 2503
2455 if (destination == null || !CrossPrimGroupIntoNewRegion(destination, pos, grp, silent)) 2504 float newRegionSizeX = neighbourRegion.RegionSizeX;
2456 { 2505 float newRegionSizeY = neighbourRegion.RegionSizeY;
2457 m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}", grp.UUID); 2506 if (newRegionSizeX == 0)
2458 2507 newRegionSizeX = Constants.RegionSize;
2459 // We are going to move the object back to the old position so long as the old position 2508 if (newRegionSizeY == 0)
2460 // is in the region 2509 newRegionSizeY = Constants.RegionSize;
2461 oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 1.0f, (float)(scene.RegionInfo.RegionSizeX - 1));
2462 oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 1.0f, (float)(scene.RegionInfo.RegionSizeY - 1));
2463 oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 1.0f, Constants.RegionHeight);
2464 2510
2465 grp.AbsolutePosition = oldGroupPosition; 2511 newpos.X = targetPosition.X - (neighbourRegion.RegionLocX - (int)scene.RegionInfo.WorldLocX);
2466 grp.Velocity = Vector3.Zero; 2512 newpos.Y = targetPosition.Y - (neighbourRegion.RegionLocY - (int)scene.RegionInfo.WorldLocY);
2467 if (grp.RootPart.PhysActor != null)
2468 grp.RootPart.PhysActor.CrossingFailure();
2469 2513
2470 if (grp.RootPart.KeyframeMotion != null) 2514 const float enterDistance = 0.2f;
2471 grp.RootPart.KeyframeMotion.CrossingFailure(); 2515 newpos.X = Util.Clamp(newpos.X, enterDistance, newRegionSizeX - enterDistance);
2516 newpos.Y = Util.Clamp(newpos.Y, enterDistance, newRegionSizeY - enterDistance);
2472 2517
2473 grp.ScheduleGroupForFullUpdate(); 2518 return neighbourRegion;
2474 }
2475 } 2519 }
2476 2520
2477 /// <summary> 2521 /// <summary>
@@ -2483,10 +2527,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2483 /// true if the crossing itself was successful, false on failure 2527 /// true if the crossing itself was successful, false on failure
2484 /// FIMXE: we still return true if the crossing object was not successfully deleted from the originating region 2528 /// FIMXE: we still return true if the crossing object was not successfully deleted from the originating region
2485 /// </returns> 2529 /// </returns>
2486 protected bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent) 2530 public bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent, bool removeScripts)
2487 { 2531 {
2488 //m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<"); 2532 //m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<");
2489 2533
2534 Culture.SetCurrentCulture();
2535
2490 bool successYN = false; 2536 bool successYN = false;
2491 grp.RootPart.ClearUpdateSchedule(); 2537 grp.RootPart.ClearUpdateSchedule();
2492 //int primcrossingXMLmethod = 0; 2538 //int primcrossingXMLmethod = 0;
@@ -2515,7 +2561,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2515 // We remove the object here 2561 // We remove the object here
2516 try 2562 try
2517 { 2563 {
2518 grp.Scene.DeleteSceneObject(grp, silent); 2564 grp.Scene.DeleteSceneObject(grp, silent, removeScripts);
2519 } 2565 }
2520 catch (Exception e) 2566 catch (Exception e)
2521 { 2567 {
@@ -2524,30 +2570,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2524 grp, e); 2570 grp, e);
2525 } 2571 }
2526 } 2572 }
2527/*
2528 * done on caller ( not in attachments crossing for now)
2529 else
2530 {
2531
2532 if (!grp.IsDeleted)
2533 {
2534 PhysicsActor pa = grp.RootPart.PhysActor;
2535 if (pa != null)
2536 {
2537 pa.CrossingFailure();
2538 if (grp.RootPart.KeyframeMotion != null)
2539 {
2540 // moved to KeyframeMotion.CrossingFailure
2541// grp.RootPart.Velocity = Vector3.Zero;
2542 grp.RootPart.KeyframeMotion.CrossingFailure();
2543// grp.SendGroupRootTerseUpdate();
2544 }
2545 }
2546 }
2547
2548 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: Prim crossing failed for {0}", grp);
2549 }
2550 */
2551 } 2573 }
2552 else 2574 else
2553 { 2575 {
@@ -2589,7 +2611,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2589 "[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}", 2611 "[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}",
2590 clone.UUID, destination.RegionName); 2612 clone.UUID, destination.RegionName);
2591 2613
2592 CrossPrimGroupIntoNewRegion(destination, Vector3.Zero, clone, silent); 2614 CrossPrimGroupIntoNewRegion(destination, Vector3.Zero, clone, silent,true);
2593 } 2615 }
2594 } 2616 }
2595 2617
@@ -2639,7 +2661,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2639 if (Scene.RegionInfo.EstateSettings.IsBanned(so.OwnerID)) 2661 if (Scene.RegionInfo.EstateSettings.IsBanned(so.OwnerID))
2640 { 2662 {
2641 m_log.DebugFormat( 2663 m_log.DebugFormat(
2642 "[ENTITY TRANSFER MODULE]: Denied prim crossing of {0} {1} into {2} for banned avatar {3}", 2664 "[ENTITY TRANSFER MODULE]: Denied prim crossing of {0} {1} into {2} for banned avatar {3}",
2643 so.Name, so.UUID, Scene.Name, so.OwnerID); 2665 so.Name, so.UUID, Scene.Name, so.OwnerID);
2644 2666
2645 return false; 2667 return false;
@@ -2651,7 +2673,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2651 if (!Scene.AddSceneObject(so)) 2673 if (!Scene.AddSceneObject(so))
2652 { 2674 {
2653 m_log.DebugFormat( 2675 m_log.DebugFormat(
2654 "[ENTITY TRANSFER MODULE]: Problem adding scene object {0} {1} into {2} ", 2676 "[ENTITY TRANSFER MODULE]: Problem adding scene object {0} {1} into {2} ",
2655 so.Name, so.UUID, Scene.Name); 2677 so.Name, so.UUID, Scene.Name);
2656 2678
2657 return false; 2679 return false;
@@ -2661,7 +2683,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2661 { 2683 {
2662 // FIXME: It would be better to never add the scene object at all rather than add it and then delete 2684 // FIXME: It would be better to never add the scene object at all rather than add it and then delete
2663 // it 2685 // it
2664 if (!Scene.Permissions.CanObjectEntry(so.UUID, true, so.AbsolutePosition)) 2686 if (!Scene.Permissions.CanObjectEntry(so, true, so.AbsolutePosition))
2665 { 2687 {
2666 // Deny non attachments based on parcel settings 2688 // Deny non attachments based on parcel settings
2667 // 2689 //
@@ -2679,8 +2701,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2679 2701
2680 so.ResumeScripts(); 2702 so.ResumeScripts();
2681 2703
2682 if (so.RootPart.KeyframeMotion != null) 2704 // AddSceneObject already does this and doing it again messes
2683 so.RootPart.KeyframeMotion.UpdateSceneObject(so); 2705 //if (so.RootPart.KeyframeMotion != null)
2706 // so.RootPart.KeyframeMotion.UpdateSceneObject(so);
2684 } 2707 }
2685 2708
2686 return true; 2709 return true;