diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 455 |
1 files changed, 164 insertions, 291 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 090f379..c16ba12 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -35,6 +35,7 @@ using log4net; | |||
35 | using OpenSim.Framework; | 35 | using OpenSim.Framework; |
36 | using OpenSim.Region.Framework.Scenes.Types; | 36 | using OpenSim.Region.Framework.Scenes.Types; |
37 | using OpenSim.Region.Physics.Manager; | 37 | using OpenSim.Region.Physics.Manager; |
38 | using OpenSim.Region.Framework.Interfaces; | ||
38 | 39 | ||
39 | namespace OpenSim.Region.Framework.Scenes | 40 | namespace OpenSim.Region.Framework.Scenes |
40 | { | 41 | { |
@@ -69,6 +70,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
69 | 70 | ||
70 | protected Dictionary<UUID, ScenePresence> m_scenePresences = new Dictionary<UUID, ScenePresence>(); | 71 | protected Dictionary<UUID, ScenePresence> m_scenePresences = new Dictionary<UUID, ScenePresence>(); |
71 | protected ScenePresence[] m_scenePresenceArray = new ScenePresence[0]; | 72 | protected ScenePresence[] m_scenePresenceArray = new ScenePresence[0]; |
73 | protected List<ScenePresence> m_scenePresenceList = new List<ScenePresence>(); | ||
74 | |||
75 | protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim(); | ||
72 | 76 | ||
73 | // SceneObjects is not currently populated or used. | 77 | // SceneObjects is not currently populated or used. |
74 | //public Dictionary<UUID, SceneObjectGroup> SceneObjects; | 78 | //public Dictionary<UUID, SceneObjectGroup> SceneObjects; |
@@ -131,10 +135,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
131 | 135 | ||
132 | protected internal void Close() | 136 | protected internal void Close() |
133 | { | 137 | { |
134 | lock (m_scenePresences) | 138 | m_scenePresencesLock.EnterWriteLock(); |
139 | try | ||
135 | { | 140 | { |
136 | m_scenePresences.Clear(); | 141 | m_scenePresences.Clear(); |
137 | m_scenePresenceArray = new ScenePresence[0]; | 142 | m_scenePresenceArray = new ScenePresence[0]; |
143 | m_scenePresenceList = new List<ScenePresence>(); | ||
144 | } | ||
145 | finally | ||
146 | { | ||
147 | m_scenePresencesLock.ExitWriteLock(); | ||
138 | } | 148 | } |
139 | 149 | ||
140 | lock (m_dictionary_lock) | 150 | lock (m_dictionary_lock) |
@@ -164,9 +174,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
164 | 174 | ||
165 | protected internal void UpdatePresences() | 175 | protected internal void UpdatePresences() |
166 | { | 176 | { |
167 | ScenePresence[] updateScenePresences = GetScenePresences(); | 177 | ForEachScenePresence(delegate(ScenePresence presence) |
168 | for (int i = 0; i < updateScenePresences.Length; i++) | 178 | { |
169 | updateScenePresences[i].Update(); | 179 | presence.Update(); |
180 | }); | ||
170 | } | 181 | } |
171 | 182 | ||
172 | protected internal float UpdatePhysics(double elapsed) | 183 | protected internal float UpdatePhysics(double elapsed) |
@@ -195,9 +206,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
195 | 206 | ||
196 | protected internal void UpdateScenePresenceMovement() | 207 | protected internal void UpdateScenePresenceMovement() |
197 | { | 208 | { |
198 | ScenePresence[] moveEntities = GetScenePresences(); | 209 | ForEachScenePresence(delegate(ScenePresence presence) |
199 | for (int i = 0; i < moveEntities.Length; i++) | 210 | { |
200 | moveEntities[i].UpdateMovement(); | 211 | presence.UpdateMovement(); |
212 | }); | ||
201 | } | 213 | } |
202 | 214 | ||
203 | #endregion | 215 | #endregion |
@@ -464,9 +476,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
464 | { | 476 | { |
465 | SceneObjectGroup group = GetGroupByPrim(objectLocalID); | 477 | SceneObjectGroup group = GetGroupByPrim(objectLocalID); |
466 | if (group != null) | 478 | if (group != null) |
467 | { | 479 | m_parentScene.AttachmentsModule.DetachSingleAttachmentToGround(group.UUID, remoteClient); |
468 | m_parentScene.DetachSingleAttachmentToGround(group.UUID, remoteClient); | ||
469 | } | ||
470 | } | 480 | } |
471 | 481 | ||
472 | protected internal void DetachObject(uint objectLocalID, IClientAPI remoteClient) | 482 | protected internal void DetachObject(uint objectLocalID, IClientAPI remoteClient) |
@@ -475,7 +485,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
475 | if (group != null) | 485 | if (group != null) |
476 | { | 486 | { |
477 | //group.DetachToGround(); | 487 | //group.DetachToGround(); |
478 | m_parentScene.DetachSingleAttachmentToInv(group.GetFromItemID(), remoteClient); | 488 | m_parentScene.AttachmentsModule.ShowDetachInUserInventory(group.GetFromItemID(), remoteClient); |
479 | } | 489 | } |
480 | } | 490 | } |
481 | 491 | ||
@@ -509,212 +519,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
509 | } | 519 | } |
510 | } | 520 | } |
511 | 521 | ||
512 | /// <summary> | ||
513 | /// Event Handling routine for Attach Object | ||
514 | /// </summary> | ||
515 | /// <param name="remoteClient"></param> | ||
516 | /// <param name="objectLocalID"></param> | ||
517 | /// <param name="AttachmentPt"></param> | ||
518 | /// <param name="rot"></param> | ||
519 | protected internal void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent) | ||
520 | { | ||
521 | // If we can't take it, we can't attach it! | ||
522 | SceneObjectPart part = m_parentScene.GetSceneObjectPart(objectLocalID); | ||
523 | if (part == null) | ||
524 | return; | ||
525 | |||
526 | if (!m_parentScene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId)) | ||
527 | return; | ||
528 | |||
529 | // Calls attach with a Zero position | ||
530 | if (AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false)) | ||
531 | { | ||
532 | m_parentScene.SendAttachEvent(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); | ||
533 | |||
534 | // Save avatar attachment information | ||
535 | ScenePresence presence; | ||
536 | if (m_parentScene.AvatarFactory != null && m_parentScene.TryGetAvatar(remoteClient.AgentId, out presence)) | ||
537 | { | ||
538 | m_log.Info( | ||
539 | "[SCENE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId | ||
540 | + ", AttachmentPoint: " + AttachmentPt); | ||
541 | |||
542 | m_parentScene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); | ||
543 | } | ||
544 | } | ||
545 | } | ||
546 | |||
547 | /// <summary> | ||
548 | /// Rez an attachment | ||
549 | /// </summary> | ||
550 | /// <param name="remoteClient"></param> | ||
551 | /// <param name="itemID"></param> | ||
552 | /// <param name="AttachmentPt"></param> | ||
553 | /// <returns>The scene object that was attached. Null if the scene object could not be found</returns> | ||
554 | public SceneObjectGroup RezSingleAttachment(IClientAPI remoteClient, UUID itemID, uint AttachmentPt) | ||
555 | { | ||
556 | SceneObjectGroup objatt = m_parentScene.RezObject(remoteClient, | ||
557 | itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | ||
558 | false, false, remoteClient.AgentId, true); | ||
559 | |||
560 | // m_log.DebugFormat( | ||
561 | // "[SCENE GRAPH]: Retrieved single object {0} for attachment to {1} on point {2}", | ||
562 | // objatt.Name, remoteClient.Name, AttachmentPt); | ||
563 | |||
564 | if (objatt != null) | ||
565 | { | ||
566 | bool tainted = false; | ||
567 | if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint()) | ||
568 | tainted = true; | ||
569 | |||
570 | AttachObject(remoteClient, objatt.LocalId, AttachmentPt, Quaternion.Identity, objatt.AbsolutePosition, false); | ||
571 | //objatt.ScheduleGroupForFullUpdate(); | ||
572 | |||
573 | if (tainted) | ||
574 | objatt.HasGroupChanged = true; | ||
575 | |||
576 | // Fire after attach, so we don't get messy perms dialogs | ||
577 | // 3 == AttachedRez | ||
578 | objatt.CreateScriptInstances(0, true, m_parentScene.DefaultScriptEngine, 3); | ||
579 | |||
580 | // Do this last so that event listeners have access to all the effects of the attachment | ||
581 | m_parentScene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId); | ||
582 | } | ||
583 | else | ||
584 | { | ||
585 | m_log.WarnFormat( | ||
586 | "[SCENE GRAPH]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", | ||
587 | itemID, remoteClient.Name, AttachmentPt); | ||
588 | } | ||
589 | |||
590 | return objatt; | ||
591 | } | ||
592 | |||
593 | // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards. | ||
594 | // To LocalId or UUID, *THAT* is the question. How now Brown UUID?? | ||
595 | public void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient) | ||
596 | { | ||
597 | if (itemID == UUID.Zero) // If this happened, someone made a mistake.... | ||
598 | return; | ||
599 | |||
600 | // We can NOT use the dictionries here, as we are looking | ||
601 | // for an entity by the fromAssetID, which is NOT the prim UUID | ||
602 | // | ||
603 | List<EntityBase> detachEntities = GetEntities(); | ||
604 | SceneObjectGroup group; | ||
605 | |||
606 | foreach (EntityBase entity in detachEntities) | ||
607 | { | ||
608 | if (entity is SceneObjectGroup) | ||
609 | { | ||
610 | group = (SceneObjectGroup)entity; | ||
611 | if (group.GetFromItemID() == itemID) | ||
612 | { | ||
613 | m_parentScene.SendAttachEvent(group.LocalId, itemID, UUID.Zero); | ||
614 | bool hasScripts = false; | ||
615 | foreach (SceneObjectPart part in group.Children.Values) | ||
616 | { | ||
617 | if (part.Inventory.ContainsScripts()) | ||
618 | { | ||
619 | hasScripts = true; | ||
620 | break; | ||
621 | } | ||
622 | } | ||
623 | |||
624 | if (hasScripts) // Allow the object to execute the attach(NULL_KEY) event | ||
625 | System.Threading.Thread.Sleep(100); | ||
626 | group.DetachToInventoryPrep(); | ||
627 | m_log.Debug("[DETACH]: Saving attachpoint: " + | ||
628 | ((uint)group.GetAttachmentPoint()).ToString()); | ||
629 | m_parentScene.UpdateKnownItem(remoteClient, group, | ||
630 | group.GetFromItemID(), group.OwnerID); | ||
631 | m_parentScene.DeleteSceneObject(group, false); | ||
632 | return; | ||
633 | } | ||
634 | } | ||
635 | } | ||
636 | } | ||
637 | |||
638 | /// <summary> | ||
639 | /// Attach a scene object to an avatar. | ||
640 | /// </summary> | ||
641 | /// <param name="remoteClient"></param> | ||
642 | /// <param name="objectLocalID"></param> | ||
643 | /// <param name="AttachmentPt"></param> | ||
644 | /// <param name="rot"></param> | ||
645 | /// <param name="attachPos"></param> | ||
646 | /// <param name="silent"></param> | ||
647 | /// <returns>true if the attachment was successful, false otherwise</returns> | ||
648 | protected internal bool AttachObject( | ||
649 | IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent) | ||
650 | { | ||
651 | SceneObjectGroup group = GetGroupByPrim(objectLocalID); | ||
652 | if (group != null) | ||
653 | { | ||
654 | if (m_parentScene.Permissions.CanTakeObject(group.UUID, remoteClient.AgentId)) | ||
655 | { | ||
656 | // If the attachment point isn't the same as the one previously used | ||
657 | // set it's offset position = 0 so that it appears on the attachment point | ||
658 | // and not in a weird location somewhere unknown. | ||
659 | if (AttachmentPt != 0 && AttachmentPt != (uint)group.GetAttachmentPoint()) | ||
660 | { | ||
661 | attachPos = Vector3.Zero; | ||
662 | } | ||
663 | |||
664 | // AttachmentPt 0 means the client chose to 'wear' the attachment. | ||
665 | if (AttachmentPt == 0) | ||
666 | { | ||
667 | // Check object for stored attachment point | ||
668 | AttachmentPt = (uint)group.GetAttachmentPoint(); | ||
669 | } | ||
670 | |||
671 | // if we still didn't find a suitable attachment point....... | ||
672 | if (AttachmentPt == 0) | ||
673 | { | ||
674 | // Stick it on left hand with Zero Offset from the attachment point. | ||
675 | AttachmentPt = (uint)AttachmentPoint.LeftHand; | ||
676 | attachPos = Vector3.Zero; | ||
677 | } | ||
678 | |||
679 | group.SetAttachmentPoint((byte)AttachmentPt); | ||
680 | group.AbsolutePosition = attachPos; | ||
681 | |||
682 | // Saves and gets itemID | ||
683 | UUID itemId; | ||
684 | |||
685 | if (group.GetFromItemID() == UUID.Zero) | ||
686 | { | ||
687 | m_parentScene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemId); | ||
688 | } | ||
689 | else | ||
690 | { | ||
691 | itemId = group.GetFromItemID(); | ||
692 | } | ||
693 | |||
694 | m_parentScene.AttachObject(remoteClient, AttachmentPt, itemId, group); | ||
695 | |||
696 | group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent); | ||
697 | // In case it is later dropped again, don't let | ||
698 | // it get cleaned up | ||
699 | // | ||
700 | group.RootPart.RemFlag(PrimFlags.TemporaryOnRez); | ||
701 | group.HasGroupChanged = false; | ||
702 | } | ||
703 | else | ||
704 | { | ||
705 | remoteClient.SendAgentAlertMessage("You don't have sufficient permissions to attach this object", false); | ||
706 | return false; | ||
707 | } | ||
708 | } | ||
709 | else | ||
710 | { | ||
711 | m_log.DebugFormat("[SCENE GRAPH]: AttachObject found no such scene object {0}", objectLocalID); | ||
712 | return false; | ||
713 | } | ||
714 | |||
715 | return true; | ||
716 | } | ||
717 | |||
718 | protected internal ScenePresence CreateAndAddChildScenePresence(IClientAPI client, AvatarAppearance appearance) | 522 | protected internal ScenePresence CreateAndAddChildScenePresence(IClientAPI client, AvatarAppearance appearance) |
719 | { | 523 | { |
720 | ScenePresence newAvatar = null; | 524 | ScenePresence newAvatar = null; |
@@ -747,7 +551,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
747 | 551 | ||
748 | Entities[presence.UUID] = presence; | 552 | Entities[presence.UUID] = presence; |
749 | 553 | ||
750 | lock (m_scenePresences) | 554 | m_scenePresencesLock.EnterWriteLock(); |
555 | try | ||
751 | { | 556 | { |
752 | if (!m_scenePresences.ContainsKey(presence.UUID)) | 557 | if (!m_scenePresences.ContainsKey(presence.UUID)) |
753 | { | 558 | { |
@@ -759,11 +564,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
759 | Array.Copy(m_scenePresenceArray, newArray, oldLength); | 564 | Array.Copy(m_scenePresenceArray, newArray, oldLength); |
760 | newArray[oldLength] = presence; | 565 | newArray[oldLength] = presence; |
761 | m_scenePresenceArray = newArray; | 566 | m_scenePresenceArray = newArray; |
567 | m_scenePresenceList = new List<ScenePresence>(m_scenePresenceArray); | ||
762 | } | 568 | } |
763 | else | 569 | else |
764 | { | 570 | { |
765 | m_scenePresences[presence.UUID] = presence; | 571 | m_scenePresences[presence.UUID] = presence; |
766 | 572 | ||
767 | // Do a linear search through the array of ScenePresence references | 573 | // Do a linear search through the array of ScenePresence references |
768 | // and update the modified entry | 574 | // and update the modified entry |
769 | for (int i = 0; i < m_scenePresenceArray.Length; i++) | 575 | for (int i = 0; i < m_scenePresenceArray.Length; i++) |
@@ -774,8 +580,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
774 | break; | 580 | break; |
775 | } | 581 | } |
776 | } | 582 | } |
583 | m_scenePresenceList = new List<ScenePresence>(m_scenePresenceArray); | ||
777 | } | 584 | } |
778 | } | 585 | } |
586 | finally | ||
587 | { | ||
588 | m_scenePresencesLock.ExitWriteLock(); | ||
589 | } | ||
779 | } | 590 | } |
780 | 591 | ||
781 | /// <summary> | 592 | /// <summary> |
@@ -790,7 +601,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
790 | agentID); | 601 | agentID); |
791 | } | 602 | } |
792 | 603 | ||
793 | lock (m_scenePresences) | 604 | m_scenePresencesLock.EnterWriteLock(); |
605 | try | ||
794 | { | 606 | { |
795 | if (m_scenePresences.Remove(agentID)) | 607 | if (m_scenePresences.Remove(agentID)) |
796 | { | 608 | { |
@@ -809,12 +621,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
809 | } | 621 | } |
810 | } | 622 | } |
811 | m_scenePresenceArray = newArray; | 623 | m_scenePresenceArray = newArray; |
624 | m_scenePresenceList = new List<ScenePresence>(m_scenePresenceArray); | ||
812 | } | 625 | } |
813 | else | 626 | else |
814 | { | 627 | { |
815 | m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); | 628 | m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); |
816 | } | 629 | } |
817 | } | 630 | } |
631 | finally | ||
632 | { | ||
633 | m_scenePresencesLock.ExitWriteLock(); | ||
634 | } | ||
818 | } | 635 | } |
819 | 636 | ||
820 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) | 637 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) |
@@ -845,18 +662,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
845 | 662 | ||
846 | public void RecalculateStats() | 663 | public void RecalculateStats() |
847 | { | 664 | { |
848 | ScenePresence[] presences = GetScenePresences(); | ||
849 | int rootcount = 0; | 665 | int rootcount = 0; |
850 | int childcount = 0; | 666 | int childcount = 0; |
851 | 667 | ||
852 | for (int i = 0; i < presences.Length; i++) | 668 | ForEachScenePresence(delegate(ScenePresence presence) |
853 | { | 669 | { |
854 | ScenePresence user = presences[i]; | 670 | if (presence.IsChildAgent) |
855 | if (user.IsChildAgent) | ||
856 | ++childcount; | 671 | ++childcount; |
857 | else | 672 | else |
858 | ++rootcount; | 673 | ++rootcount; |
859 | } | 674 | }); |
860 | 675 | ||
861 | m_numRootAgents = rootcount; | 676 | m_numRootAgents = rootcount; |
862 | m_numChildAgents = childcount; | 677 | m_numChildAgents = childcount; |
@@ -903,25 +718,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
903 | #endregion | 718 | #endregion |
904 | 719 | ||
905 | #region Get Methods | 720 | #region Get Methods |
906 | |||
907 | /// <summary> | ||
908 | /// Request a List of all scene presences in this scene. This is a new list, so no | ||
909 | /// locking is required to iterate over it. | ||
910 | /// </summary> | ||
911 | /// <returns></returns> | ||
912 | protected internal ScenePresence[] GetScenePresences() | ||
913 | { | ||
914 | return m_scenePresenceArray; | ||
915 | } | ||
916 | |||
917 | protected internal List<ScenePresence> GetAvatars() | ||
918 | { | ||
919 | List<ScenePresence> result = | ||
920 | GetScenePresences(delegate(ScenePresence scenePresence) { return !scenePresence.IsChildAgent; }); | ||
921 | |||
922 | return result; | ||
923 | } | ||
924 | |||
925 | /// <summary> | 721 | /// <summary> |
926 | /// Get the controlling client for the given avatar, if there is one. | 722 | /// Get the controlling client for the given avatar, if there is one. |
927 | /// | 723 | /// |
@@ -948,44 +744,103 @@ namespace OpenSim.Region.Framework.Scenes | |||
948 | } | 744 | } |
949 | 745 | ||
950 | /// <summary> | 746 | /// <summary> |
951 | /// Request a filtered list of m_scenePresences in this World | 747 | /// Request a copy of m_scenePresences in this World |
748 | /// There is no guarantee that presences will remain in the scene after the list is returned. | ||
749 | /// This list should remain private to SceneGraph. Callers wishing to iterate should instead | ||
750 | /// pass a delegate to ForEachScenePresence. | ||
952 | /// </summary> | 751 | /// </summary> |
953 | /// <returns></returns> | 752 | /// <returns></returns> |
954 | protected internal List<ScenePresence> GetScenePresences(FilterAvatarList filter) | 753 | private List<ScenePresence> GetScenePresences() |
955 | { | 754 | { |
956 | // No locking of scene presences here since we're passing back a list... | 755 | m_scenePresencesLock.EnterReadLock(); |
957 | 756 | try | |
958 | List<ScenePresence> result = new List<ScenePresence>(); | ||
959 | ScenePresence[] scenePresences = GetScenePresences(); | ||
960 | |||
961 | for (int i = 0; i < scenePresences.Length; i++) | ||
962 | { | 757 | { |
963 | ScenePresence avatar = scenePresences[i]; | 758 | return m_scenePresenceList; |
964 | if (filter(avatar)) | 759 | } |
965 | result.Add(avatar); | 760 | finally |
761 | { | ||
762 | m_scenePresencesLock.ExitReadLock(); | ||
966 | } | 763 | } |
967 | |||
968 | return result; | ||
969 | } | 764 | } |
970 | 765 | ||
971 | /// <summary> | 766 | /// <summary> |
972 | /// Request a scene presence by UUID | 767 | /// Request a scene presence by UUID. Fast, indexed lookup. |
973 | /// </summary> | 768 | /// </summary> |
974 | /// <param name="avatarID"></param> | 769 | /// <param name="agentID"></param> |
975 | /// <returns>null if the agent was not found</returns> | 770 | /// <returns>null if the presence was not found</returns> |
976 | protected internal ScenePresence GetScenePresence(UUID agentID) | 771 | protected internal ScenePresence GetScenePresence(UUID agentID) |
977 | { | 772 | { |
978 | ScenePresence sp; | 773 | ScenePresence sp; |
979 | 774 | m_scenePresencesLock.EnterReadLock(); | |
980 | lock (m_scenePresences) | 775 | try |
981 | { | 776 | { |
982 | m_scenePresences.TryGetValue(agentID, out sp); | 777 | m_scenePresences.TryGetValue(agentID, out sp); |
983 | } | 778 | } |
984 | 779 | finally | |
780 | { | ||
781 | m_scenePresencesLock.ExitReadLock(); | ||
782 | } | ||
985 | return sp; | 783 | return sp; |
986 | } | 784 | } |
987 | 785 | ||
988 | /// <summary> | 786 | /// <summary> |
787 | /// Request the scene presence by name. | ||
788 | /// </summary> | ||
789 | /// <param name="firstName"></param> | ||
790 | /// <param name="lastName"></param> | ||
791 | /// <returns>null if the presence was not found</returns> | ||
792 | protected internal ScenePresence GetScenePresence(string firstName, string lastName) | ||
793 | { | ||
794 | foreach (ScenePresence presence in GetScenePresences()) | ||
795 | { | ||
796 | if (presence.Firstname == firstName && presence.Lastname == lastName) | ||
797 | return presence; | ||
798 | } | ||
799 | return null; | ||
800 | } | ||
801 | |||
802 | /// <summary> | ||
803 | /// Request the scene presence by localID. | ||
804 | /// </summary> | ||
805 | /// <param name="localID"></param> | ||
806 | /// <returns>null if the presence was not found</returns> | ||
807 | protected internal ScenePresence GetScenePresence(uint localID) | ||
808 | { | ||
809 | foreach (ScenePresence presence in GetScenePresences()) | ||
810 | if (presence.LocalId == localID) | ||
811 | return presence; | ||
812 | return null; | ||
813 | } | ||
814 | |||
815 | protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar) | ||
816 | { | ||
817 | m_scenePresencesLock.EnterReadLock(); | ||
818 | try | ||
819 | { | ||
820 | m_scenePresences.TryGetValue(agentID, out avatar); | ||
821 | } | ||
822 | finally | ||
823 | { | ||
824 | m_scenePresencesLock.ExitReadLock(); | ||
825 | } | ||
826 | return (avatar != null); | ||
827 | } | ||
828 | |||
829 | protected internal bool TryGetAvatarByName(string name, out ScenePresence avatar) | ||
830 | { | ||
831 | avatar = null; | ||
832 | foreach (ScenePresence presence in GetScenePresences()) | ||
833 | { | ||
834 | if (String.Compare(name, presence.ControllingClient.Name, true) == 0) | ||
835 | { | ||
836 | avatar = presence; | ||
837 | break; | ||
838 | } | ||
839 | } | ||
840 | return (avatar != null); | ||
841 | } | ||
842 | |||
843 | /// <summary> | ||
989 | /// Get a scene object group that contains the prim with the given local id | 844 | /// Get a scene object group that contains the prim with the given local id |
990 | /// </summary> | 845 | /// </summary> |
991 | /// <param name="localID"></param> | 846 | /// <param name="localID"></param> |
@@ -1136,34 +991,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1136 | return group.GetChildPart(fullID); | 991 | return group.GetChildPart(fullID); |
1137 | } | 992 | } |
1138 | 993 | ||
1139 | protected internal bool TryGetAvatar(UUID avatarId, out ScenePresence avatar) | ||
1140 | { | ||
1141 | lock (m_scenePresences) | ||
1142 | return m_scenePresences.TryGetValue(avatarId, out avatar); | ||
1143 | } | ||
1144 | |||
1145 | protected internal bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) | ||
1146 | { | ||
1147 | ScenePresence[] presences = GetScenePresences(); | ||
1148 | |||
1149 | for (int i = 0; i < presences.Length; i++) | ||
1150 | { | ||
1151 | ScenePresence presence = presences[i]; | ||
1152 | |||
1153 | if (!presence.IsChildAgent) | ||
1154 | { | ||
1155 | if (String.Compare(avatarName, presence.ControllingClient.Name, true) == 0) | ||
1156 | { | ||
1157 | avatar = presence; | ||
1158 | return true; | ||
1159 | } | ||
1160 | } | ||
1161 | } | ||
1162 | |||
1163 | avatar = null; | ||
1164 | return false; | ||
1165 | } | ||
1166 | |||
1167 | /// <summary> | 994 | /// <summary> |
1168 | /// Returns a list of the entities in the scene. This is a new list so no locking is required to iterate over | 995 | /// Returns a list of the entities in the scene. This is a new list so no locking is required to iterate over |
1169 | /// it | 996 | /// it |
@@ -1226,6 +1053,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
1226 | return UUID.Zero; | 1053 | return UUID.Zero; |
1227 | } | 1054 | } |
1228 | 1055 | ||
1056 | /// <summary> | ||
1057 | /// Performs action on all scene object groups. | ||
1058 | /// </summary> | ||
1059 | /// <param name="action"></param> | ||
1229 | protected internal void ForEachSOG(Action<SceneObjectGroup> action) | 1060 | protected internal void ForEachSOG(Action<SceneObjectGroup> action) |
1230 | { | 1061 | { |
1231 | List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); | 1062 | List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); |
@@ -1242,6 +1073,47 @@ namespace OpenSim.Region.Framework.Scenes | |||
1242 | } | 1073 | } |
1243 | } | 1074 | } |
1244 | } | 1075 | } |
1076 | |||
1077 | |||
1078 | /// <summary> | ||
1079 | /// Performs action on all scene presences. This can ultimately run the actions in parallel but | ||
1080 | /// any delegates passed in will need to implement their own locking on data they reference and | ||
1081 | /// modify outside of the scope of the delegate. | ||
1082 | /// </summary> | ||
1083 | /// <param name="action"></param> | ||
1084 | public void ForEachScenePresence(Action<ScenePresence> action) | ||
1085 | { | ||
1086 | // Once all callers have their delegates configured for parallelism, we can unleash this | ||
1087 | /* | ||
1088 | Action<ScenePresence> protectedAction = new Action<ScenePresence>(delegate(ScenePresence sp) | ||
1089 | { | ||
1090 | try | ||
1091 | { | ||
1092 | action(sp); | ||
1093 | } | ||
1094 | catch (Exception e) | ||
1095 | { | ||
1096 | m_log.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString()); | ||
1097 | m_log.Info("[BUG] Stack Trace: " + e.StackTrace); | ||
1098 | } | ||
1099 | }); | ||
1100 | Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction); | ||
1101 | */ | ||
1102 | // For now, perform actiona serially | ||
1103 | |||
1104 | foreach (ScenePresence sp in GetScenePresences()) | ||
1105 | { | ||
1106 | try | ||
1107 | { | ||
1108 | action(sp); | ||
1109 | } | ||
1110 | catch (Exception e) | ||
1111 | { | ||
1112 | m_log.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString()); | ||
1113 | m_log.Info("[BUG] Stack Trace: " + e.StackTrace); | ||
1114 | } | ||
1115 | } | ||
1116 | } | ||
1245 | 1117 | ||
1246 | #endregion | 1118 | #endregion |
1247 | 1119 | ||
@@ -1924,6 +1796,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1924 | copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 0); | 1796 | copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 0); |
1925 | copy.HasGroupChanged = true; | 1797 | copy.HasGroupChanged = true; |
1926 | copy.ScheduleGroupForFullUpdate(); | 1798 | copy.ScheduleGroupForFullUpdate(); |
1799 | copy.ResumeScripts(); | ||
1927 | 1800 | ||
1928 | // required for physics to update it's position | 1801 | // required for physics to update it's position |
1929 | copy.AbsolutePosition = copy.AbsolutePosition; | 1802 | copy.AbsolutePosition = copy.AbsolutePosition; |