aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/ScenePresence.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs135
1 files changed, 86 insertions, 49 deletions
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 252c72f..f57d4fe 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -109,6 +109,16 @@ namespace OpenSim.Region.Framework.Scenes
109 } 109 }
110 } 110 }
111 111
112 /// <summary>
113 /// This exists to prevent race conditions between two CompleteMovement threads if the simulator is slow and
114 /// the viewer fires these in quick succession.
115 /// </summary>
116 /// <remarks>
117 /// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement
118 /// regulation done there.
119 /// </remarks>
120 private object m_completeMovementLock = new object();
121
112// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 122// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
113 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); 123 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
114 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); 124 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
@@ -984,6 +994,7 @@ namespace OpenSim.Region.Framework.Scenes
984 /// <summary> 994 /// <summary>
985 /// Turns a child agent into a root agent. 995 /// Turns a child agent into a root agent.
986 /// </summary> 996 /// </summary>
997 /// <remarks>
987 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the 998 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the
988 /// avatar is actual in the sim. They can perform all actions. 999 /// avatar is actual in the sim. They can perform all actions.
989 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim, 1000 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim,
@@ -991,49 +1002,52 @@ namespace OpenSim.Region.Framework.Scenes
991 /// 1002 ///
992 /// This method is on the critical path for transferring an avatar from one region to another. Delay here 1003 /// This method is on the critical path for transferring an avatar from one region to another. Delay here
993 /// delays that crossing. 1004 /// delays that crossing.
994 /// </summary> 1005 /// </remarks>
995 private void MakeRootAgent(Vector3 pos, bool isFlying) 1006 private bool MakeRootAgent(Vector3 pos, bool isFlying)
996 { 1007 {
997// m_log.InfoFormat( 1008 lock (m_completeMovementLock)
998// "[SCENE]: Upgrading child to root agent for {0} in {1}",
999// Name, m_scene.RegionInfo.RegionName);
1000
1001 if (ParentUUID != UUID.Zero)
1002 { 1009 {
1003 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); 1010 if (!IsChildAgent)
1004 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); 1011 return false;
1005 if (part == null) 1012
1013 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1014
1015 // m_log.InfoFormat(
1016 // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1017 // Name, m_scene.RegionInfo.RegionName);
1018
1019 if (ParentUUID != UUID.Zero)
1006 { 1020 {
1007 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); 1021 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
1022 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
1023 if (part == null)
1024 {
1025 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1026 }
1027 else
1028 {
1029 part.ParentGroup.AddAvatar(UUID);
1030 if (part.SitTargetPosition != Vector3.Zero)
1031 part.SitTargetAvatar = UUID;
1032 // ParentPosition = part.GetWorldPosition();
1033 ParentID = part.LocalId;
1034 ParentPart = part;
1035 m_pos = PrevSitOffset;
1036 // pos = ParentPosition;
1037 pos = part.GetWorldPosition();
1038 }
1039 ParentUUID = UUID.Zero;
1040
1041 // Animator.TrySetMovementAnimation("SIT");
1008 } 1042 }
1009 else 1043 else
1010 { 1044 {
1011 part.ParentGroup.AddAvatar(UUID); 1045 IsLoggingIn = false;
1012 if (part.SitTargetPosition != Vector3.Zero)
1013 part.SitTargetAvatar = UUID;
1014// ParentPosition = part.GetWorldPosition();
1015 ParentID = part.LocalId;
1016 ParentPart = part;
1017 m_pos = PrevSitOffset;
1018// pos = ParentPosition;
1019 pos = part.GetWorldPosition();
1020 } 1046 }
1021 ParentUUID = UUID.Zero;
1022
1023 IsChildAgent = false;
1024 1047
1025// Animator.TrySetMovementAnimation("SIT");
1026 }
1027 else
1028 {
1029 IsChildAgent = false; 1048 IsChildAgent = false;
1030 IsLoggingIn = false;
1031 } 1049 }
1032 1050
1033 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1034
1035 IsChildAgent = false;
1036
1037 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag 1051 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
1038 // set and prevent the close of the connection on a subsequent re-teleport. 1052 // set and prevent the close of the connection on a subsequent re-teleport.
1039 // Should not be needed if we are not trying to tell this region to close 1053 // Should not be needed if we are not trying to tell this region to close
@@ -1178,22 +1192,36 @@ namespace OpenSim.Region.Framework.Scenes
1178 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently 1192 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1179 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are 1193 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1180 // not transporting the required data. 1194 // not transporting the required data.
1181 lock (m_attachments) 1195 //
1196 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
1197 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1198 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1199 // not transporting the required data.
1200 //
1201 // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of
1202 // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here
1203 // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status.
1204 //
1205 // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts().
1206 // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing
1207 // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the
1208 // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
1209 //
1210 // One cannot simply iterate over attachments in a fire and forget thread because this would no longer
1211 // be locked, allowing race conditions if other code changes the attachments list.
1212 List<SceneObjectGroup> attachments = GetAttachments();
1213
1214 if (attachments.Count > 0)
1182 { 1215 {
1183 if (HasAttachments()) 1216 m_log.DebugFormat(
1184 { 1217 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1185 m_log.DebugFormat(
1186 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1187 1218
1188 // Resume scripts 1219 // Resume scripts
1189 Util.FireAndForget(delegate(object x) { 1220 foreach (SceneObjectGroup sog in attachments)
1190 foreach (SceneObjectGroup sog in m_attachments) 1221 {
1191 { 1222 sog.ScheduleGroupForFullUpdate();
1192 sog.ScheduleGroupForFullUpdate(); 1223 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1193 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 1224 sog.ResumeScripts();
1194 sog.ResumeScripts();
1195 }
1196 });
1197 } 1225 }
1198 } 1226 }
1199 } 1227 }
@@ -1215,6 +1243,7 @@ namespace OpenSim.Region.Framework.Scenes
1215 1243
1216 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1244 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1217 1245
1246 return true;
1218 } 1247 }
1219 1248
1220 public int GetStateSource() 1249 public int GetStateSource()
@@ -1637,7 +1666,14 @@ namespace OpenSim.Region.Framework.Scenes
1637 } 1666 }
1638 1667
1639 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1668 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1640 MakeRootAgent(AbsolutePosition, flying); 1669 if (!MakeRootAgent(AbsolutePosition, flying))
1670 {
1671 m_log.DebugFormat(
1672 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
1673 Name, Scene.Name);
1674
1675 return;
1676 }
1641 1677
1642 // Tell the client that we're totally ready 1678 // Tell the client that we're totally ready
1643 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); 1679 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
@@ -2884,7 +2920,6 @@ namespace OpenSim.Region.Framework.Scenes
2884 Rotation = newRot; 2920 Rotation = newRot;
2885 2921
2886// ParentPosition = part.AbsolutePosition; 2922// ParentPosition = part.AbsolutePosition;
2887 part.ParentGroup.AddAvatar(UUID);
2888 } 2923 }
2889 else 2924 else
2890 { 2925 {
@@ -2893,13 +2928,13 @@ namespace OpenSim.Region.Framework.Scenes
2893 m_pos -= part.GroupPosition; 2928 m_pos -= part.GroupPosition;
2894 2929
2895// ParentPosition = part.AbsolutePosition; 2930// ParentPosition = part.AbsolutePosition;
2896 part.ParentGroup.AddAvatar(UUID);
2897 2931
2898// m_log.DebugFormat( 2932// m_log.DebugFormat(
2899// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2933// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
2900// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); 2934// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
2901 } 2935 }
2902 2936
2937 part.ParentGroup.AddAvatar(UUID);
2903 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 2938 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2904 ParentID = m_requestedSitTargetID; 2939 ParentID = m_requestedSitTargetID;
2905 m_AngularVelocity = Vector3.Zero; 2940 m_AngularVelocity = Vector3.Zero;
@@ -3210,6 +3245,8 @@ namespace OpenSim.Region.Framework.Scenes
3210 // again here... this comes after the cached appearance check because the avatars 3245 // again here... this comes after the cached appearance check because the avatars
3211 // appearance goes into the avatar update packet 3246 // appearance goes into the avatar update packet
3212 SendAvatarDataToAllAgents(); 3247 SendAvatarDataToAllAgents();
3248
3249 // This invocation always shows up in the viewer logs as an error. Is it needed?
3213 SendAppearanceToAgent(this); 3250 SendAppearanceToAgent(this);
3214 3251
3215 // If we are using the the cached appearance then send it out to everyone 3252 // If we are using the the cached appearance then send it out to everyone