diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 357 |
1 files changed, 199 insertions, 158 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 0eed64e..a7e7294 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -516,6 +516,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
516 | public uint ParentID; | 516 | public uint ParentID; |
517 | } | 517 | } |
518 | 518 | ||
519 | |||
520 | public bool inTransit = false; | ||
521 | public delegate SceneObjectGroup SOGCrossDelegate(SceneObjectGroup sog,Vector3 pos); | ||
522 | |||
519 | /// <summary> | 523 | /// <summary> |
520 | /// The absolute position of this scene object in the scene | 524 | /// The absolute position of this scene object in the scene |
521 | /// </summary> | 525 | /// </summary> |
@@ -525,8 +529,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
525 | set | 529 | set |
526 | { | 530 | { |
527 | Vector3 val = value; | 531 | Vector3 val = value; |
528 | 532 | ||
529 | if (Scene != null) | 533 | if (Scene != null && !inTransit) |
530 | { | 534 | { |
531 | if ( | 535 | if ( |
532 | // (Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) | 536 | // (Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) |
@@ -543,130 +547,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
543 | || Scene.TestBorderCross(val, Cardinals.S)) | 547 | || Scene.TestBorderCross(val, Cardinals.S)) |
544 | && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) | 548 | && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) |
545 | { | 549 | { |
546 | IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); | 550 | inTransit = true; |
547 | uint x = 0; | 551 | SOGCrossDelegate d = CrossAsync; |
548 | uint y = 0; | 552 | d.BeginInvoke(this, val, CrossAsyncCompleted, d); |
549 | string version = String.Empty; | 553 | return; |
550 | Vector3 newpos = Vector3.Zero; | ||
551 | OpenSim.Services.Interfaces.GridRegion destination = null; | ||
552 | |||
553 | if (m_rootPart.DIE_AT_EDGE || m_rootPart.RETURN_AT_EDGE) | ||
554 | { | ||
555 | // this should delete the grp in this case | ||
556 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); | ||
557 | // actually assume this sog was removed from simulation | ||
558 | return; | ||
559 | } | ||
560 | |||
561 | if (m_rootPart.KeyframeMotion != null) | ||
562 | m_rootPart.KeyframeMotion.StartCrossingCheck(); | ||
563 | |||
564 | bool canCross = true; | ||
565 | |||
566 | foreach (ScenePresence av in m_linkedAvatars) | ||
567 | { | ||
568 | // We need to cross these agents. First, let's find | ||
569 | // out if any of them can't cross for some reason. | ||
570 | // We have to deny the crossing entirely if any | ||
571 | // of them are banned. Alternatively, we could | ||
572 | // unsit banned agents.... | ||
573 | |||
574 | |||
575 | // We set the avatar position as being the object | ||
576 | // position to get the region to send to | ||
577 | if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null) | ||
578 | { | ||
579 | canCross = false; | ||
580 | break; | ||
581 | } | ||
582 | |||
583 | m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); | ||
584 | } | ||
585 | |||
586 | if (canCross) | ||
587 | { | ||
588 | // We unparent the SP quietly so that it won't | ||
589 | // be made to stand up | ||
590 | |||
591 | List<avtocrossInfo> avsToCross = new List<avtocrossInfo>(); | ||
592 | |||
593 | foreach (ScenePresence av in m_linkedAvatars) | ||
594 | { | ||
595 | avtocrossInfo avinfo = new avtocrossInfo(); | ||
596 | SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID); | ||
597 | if (parentPart != null) | ||
598 | av.ParentUUID = parentPart.UUID; | ||
599 | |||
600 | avinfo.av = av; | ||
601 | avinfo.ParentID = av.ParentID; | ||
602 | avsToCross.Add(avinfo); | ||
603 | |||
604 | av.PrevSitOffset = av.OffsetPosition; | ||
605 | av.ParentID = 0; | ||
606 | } | ||
607 | |||
608 | // m_linkedAvatars.Clear(); | ||
609 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); | ||
610 | |||
611 | // Normalize | ||
612 | if (val.X >= Constants.RegionSize) | ||
613 | val.X -= Constants.RegionSize; | ||
614 | if (val.Y >= Constants.RegionSize) | ||
615 | val.Y -= Constants.RegionSize; | ||
616 | if (val.X < 0) | ||
617 | val.X += Constants.RegionSize; | ||
618 | if (val.Y < 0) | ||
619 | val.Y += Constants.RegionSize; | ||
620 | |||
621 | // If it's deleted, crossing was successful | ||
622 | if (IsDeleted) | ||
623 | { | ||
624 | // foreach (ScenePresence av in m_linkedAvatars) | ||
625 | foreach (avtocrossInfo avinfo in avsToCross) | ||
626 | { | ||
627 | ScenePresence av = avinfo.av; | ||
628 | if (!av.IsInTransit) // just in case... | ||
629 | { | ||
630 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val); | ||
631 | |||
632 | av.IsInTransit = true; | ||
633 | |||
634 | CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync; | ||
635 | d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d); | ||
636 | } | ||
637 | else | ||
638 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val); | ||
639 | } | ||
640 | avsToCross.Clear(); | ||
641 | return; | ||
642 | } | ||
643 | else // cross failed, put avas back ?? | ||
644 | { | ||
645 | foreach (avtocrossInfo avinfo in avsToCross) | ||
646 | { | ||
647 | ScenePresence av = avinfo.av; | ||
648 | av.ParentUUID = UUID.Zero; | ||
649 | av.ParentID = avinfo.ParentID; | ||
650 | // m_linkedAvatars.Add(av); | ||
651 | } | ||
652 | } | ||
653 | avsToCross.Clear(); | ||
654 | } | ||
655 | else | ||
656 | { | ||
657 | if (m_rootPart.KeyframeMotion != null) | ||
658 | m_rootPart.KeyframeMotion.CrossingFailure(); | ||
659 | |||
660 | if (RootPart.PhysActor != null) | ||
661 | { | ||
662 | RootPart.PhysActor.CrossingFailure(); | ||
663 | } | ||
664 | } | ||
665 | Vector3 oldp = AbsolutePosition; | ||
666 | val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f); | ||
667 | val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f); | ||
668 | // dont crash land StarShips | ||
669 | // val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f); | ||
670 | } | 554 | } |
671 | } | 555 | } |
672 | 556 | ||
@@ -714,46 +598,197 @@ namespace OpenSim.Region.Framework.Scenes | |||
714 | part.TriggerScriptChangedEvent(Changed.POSITION); | 598 | part.TriggerScriptChangedEvent(Changed.POSITION); |
715 | } | 599 | } |
716 | } | 600 | } |
601 | |||
602 | Scene.EventManager.TriggerParcelPrimCountTainted(); | ||
603 | } | ||
604 | } | ||
717 | 605 | ||
718 | /* | 606 | public SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val) |
719 | This seems not needed and should not be needed: | 607 | { |
720 | sp absolute position depends on sit part absolute position fixed above. | 608 | Scene sogScene = sog.m_scene; |
721 | sp ParentPosition is not used anywhere. | 609 | IEntityTransferModule entityTransfer = sogScene.RequestModuleInterface<IEntityTransferModule>(); |
722 | Since presence is sitting, viewer considers it 'linked' to root prim, so it will move/rotate it | 610 | |
723 | Sending a extra packet with avatar position is not only bandwidth waste, but may cause jitter in viewers due to UPD nature. | 611 | Vector3 newpos = Vector3.Zero; |
724 | 612 | OpenSim.Services.Interfaces.GridRegion destination = null; | |
725 | if (!m_dupeInProgress) | 613 | |
614 | if (sog.RootPart.DIE_AT_EDGE) | ||
615 | { | ||
616 | try | ||
617 | { | ||
618 | sogScene.DeleteSceneObject(sog, false); | ||
619 | } | ||
620 | catch (Exception) | ||
621 | { | ||
622 | m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border."); | ||
623 | } | ||
624 | return sog; | ||
625 | } | ||
626 | |||
627 | if (sog.RootPart.RETURN_AT_EDGE) | ||
628 | { | ||
629 | // We remove the object here | ||
630 | try | ||
631 | { | ||
632 | List<uint> localIDs = new List<uint>(); | ||
633 | localIDs.Add(sog.RootPart.LocalId); | ||
634 | sogScene.AddReturn(sog.OwnerID, sog.Name, sog.AbsolutePosition, | ||
635 | "Returned at region cross"); | ||
636 | sogScene.DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, UUID.Zero); | ||
637 | } | ||
638 | catch (Exception) | ||
639 | { | ||
640 | m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border."); | ||
641 | } | ||
642 | return sog; | ||
643 | } | ||
644 | |||
645 | if (sog.m_rootPart.KeyframeMotion != null) | ||
646 | sog.m_rootPart.KeyframeMotion.StartCrossingCheck(); | ||
647 | |||
648 | if (entityTransfer == null) | ||
649 | return sog; | ||
650 | |||
651 | destination = entityTransfer.GetObjectDestination(sog, val, out newpos); | ||
652 | if (destination == null) | ||
653 | return sog; | ||
654 | |||
655 | if (sog.m_linkedAvatars.Count == 0) | ||
656 | { | ||
657 | entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true); | ||
658 | return sog; | ||
659 | } | ||
660 | |||
661 | string reason = String.Empty; | ||
662 | string version = String.Empty; | ||
663 | |||
664 | foreach (ScenePresence av in sog.m_linkedAvatars) | ||
665 | { | ||
666 | // We need to cross these agents. First, let's find | ||
667 | // out if any of them can't cross for some reason. | ||
668 | // We have to deny the crossing entirely if any | ||
669 | // of them are banned. Alternatively, we could | ||
670 | // unsit banned agents.... | ||
671 | |||
672 | // We set the avatar position as being the object | ||
673 | // position to get the region to send to | ||
674 | if(!entityTransfer.checkAgentAccessToRegion(av, destination, newpos, out version, out reason)) | ||
675 | { | ||
676 | return sog; | ||
677 | } | ||
678 | m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); | ||
679 | } | ||
680 | |||
681 | // We unparent the SP quietly so that it won't | ||
682 | // be made to stand up | ||
683 | |||
684 | List<avtocrossInfo> avsToCross = new List<avtocrossInfo>(); | ||
685 | |||
686 | foreach (ScenePresence av in sog.m_linkedAvatars) | ||
687 | { | ||
688 | avtocrossInfo avinfo = new avtocrossInfo(); | ||
689 | SceneObjectPart parentPart = sogScene.GetSceneObjectPart(av.ParentID); | ||
690 | if (parentPart != null) | ||
691 | av.ParentUUID = parentPart.UUID; | ||
692 | |||
693 | avinfo.av = av; | ||
694 | avinfo.ParentID = av.ParentID; | ||
695 | avsToCross.Add(avinfo); | ||
696 | |||
697 | av.PrevSitOffset = av.OffsetPosition; | ||
698 | av.ParentID = 0; | ||
699 | } | ||
700 | |||
701 | if (entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true)) | ||
702 | { | ||
703 | foreach (avtocrossInfo avinfo in avsToCross) | ||
726 | { | 704 | { |
727 | foreach (ScenePresence av in m_linkedAvatars) | 705 | ScenePresence av = avinfo.av; |
706 | if (!av.IsInTransit) // just in case... | ||
728 | { | 707 | { |
729 | SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID); | 708 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val); |
730 | if (p != null && m_parts.TryGetValue(p.UUID, out p)) | 709 | |
710 | av.IsInTransit = true; | ||
711 | |||
712 | // CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync; | ||
713 | // d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d); | ||
714 | entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, av.Flying, version); | ||
715 | if(av.IsChildAgent) | ||
731 | { | 716 | { |
732 | Vector3 offset = p.GetWorldPosition() - av.ParentPosition; | 717 | if (av.ParentUUID != UUID.Zero) |
733 | av.AbsolutePosition += offset; | 718 | { |
734 | // av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition | 719 | av.ClearControls(); |
735 | av.SendAvatarDataToAllAgents(); | 720 | av.ParentPart = null; |
721 | } | ||
736 | } | 722 | } |
723 | av.ParentUUID = UUID.Zero; | ||
724 | // In any case | ||
725 | av.IsInTransit = false; | ||
726 | |||
727 | m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname); | ||
737 | } | 728 | } |
729 | else | ||
730 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar already in transit {0} to {1}", av.Name, val); | ||
731 | } | ||
732 | avsToCross.Clear(); | ||
733 | return sog; | ||
734 | } | ||
735 | else // cross failed, put avas back ?? | ||
736 | { | ||
737 | foreach (avtocrossInfo avinfo in avsToCross) | ||
738 | { | ||
739 | ScenePresence av = avinfo.av; | ||
740 | av.ParentUUID = UUID.Zero; | ||
741 | av.ParentID = avinfo.ParentID; | ||
738 | } | 742 | } |
739 | */ | ||
740 | //if (m_rootPart.PhysActor != null) | ||
741 | //{ | ||
742 | //m_rootPart.PhysActor.Position = | ||
743 | //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y, | ||
744 | //m_rootPart.GroupPosition.Z); | ||
745 | //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); | ||
746 | //} | ||
747 | |||
748 | if (Scene != null) | ||
749 | Scene.EventManager.TriggerParcelPrimCountTainted(); | ||
750 | } | 743 | } |
744 | avsToCross.Clear(); | ||
745 | |||
746 | return sog; | ||
751 | } | 747 | } |
752 | 748 | ||
753 | public override Vector3 Velocity | 749 | public void CrossAsyncCompleted(IAsyncResult iar) |
754 | { | 750 | { |
755 | get { return RootPart.Velocity; } | 751 | SOGCrossDelegate icon = (SOGCrossDelegate)iar.AsyncState; |
756 | set { RootPart.Velocity = value; } | 752 | SceneObjectGroup sog = icon.EndInvoke(iar); |
753 | |||
754 | if (sog.IsDeleted) | ||
755 | { | ||
756 | sog.inTransit = false; // just in case... | ||
757 | } | ||
758 | else | ||
759 | { | ||
760 | SceneObjectPart rootp = sog.m_rootPart; | ||
761 | Vector3 oldp = rootp.GroupPosition; | ||
762 | oldp.X = Util.Clamp<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f); | ||
763 | oldp.Y = Util.Clamp<float>(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f); | ||
764 | rootp.GroupPosition = oldp; | ||
765 | |||
766 | SceneObjectPart[] parts = sog.m_parts.GetArray(); | ||
767 | |||
768 | foreach (SceneObjectPart part in parts) | ||
769 | { | ||
770 | if (part != rootp) | ||
771 | part.GroupPosition = oldp; | ||
772 | } | ||
773 | |||
774 | foreach (ScenePresence av in sog.m_linkedAvatars) | ||
775 | { | ||
776 | av.sitSOGmoved(); | ||
777 | } | ||
778 | |||
779 | sog.Velocity = Vector3.Zero; | ||
780 | |||
781 | if (sog.m_rootPart.KeyframeMotion != null) | ||
782 | sog.m_rootPart.KeyframeMotion.CrossingFailure(); | ||
783 | |||
784 | if (sog.RootPart.PhysActor != null) | ||
785 | { | ||
786 | sog.RootPart.PhysActor.CrossingFailure(); | ||
787 | } | ||
788 | |||
789 | sog.inTransit = false; | ||
790 | sog.ScheduleGroupForFullUpdate(); | ||
791 | } | ||
757 | } | 792 | } |
758 | 793 | ||
759 | private void CrossAgentToNewRegionCompleted(IAsyncResult iar) | 794 | private void CrossAgentToNewRegionCompleted(IAsyncResult iar) |
@@ -784,6 +819,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
784 | m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); | 819 | m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); |
785 | } | 820 | } |
786 | 821 | ||
822 | public override Vector3 Velocity | ||
823 | { | ||
824 | get { return RootPart.Velocity; } | ||
825 | set { RootPart.Velocity = value; } | ||
826 | } | ||
827 | |||
787 | public override uint LocalId | 828 | public override uint LocalId |
788 | { | 829 | { |
789 | get { return m_rootPart.LocalId; } | 830 | get { return m_rootPart.LocalId; } |
@@ -2620,7 +2661,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2620 | // an object has been deleted from a scene before update was processed. | 2661 | // an object has been deleted from a scene before update was processed. |
2621 | // A more fundamental overhaul of the update mechanism is required to eliminate all | 2662 | // A more fundamental overhaul of the update mechanism is required to eliminate all |
2622 | // the race conditions. | 2663 | // the race conditions. |
2623 | if (IsDeleted) | 2664 | if (IsDeleted || inTransit) |
2624 | return; | 2665 | return; |
2625 | 2666 | ||
2626 | // Even temporary objects take part in physics (e.g. temp-on-rez bullets) | 2667 | // Even temporary objects take part in physics (e.g. temp-on-rez bullets) |
@@ -2736,7 +2777,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2736 | /// </summary> | 2777 | /// </summary> |
2737 | public void SendGroupRootTerseUpdate() | 2778 | public void SendGroupRootTerseUpdate() |
2738 | { | 2779 | { |
2739 | if (IsDeleted) | 2780 | if (IsDeleted || inTransit) |
2740 | return; | 2781 | return; |
2741 | 2782 | ||
2742 | RootPart.SendTerseUpdateToAllClients(); | 2783 | RootPart.SendTerseUpdateToAllClients(); |
@@ -2755,7 +2796,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2755 | /// </summary> | 2796 | /// </summary> |
2756 | public void SendGroupTerseUpdate() | 2797 | public void SendGroupTerseUpdate() |
2757 | { | 2798 | { |
2758 | if (IsDeleted) | 2799 | if (IsDeleted || inTransit) |
2759 | return; | 2800 | return; |
2760 | 2801 | ||
2761 | if (IsAttachment) | 2802 | if (IsAttachment) |