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