diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 1675 |
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; |