diff options
author | Justin Clark-Casey (justincc) | 2012-05-24 22:26:02 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-05-24 22:26:02 +0100 |
commit | 5c9086ade688b457e9aa9cd0d2099985b7336b71 (patch) | |
tree | 06c20284873e91ed30cda64a6d2dd8c9cbf720ce /OpenSim/Region | |
parent | adding status codes from rfc 6585 (diff) | |
download | opensim-SC-5c9086ade688b457e9aa9cd0d2099985b7336b71.zip opensim-SC-5c9086ade688b457e9aa9cd0d2099985b7336b71.tar.gz opensim-SC-5c9086ade688b457e9aa9cd0d2099985b7336b71.tar.bz2 opensim-SC-5c9086ade688b457e9aa9cd0d2099985b7336b71.tar.xz |
Fix issue where a dns resolution failure on the final destination might leave the user unable to teleport since the transit flag was not being reset.
This moves the 'already in transit' check further up and resets the flag if dns resolution fails and in the new required places.
Diffstat (limited to 'OpenSim/Region')
-rw-r--r-- | OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 392 |
1 files changed, 200 insertions, 192 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 408d63d..4988e93 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | |||
@@ -358,33 +358,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
358 | ScenePresence sp, GridRegion reg, GridRegion finalDestination, | 358 | ScenePresence sp, GridRegion reg, GridRegion finalDestination, |
359 | Vector3 position, Vector3 lookAt, uint teleportFlags) | 359 | Vector3 position, Vector3 lookAt, uint teleportFlags) |
360 | { | 360 | { |
361 | RegionInfo sourceRegion = sp.Scene.RegionInfo; | 361 | // Record that this agent is in transit so that we can prevent simultaneous requests and do later detection |
362 | 362 | // of whether the destination region completes the teleport. | |
363 | if (!IsWithinMaxTeleportDistance(sourceRegion, finalDestination)) | 363 | if (!SetInTransit(sp.UUID)) |
364 | { | 364 | { |
365 | sp.ControllingClient.SendTeleportFailed( | 365 | m_log.DebugFormat( |
366 | string.Format( | 366 | "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.", |
367 | "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way", | 367 | sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); |
368 | finalDestination.RegionName, finalDestination.RegionCoordX, finalDestination.RegionCoordY, | ||
369 | sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY, | ||
370 | MaxTransferDistance)); | ||
371 | 368 | ||
372 | return; | 369 | return; |
373 | } | 370 | } |
374 | 371 | ||
375 | IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>(); | ||
376 | |||
377 | if (reg == null || finalDestination == null) | 372 | if (reg == null || finalDestination == null) |
378 | { | 373 | { |
379 | sp.ControllingClient.SendTeleportFailed("Unable to locate destination"); | 374 | sp.ControllingClient.SendTeleportFailed("Unable to locate destination"); |
380 | return; | 375 | ResetFromTransit(sp.UUID); |
381 | } | ||
382 | |||
383 | if (!SetInTransit(sp.UUID)) // Avie is already on the way. Caller shouldn't do this. | ||
384 | { | ||
385 | m_log.DebugFormat( | ||
386 | "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.", | ||
387 | sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); | ||
388 | 376 | ||
389 | return; | 377 | return; |
390 | } | 378 | } |
@@ -394,6 +382,24 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
394 | sp.Name, sp.UUID, sp.Scene.RegionInfo.RegionName, | 382 | sp.Name, sp.UUID, sp.Scene.RegionInfo.RegionName, |
395 | reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); | 383 | reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); |
396 | 384 | ||
385 | RegionInfo sourceRegion = sp.Scene.RegionInfo; | ||
386 | |||
387 | if (!IsWithinMaxTeleportDistance(sourceRegion, finalDestination)) | ||
388 | { | ||
389 | sp.ControllingClient.SendTeleportFailed( | ||
390 | string.Format( | ||
391 | "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way", | ||
392 | finalDestination.RegionName, finalDestination.RegionCoordX, finalDestination.RegionCoordY, | ||
393 | sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY, | ||
394 | MaxTransferDistance)); | ||
395 | |||
396 | ResetFromTransit(sp.UUID); | ||
397 | |||
398 | return; | ||
399 | } | ||
400 | |||
401 | IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>(); | ||
402 | |||
397 | uint newRegionX = (uint)(reg.RegionHandle >> 40); | 403 | uint newRegionX = (uint)(reg.RegionHandle >> 40); |
398 | uint newRegionY = (((uint)(reg.RegionHandle)) >> 8); | 404 | uint newRegionY = (((uint)(reg.RegionHandle)) >> 8); |
399 | uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40); | 405 | uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40); |
@@ -405,17 +411,24 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
405 | // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field, | 411 | // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field, |
406 | // it's actually doing a lot of work. | 412 | // it's actually doing a lot of work. |
407 | IPEndPoint endPoint = finalDestination.ExternalEndPoint; | 413 | IPEndPoint endPoint = finalDestination.ExternalEndPoint; |
408 | if (endPoint.Address != null) | 414 | |
415 | if (endPoint.Address == null) | ||
409 | { | 416 | { |
410 | // Fixing a bug where teleporting while sitting results in the avatar ending up removed from | 417 | sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); |
411 | // both regions | 418 | ResetFromTransit(sp.UUID); |
412 | if (sp.ParentID != (uint)0) | 419 | |
413 | sp.StandUp(); | 420 | return; |
421 | } | ||
414 | 422 | ||
415 | if (!sp.ValidateAttachments()) | 423 | // Fixing a bug where teleporting while sitting results in the avatar ending up removed from |
416 | m_log.DebugFormat( | 424 | // both regions |
417 | "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.", | 425 | if (sp.ParentID != (uint)0) |
418 | sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName); | 426 | sp.StandUp(); |
427 | |||
428 | if (!sp.ValidateAttachments()) | ||
429 | m_log.DebugFormat( | ||
430 | "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.", | ||
431 | sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName); | ||
419 | 432 | ||
420 | // if (!sp.ValidateAttachments()) | 433 | // if (!sp.ValidateAttachments()) |
421 | // { | 434 | // { |
@@ -423,211 +436,206 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
423 | // return; | 436 | // return; |
424 | // } | 437 | // } |
425 | 438 | ||
426 | string reason; | 439 | string reason; |
427 | string version; | 440 | string version; |
428 | if (!m_scene.SimulationService.QueryAccess( | 441 | if (!m_scene.SimulationService.QueryAccess( |
429 | finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason)) | 442 | finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason)) |
430 | { | 443 | { |
431 | sp.ControllingClient.SendTeleportFailed(reason); | 444 | sp.ControllingClient.SendTeleportFailed(reason); |
432 | ResetFromTransit(sp.UUID); | 445 | ResetFromTransit(sp.UUID); |
433 | 446 | ||
434 | m_log.DebugFormat( | 447 | m_log.DebugFormat( |
435 | "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}", | 448 | "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}", |
436 | sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason); | 449 | sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason); |
437 | 450 | ||
438 | return; | 451 | return; |
439 | } | 452 | } |
440 | 453 | ||
441 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); | 454 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); |
442 | 455 | ||
443 | sp.ControllingClient.SendTeleportStart(teleportFlags); | 456 | sp.ControllingClient.SendTeleportStart(teleportFlags); |
444 | 457 | ||
445 | // the avatar.Close below will clear the child region list. We need this below for (possibly) | 458 | // the avatar.Close below will clear the child region list. We need this below for (possibly) |
446 | // closing the child agents, so save it here (we need a copy as it is Clear()-ed). | 459 | // closing the child agents, so save it here (we need a copy as it is Clear()-ed). |
447 | //List<ulong> childRegions = avatar.KnownRegionHandles; | 460 | //List<ulong> childRegions = avatar.KnownRegionHandles; |
448 | // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport | 461 | // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport |
449 | // failure at this point (unlike a border crossing failure). So perhaps this can never fail | 462 | // failure at this point (unlike a border crossing failure). So perhaps this can never fail |
450 | // once we reach here... | 463 | // once we reach here... |
451 | //avatar.Scene.RemoveCapsHandler(avatar.UUID); | 464 | //avatar.Scene.RemoveCapsHandler(avatar.UUID); |
452 | 465 | ||
453 | string capsPath = String.Empty; | 466 | string capsPath = String.Empty; |
454 | 467 | ||
455 | AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); | 468 | AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); |
456 | AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo(); | 469 | AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo(); |
457 | agentCircuit.startpos = position; | 470 | agentCircuit.startpos = position; |
458 | agentCircuit.child = true; | 471 | agentCircuit.child = true; |
459 | agentCircuit.Appearance = sp.Appearance; | 472 | agentCircuit.Appearance = sp.Appearance; |
460 | if (currentAgentCircuit != null) | 473 | if (currentAgentCircuit != null) |
461 | { | 474 | { |
462 | agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs; | 475 | agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs; |
463 | agentCircuit.IPAddress = currentAgentCircuit.IPAddress; | 476 | agentCircuit.IPAddress = currentAgentCircuit.IPAddress; |
464 | agentCircuit.Viewer = currentAgentCircuit.Viewer; | 477 | agentCircuit.Viewer = currentAgentCircuit.Viewer; |
465 | agentCircuit.Channel = currentAgentCircuit.Channel; | 478 | agentCircuit.Channel = currentAgentCircuit.Channel; |
466 | agentCircuit.Mac = currentAgentCircuit.Mac; | 479 | agentCircuit.Mac = currentAgentCircuit.Mac; |
467 | agentCircuit.Id0 = currentAgentCircuit.Id0; | 480 | agentCircuit.Id0 = currentAgentCircuit.Id0; |
468 | } | 481 | } |
469 | 482 | ||
470 | if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) | 483 | if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) |
471 | { | 484 | { |
472 | // brand new agent, let's create a new caps seed | 485 | // brand new agent, let's create a new caps seed |
473 | agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); | 486 | agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); |
474 | } | 487 | } |
475 | 488 | ||
476 | // Let's create an agent there if one doesn't exist yet. | 489 | // Let's create an agent there if one doesn't exist yet. |
477 | bool logout = false; | 490 | bool logout = false; |
478 | if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) | 491 | if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) |
479 | { | 492 | { |
480 | sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason)); | 493 | sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason)); |
481 | ResetFromTransit(sp.UUID); | 494 | ResetFromTransit(sp.UUID); |
482 | 495 | ||
483 | m_log.DebugFormat( | 496 | m_log.DebugFormat( |
484 | "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}", | 497 | "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}", |
485 | sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason); | 498 | sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason); |
486 | 499 | ||
487 | return; | 500 | return; |
488 | } | 501 | } |
489 | 502 | ||
490 | // OK, it got this agent. Let's close some child agents | 503 | // OK, it got this agent. Let's close some child agents |
491 | sp.CloseChildAgents(newRegionX, newRegionY); | 504 | sp.CloseChildAgents(newRegionX, newRegionY); |
492 | 505 | ||
493 | IClientIPEndpoint ipepClient; | 506 | IClientIPEndpoint ipepClient; |
494 | if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) | 507 | if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) |
508 | { | ||
509 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); | ||
510 | #region IP Translation for NAT | ||
511 | // Uses ipepClient above | ||
512 | if (sp.ClientView.TryGet(out ipepClient)) | ||
495 | { | 513 | { |
496 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); | 514 | endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); |
497 | #region IP Translation for NAT | 515 | } |
498 | // Uses ipepClient above | 516 | #endregion |
499 | if (sp.ClientView.TryGet(out ipepClient)) | 517 | capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); |
500 | { | ||
501 | endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); | ||
502 | } | ||
503 | #endregion | ||
504 | capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); | ||
505 | 518 | ||
506 | if (eq != null) | 519 | if (eq != null) |
507 | { | 520 | { |
508 | eq.EnableSimulator(destinationHandle, endPoint, sp.UUID); | 521 | eq.EnableSimulator(destinationHandle, endPoint, sp.UUID); |
509 | 522 | ||
510 | // ES makes the client send a UseCircuitCode message to the destination, | 523 | // ES makes the client send a UseCircuitCode message to the destination, |
511 | // which triggers a bunch of things there. | 524 | // which triggers a bunch of things there. |
512 | // So let's wait | 525 | // So let's wait |
513 | Thread.Sleep(200); | 526 | Thread.Sleep(200); |
514 | 527 | ||
515 | eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); | 528 | eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); |
516 | 529 | ||
517 | } | ||
518 | else | ||
519 | { | ||
520 | sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); | ||
521 | } | ||
522 | } | 530 | } |
523 | else | 531 | else |
524 | { | 532 | { |
525 | agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle); | 533 | sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); |
526 | capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); | ||
527 | } | 534 | } |
535 | } | ||
536 | else | ||
537 | { | ||
538 | agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle); | ||
539 | capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); | ||
540 | } | ||
528 | 541 | ||
529 | // Let's send a full update of the agent. This is a synchronous call. | 542 | // Let's send a full update of the agent. This is a synchronous call. |
530 | AgentData agent = new AgentData(); | 543 | AgentData agent = new AgentData(); |
531 | sp.CopyTo(agent); | 544 | sp.CopyTo(agent); |
532 | agent.Position = position; | 545 | agent.Position = position; |
533 | SetCallbackURL(agent, sp.Scene.RegionInfo); | 546 | SetCallbackURL(agent, sp.Scene.RegionInfo); |
534 | 547 | ||
535 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); | 548 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); |
536 | 549 | ||
537 | if (!UpdateAgent(reg, finalDestination, agent)) | 550 | if (!UpdateAgent(reg, finalDestination, agent)) |
538 | { | 551 | { |
539 | // Region doesn't take it | 552 | // Region doesn't take it |
540 | m_log.WarnFormat( | 553 | m_log.WarnFormat( |
541 | "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Returning avatar to source region.", | 554 | "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Returning avatar to source region.", |
542 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); | 555 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); |
543 | 556 | ||
544 | Fail(sp, finalDestination, logout); | 557 | Fail(sp, finalDestination, logout); |
545 | return; | 558 | return; |
546 | } | 559 | } |
547 | 560 | ||
548 | sp.ControllingClient.SendTeleportProgress(teleportFlags | (uint)TeleportFlags.DisableCancel, "sending_dest"); | 561 | sp.ControllingClient.SendTeleportProgress(teleportFlags | (uint)TeleportFlags.DisableCancel, "sending_dest"); |
549 | 562 | ||
550 | m_log.DebugFormat( | 563 | m_log.DebugFormat( |
551 | "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", | 564 | "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", |
552 | capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); | 565 | capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); |
553 | 566 | ||
554 | if (eq != null) | 567 | if (eq != null) |
555 | { | 568 | { |
556 | eq.TeleportFinishEvent(destinationHandle, 13, endPoint, | 569 | eq.TeleportFinishEvent(destinationHandle, 13, endPoint, |
557 | 0, teleportFlags, capsPath, sp.UUID); | 570 | 0, teleportFlags, capsPath, sp.UUID); |
558 | } | 571 | } |
559 | else | 572 | else |
560 | { | 573 | { |
561 | sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4, | 574 | sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4, |
562 | teleportFlags, capsPath); | 575 | teleportFlags, capsPath); |
563 | } | 576 | } |
564 | 577 | ||
565 | // Let's set this to true tentatively. This does not trigger OnChildAgent | 578 | // Let's set this to true tentatively. This does not trigger OnChildAgent |
566 | sp.IsChildAgent = true; | 579 | sp.IsChildAgent = true; |
567 | 580 | ||
568 | // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which | 581 | // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which |
569 | // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation | 582 | // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation |
570 | // that the client contacted the destination before we close things here. | 583 | // that the client contacted the destination before we close things here. |
571 | if (EnableWaitForCallbackFromTeleportDest && !WaitForCallback(sp.UUID)) | 584 | if (EnableWaitForCallbackFromTeleportDest && !WaitForCallback(sp.UUID)) |
572 | { | 585 | { |
573 | m_log.WarnFormat( | 586 | m_log.WarnFormat( |
574 | "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", | 587 | "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", |
575 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); | 588 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); |
576 | 589 | ||
577 | Fail(sp, finalDestination, logout); | 590 | Fail(sp, finalDestination, logout); |
578 | return; | 591 | return; |
579 | } | 592 | } |
580 | 593 | ||
581 | // For backwards compatibility | 594 | // For backwards compatibility |
582 | if (version == "Unknown" || version == string.Empty) | 595 | if (version == "Unknown" || version == string.Empty) |
583 | { | 596 | { |
584 | // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it | 597 | // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it |
585 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Old simulator, sending attachments one by one..."); | 598 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Old simulator, sending attachments one by one..."); |
586 | CrossAttachmentsIntoNewRegion(finalDestination, sp, true); | 599 | CrossAttachmentsIntoNewRegion(finalDestination, sp, true); |
587 | } | 600 | } |
588 | 601 | ||
589 | // May need to logout or other cleanup | 602 | // May need to logout or other cleanup |
590 | AgentHasMovedAway(sp, logout); | 603 | AgentHasMovedAway(sp, logout); |
591 | 604 | ||
592 | // Well, this is it. The agent is over there. | 605 | // Well, this is it. The agent is over there. |
593 | KillEntity(sp.Scene, sp.LocalId); | 606 | KillEntity(sp.Scene, sp.LocalId); |
594 | 607 | ||
595 | // Now let's make it officially a child agent | 608 | // Now let's make it officially a child agent |
596 | sp.MakeChildAgent(); | 609 | sp.MakeChildAgent(); |
597 | 610 | ||
598 | // sp.Scene.CleanDroppedAttachments(); | 611 | // sp.Scene.CleanDroppedAttachments(); |
599 | 612 | ||
600 | // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone | 613 | // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone |
601 | |||
602 | if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) | ||
603 | { | ||
604 | // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before | ||
605 | // they regard the new region as the current region after receiving the AgentMovementComplete | ||
606 | // response. If close is sent before then, it will cause the viewer to quit instead. | ||
607 | // However, if this delay is longer, then a viewer can teleport back to this region and experience | ||
608 | // a failure because the old ScenePresence has not yet been cleaned up. | ||
609 | Thread.Sleep(2000); | ||
610 | |||
611 | sp.Close(); | ||
612 | sp.Scene.IncomingCloseAgent(sp.UUID); | ||
613 | } | ||
614 | else | ||
615 | { | ||
616 | // now we have a child agent in this region. | ||
617 | sp.Reset(); | ||
618 | } | ||
619 | 614 | ||
620 | // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! | 615 | if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) |
621 | if (sp.Scene.NeedSceneCacheClear(sp.UUID)) | 616 | { |
622 | { | 617 | // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before |
623 | m_log.DebugFormat( | 618 | // they regard the new region as the current region after receiving the AgentMovementComplete |
624 | "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", | 619 | // response. If close is sent before then, it will cause the viewer to quit instead. |
625 | sp.UUID); | 620 | // However, if this delay is longer, then a viewer can teleport back to this region and experience |
626 | } | 621 | // a failure because the old ScenePresence has not yet been cleaned up. |
622 | Thread.Sleep(2000); | ||
623 | |||
624 | sp.Close(); | ||
625 | sp.Scene.IncomingCloseAgent(sp.UUID); | ||
627 | } | 626 | } |
628 | else | 627 | else |
629 | { | 628 | { |
630 | sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); | 629 | // now we have a child agent in this region. |
630 | sp.Reset(); | ||
631 | } | ||
632 | |||
633 | // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! | ||
634 | if (sp.Scene.NeedSceneCacheClear(sp.UUID)) | ||
635 | { | ||
636 | m_log.DebugFormat( | ||
637 | "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", | ||
638 | sp.UUID); | ||
631 | } | 639 | } |
632 | } | 640 | } |
633 | 641 | ||