diff options
-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 | ||