aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneGraph.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs402
1 files changed, 118 insertions, 284 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index bbcb85e..3a1962c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -35,6 +35,7 @@ using log4net;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Region.Framework.Scenes.Types; 36using OpenSim.Region.Framework.Scenes.Types;
37using OpenSim.Region.Physics.Manager; 37using OpenSim.Region.Physics.Manager;
38using OpenSim.Region.Framework.Interfaces;
38 39
39namespace OpenSim.Region.Framework.Scenes 40namespace OpenSim.Region.Framework.Scenes
40{ 41{
@@ -164,9 +165,10 @@ namespace OpenSim.Region.Framework.Scenes
164 165
165 protected internal void UpdatePresences() 166 protected internal void UpdatePresences()
166 { 167 {
167 ScenePresence[] updateScenePresences = GetScenePresences(); 168 ForEachScenePresence(delegate(ScenePresence presence)
168 for (int i = 0; i < updateScenePresences.Length; i++) 169 {
169 updateScenePresences[i].Update(); 170 presence.Update();
171 });
170 } 172 }
171 173
172 protected internal float UpdatePhysics(double elapsed) 174 protected internal float UpdatePhysics(double elapsed)
@@ -195,9 +197,10 @@ namespace OpenSim.Region.Framework.Scenes
195 197
196 protected internal void UpdateScenePresenceMovement() 198 protected internal void UpdateScenePresenceMovement()
197 { 199 {
198 ScenePresence[] moveEntities = GetScenePresences(); 200 ForEachScenePresence(delegate(ScenePresence presence)
199 for (int i = 0; i < moveEntities.Length; i++) 201 {
200 moveEntities[i].UpdateMovement(); 202 presence.UpdateMovement();
203 });
201 } 204 }
202 205
203 #endregion 206 #endregion
@@ -475,7 +478,7 @@ namespace OpenSim.Region.Framework.Scenes
475 if (group != null) 478 if (group != null)
476 { 479 {
477 //group.DetachToGround(); 480 //group.DetachToGround();
478 m_parentScene.DetachSingleAttachmentToInv(group.GetFromItemID(), remoteClient); 481 m_parentScene.AttachmentsModule.ShowDetachInUserInventory(group.GetFromItemID(), remoteClient);
479 } 482 }
480 } 483 }
481 484
@@ -509,212 +512,6 @@ namespace OpenSim.Region.Framework.Scenes
509 } 512 }
510 } 513 }
511 514
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) 515 protected internal ScenePresence CreateAndAddChildScenePresence(IClientAPI client, AvatarAppearance appearance)
719 { 516 {
720 ScenePresence newAvatar = null; 517 ScenePresence newAvatar = null;
@@ -845,18 +642,16 @@ namespace OpenSim.Region.Framework.Scenes
845 642
846 public void RecalculateStats() 643 public void RecalculateStats()
847 { 644 {
848 ScenePresence[] presences = GetScenePresences();
849 int rootcount = 0; 645 int rootcount = 0;
850 int childcount = 0; 646 int childcount = 0;
851 647
852 for (int i = 0; i < presences.Length; i++) 648 ForEachScenePresence(delegate(ScenePresence presence)
853 { 649 {
854 ScenePresence user = presences[i]; 650 if (presence.IsChildAgent)
855 if (user.IsChildAgent)
856 ++childcount; 651 ++childcount;
857 else 652 else
858 ++rootcount; 653 ++rootcount;
859 } 654 });
860 655
861 m_numRootAgents = rootcount; 656 m_numRootAgents = rootcount;
862 m_numChildAgents = childcount; 657 m_numChildAgents = childcount;
@@ -903,25 +698,6 @@ namespace OpenSim.Region.Framework.Scenes
903 #endregion 698 #endregion
904 699
905 #region Get Methods 700 #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> 701 /// <summary>
926 /// Get the controlling client for the given avatar, if there is one. 702 /// Get the controlling client for the given avatar, if there is one.
927 /// 703 ///
@@ -948,41 +724,83 @@ namespace OpenSim.Region.Framework.Scenes
948 } 724 }
949 725
950 /// <summary> 726 /// <summary>
951 /// Request a filtered list of m_scenePresences in this World 727 /// Request a copy of m_scenePresences in this World
728 /// There is no guarantee that presences will remain in the scene after the list is returned.
729 /// This list should remain private to SceneGraph. Callers wishing to iterate should instead
730 /// pass a delegate to ForEachScenePresence.
952 /// </summary> 731 /// </summary>
953 /// <returns></returns> 732 /// <returns></returns>
954 protected internal List<ScenePresence> GetScenePresences(FilterAvatarList filter) 733 private List<ScenePresence> GetScenePresences()
955 { 734 {
956 // No locking of scene presences here since we're passing back a list... 735 lock (m_scenePresences)
957 736 return new List<ScenePresence>(m_scenePresenceArray);
958 List<ScenePresence> result = new List<ScenePresence>(); 737 }
959 ScenePresence[] scenePresences = GetScenePresences();
960 738
961 for (int i = 0; i < scenePresences.Length; i++) 739 /// <summary>
740 /// Request a scene presence by UUID. Fast, indexed lookup.
741 /// </summary>
742 /// <param name="agentID"></param>
743 /// <returns>null if the presence was not found</returns>
744 protected internal ScenePresence GetScenePresence(UUID agentID)
745 {
746 ScenePresence sp;
747 lock (m_scenePresences)
962 { 748 {
963 ScenePresence avatar = scenePresences[i]; 749 m_scenePresences.TryGetValue(agentID, out sp);
964 if (filter(avatar))
965 result.Add(avatar);
966 } 750 }
751 return sp;
752 }
967 753
968 return result; 754 /// <summary>
755 /// Request the scene presence by name.
756 /// </summary>
757 /// <param name="firstName"></param>
758 /// <param name="lastName"></param>
759 /// <returns>null if the presence was not found</returns>
760 protected internal ScenePresence GetScenePresence(string firstName, string lastName)
761 {
762 foreach (ScenePresence presence in GetScenePresences())
763 {
764 if (presence.Firstname == firstName && presence.Lastname == lastName)
765 return presence;
766 }
767 return null;
969 } 768 }
970 769
971 /// <summary> 770 /// <summary>
972 /// Request a scene presence by UUID 771 /// Request the scene presence by localID.
973 /// </summary> 772 /// </summary>
974 /// <param name="avatarID"></param> 773 /// <param name="localID"></param>
975 /// <returns>null if the agent was not found</returns> 774 /// <returns>null if the presence was not found</returns>
976 protected internal ScenePresence GetScenePresence(UUID agentID) 775 protected internal ScenePresence GetScenePresence(uint localID)
776 {
777 foreach (ScenePresence presence in GetScenePresences())
778 if (presence.LocalId == localID)
779 return presence;
780 return null;
781 }
782
783 protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar)
977 { 784 {
978 ScenePresence sp;
979
980 lock (m_scenePresences) 785 lock (m_scenePresences)
981 { 786 {
982 m_scenePresences.TryGetValue(agentID, out sp); 787 m_scenePresences.TryGetValue(agentID, out avatar);
983 } 788 }
789 return (avatar != null);
790 }
984 791
985 return sp; 792 protected internal bool TryGetAvatarByName(string name, out ScenePresence avatar)
793 {
794 avatar = null;
795 foreach (ScenePresence presence in GetScenePresences())
796 {
797 if (String.Compare(name, presence.ControllingClient.Name, true) == 0)
798 {
799 avatar = presence;
800 break;
801 }
802 }
803 return (avatar != null);
986 } 804 }
987 805
988 /// <summary> 806 /// <summary>
@@ -1136,34 +954,6 @@ namespace OpenSim.Region.Framework.Scenes
1136 return group.GetChildPart(fullID); 954 return group.GetChildPart(fullID);
1137 } 955 }
1138 956
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> 957 /// <summary>
1168 /// Returns a list of the entities in the scene. This is a new list so no locking is required to iterate over 958 /// Returns a list of the entities in the scene. This is a new list so no locking is required to iterate over
1169 /// it 959 /// it
@@ -1226,6 +1016,10 @@ namespace OpenSim.Region.Framework.Scenes
1226 return UUID.Zero; 1016 return UUID.Zero;
1227 } 1017 }
1228 1018
1019 /// <summary>
1020 /// Performs action on all scene object groups.
1021 /// </summary>
1022 /// <param name="action"></param>
1229 protected internal void ForEachSOG(Action<SceneObjectGroup> action) 1023 protected internal void ForEachSOG(Action<SceneObjectGroup> action)
1230 { 1024 {
1231 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); 1025 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values);
@@ -1242,6 +1036,46 @@ namespace OpenSim.Region.Framework.Scenes
1242 } 1036 }
1243 } 1037 }
1244 } 1038 }
1039
1040
1041 /// <summary>
1042 /// Performs action on all scene presences. This can ultimately run the actions in parallel but
1043 /// any delegates passed in will need to implement their own locking on data they reference and
1044 /// modify outside of the scope of the delegate.
1045 /// </summary>
1046 /// <param name="action"></param>
1047 public void ForEachScenePresence(Action<ScenePresence> action)
1048 {
1049 // Once all callers have their delegates configured for parallelism, we can unleash this
1050 /*
1051 Action<ScenePresence> protectedAction = new Action<ScenePresence>(delegate(ScenePresence sp)
1052 {
1053 try
1054 {
1055 action(sp);
1056 }
1057 catch (Exception e)
1058 {
1059 m_log.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
1060 m_log.Info("[BUG] Stack Trace: " + e.StackTrace);
1061 }
1062 });
1063 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction);
1064 */
1065 // For now, perform actiona serially
1066 foreach (ScenePresence sp in GetScenePresences())
1067 {
1068 try
1069 {
1070 action(sp);
1071 }
1072 catch (Exception e)
1073 {
1074 m_log.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
1075 m_log.Info("[BUG] Stack Trace: " + e.StackTrace);
1076 }
1077 }
1078 }
1245 1079
1246 #endregion 1080 #endregion
1247 1081