diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/ScenePresence.cs | 738 |
1 files changed, 533 insertions, 205 deletions
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 7004d23..f57d4fe 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -29,7 +29,9 @@ using System; | |||
29 | using System.Xml; | 29 | using System.Xml; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Threading; | ||
32 | using System.Timers; | 33 | using System.Timers; |
34 | using Timer = System.Timers.Timer; | ||
33 | using OpenMetaverse; | 35 | using OpenMetaverse; |
34 | using log4net; | 36 | using log4net; |
35 | using Nini.Config; | 37 | using Nini.Config; |
@@ -73,21 +75,50 @@ namespace OpenSim.Region.Framework.Scenes | |||
73 | 75 | ||
74 | public class ScenePresence : EntityBase, IScenePresence | 76 | public class ScenePresence : EntityBase, IScenePresence |
75 | { | 77 | { |
78 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
79 | |||
76 | // ~ScenePresence() | 80 | // ~ScenePresence() |
77 | // { | 81 | // { |
78 | // m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); | 82 | // m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); |
79 | // } | 83 | // } |
80 | 84 | ||
81 | private void TriggerScenePresenceUpdated() | 85 | public void TriggerScenePresenceUpdated() |
82 | { | 86 | { |
83 | if (m_scene != null) | 87 | if (m_scene != null) |
84 | m_scene.EventManager.TriggerScenePresenceUpdated(this); | 88 | m_scene.EventManager.TriggerScenePresenceUpdated(this); |
85 | } | 89 | } |
86 | 90 | ||
87 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
88 | |||
89 | public PresenceType PresenceType { get; private set; } | 91 | public PresenceType PresenceType { get; private set; } |
90 | 92 | ||
93 | private ScenePresenceStateMachine m_stateMachine; | ||
94 | |||
95 | /// <summary> | ||
96 | /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine | ||
97 | /// for more details. | ||
98 | /// </summary> | ||
99 | public ScenePresenceState LifecycleState | ||
100 | { | ||
101 | get | ||
102 | { | ||
103 | return m_stateMachine.GetState(); | ||
104 | } | ||
105 | |||
106 | set | ||
107 | { | ||
108 | m_stateMachine.SetState(value); | ||
109 | } | ||
110 | } | ||
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 | |||
91 | // private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); | 122 | // private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); |
92 | 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)); |
93 | 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); |
@@ -142,6 +173,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
142 | private Vector3 m_lastVelocity; | 173 | private Vector3 m_lastVelocity; |
143 | private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); | 174 | private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); |
144 | 175 | ||
176 | private bool m_followCamAuto = false; | ||
177 | |||
145 | 178 | ||
146 | private Vector3? m_forceToApply; | 179 | private Vector3? m_forceToApply; |
147 | private int m_userFlags; | 180 | private int m_userFlags; |
@@ -200,7 +233,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
200 | private float m_sitAvatarHeight = 2.0f; | 233 | private float m_sitAvatarHeight = 2.0f; |
201 | 234 | ||
202 | private Vector3 m_lastChildAgentUpdatePosition; | 235 | private Vector3 m_lastChildAgentUpdatePosition; |
203 | private Vector3 m_lastChildAgentUpdateCamPosition; | 236 | // private Vector3 m_lastChildAgentUpdateCamPosition; |
204 | 237 | ||
205 | private const int LAND_VELOCITYMAG_MAX = 12; | 238 | private const int LAND_VELOCITYMAG_MAX = 12; |
206 | 239 | ||
@@ -290,9 +323,37 @@ namespace OpenSim.Region.Framework.Scenes | |||
290 | /// </summary> | 323 | /// </summary> |
291 | private Vector3 posLastSignificantMove; | 324 | private Vector3 posLastSignificantMove; |
292 | 325 | ||
293 | // For teleports and crossings callbacks | 326 | #region For teleports and crossings callbacks |
294 | string m_callbackURI; | 327 | |
295 | UUID m_originRegionID; | 328 | /// <summary> |
329 | /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address. | ||
330 | /// </summary> | ||
331 | private string m_callbackURI; | ||
332 | |||
333 | /// <summary> | ||
334 | /// Records the region from which this presence originated, if not from login. | ||
335 | /// </summary> | ||
336 | /// <remarks> | ||
337 | /// Also acts as a signal in the teleport V2 process to release UpdateAgent after a viewer has triggered | ||
338 | /// CompleteMovement and made the previous child agent a root agent. | ||
339 | /// </remarks> | ||
340 | private UUID m_originRegionID; | ||
341 | |||
342 | /// <summary> | ||
343 | /// This object is used as a lock before accessing m_originRegionID to make sure that every thread is seeing | ||
344 | /// the very latest value and not using some cached version. Cannot make m_originRegionID itself volatite as | ||
345 | /// it is a value type. | ||
346 | /// </summary> | ||
347 | private object m_originRegionIDAccessLock = new object(); | ||
348 | |||
349 | /// <summary> | ||
350 | /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent | ||
351 | /// teleport is reusing the connection. | ||
352 | /// </summary> | ||
353 | /// <remarks>May be refactored or move somewhere else soon.</remarks> | ||
354 | public bool DoNotCloseAfterTeleport { get; set; } | ||
355 | |||
356 | #endregion | ||
296 | 357 | ||
297 | /// <value> | 358 | /// <value> |
298 | /// Script engines present in the scene | 359 | /// Script engines present in the scene |
@@ -309,15 +370,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
309 | /// <summary> | 370 | /// <summary> |
310 | /// Record user movement inputs. | 371 | /// Record user movement inputs. |
311 | /// </summary> | 372 | /// </summary> |
312 | public byte MovementFlag { get; private set; } | 373 | public uint MovementFlag { get; private set; } |
313 | 374 | ||
314 | private bool m_updateflag; | 375 | /// <summary> |
315 | 376 | /// Is the agent stop control flag currently active? | |
316 | public bool Updated | 377 | /// </summary> |
317 | { | 378 | public bool AgentControlStopActive { get; private set; } |
318 | set { m_updateflag = value; } | ||
319 | get { return m_updateflag; } | ||
320 | } | ||
321 | 379 | ||
322 | private bool m_invulnerable = true; | 380 | private bool m_invulnerable = true; |
323 | 381 | ||
@@ -462,6 +520,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
462 | } | 520 | } |
463 | else | 521 | else |
464 | { | 522 | { |
523 | // m_log.DebugFormat("[SCENE PRESENCE]: Fetching abs pos where PhysicsActor == null and parent part {0} for {1}", Name, Scene.Name); | ||
465 | // Obtain the correct position of a seated avatar. | 524 | // Obtain the correct position of a seated avatar. |
466 | // In addition to providing the correct position while | 525 | // In addition to providing the correct position while |
467 | // the avatar is seated, this value will also | 526 | // the avatar is seated, this value will also |
@@ -485,7 +544,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
485 | } | 544 | } |
486 | set | 545 | set |
487 | { | 546 | { |
488 | // m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} in {1} to {2}", Name, Scene.Name, value); | 547 | // m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} to {1} in {2}", Name, value, Scene.Name); |
489 | // Util.PrintCallStack(); | 548 | // Util.PrintCallStack(); |
490 | 549 | ||
491 | if (PhysicsActor != null) | 550 | if (PhysicsActor != null) |
@@ -502,10 +561,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
502 | 561 | ||
503 | // Don't update while sitting. The PhysicsActor above is null whilst sitting. | 562 | // Don't update while sitting. The PhysicsActor above is null whilst sitting. |
504 | if (ParentID == 0) | 563 | if (ParentID == 0) |
505 | { | ||
506 | m_pos = value; | 564 | m_pos = value; |
507 | // ParentPosition = Vector3.Zero; | ||
508 | } | ||
509 | 565 | ||
510 | //m_log.DebugFormat( | 566 | //m_log.DebugFormat( |
511 | // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", | 567 | // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", |
@@ -768,6 +824,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
768 | set { m_speedModifier = value; } | 824 | set { m_speedModifier = value; } |
769 | } | 825 | } |
770 | 826 | ||
827 | /// <summary> | ||
828 | /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running | ||
829 | /// </summary> | ||
830 | /// <remarks> | ||
831 | /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers. | ||
832 | /// </remarks> | ||
833 | private float AgentControlStopSlowWhilstMoving = 0.5f; | ||
834 | |||
771 | private bool m_forceFly; | 835 | private bool m_forceFly; |
772 | 836 | ||
773 | public bool ForceFly | 837 | public bool ForceFly |
@@ -795,7 +859,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
795 | 859 | ||
796 | public ScenePresence( | 860 | public ScenePresence( |
797 | IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) | 861 | IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) |
798 | { | 862 | { |
799 | AttachmentsSyncLock = new Object(); | 863 | AttachmentsSyncLock = new Object(); |
800 | AllowMovement = true; | 864 | AllowMovement = true; |
801 | IsChildAgent = true; | 865 | IsChildAgent = true; |
@@ -841,6 +905,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
841 | SetDirectionVectors(); | 905 | SetDirectionVectors(); |
842 | 906 | ||
843 | Appearance = appearance; | 907 | Appearance = appearance; |
908 | |||
909 | m_stateMachine = new ScenePresenceStateMachine(this); | ||
844 | } | 910 | } |
845 | 911 | ||
846 | private void RegionHeartbeatEnd(Scene scene) | 912 | private void RegionHeartbeatEnd(Scene scene) |
@@ -874,6 +940,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
874 | { | 940 | { |
875 | ControllingClient.OnCompleteMovementToRegion += CompleteMovement; | 941 | ControllingClient.OnCompleteMovementToRegion += CompleteMovement; |
876 | ControllingClient.OnAgentUpdate += HandleAgentUpdate; | 942 | ControllingClient.OnAgentUpdate += HandleAgentUpdate; |
943 | ControllingClient.OnAgentCameraUpdate += HandleAgentCamerasUpdate; | ||
877 | ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; | 944 | ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; |
878 | ControllingClient.OnAgentSit += HandleAgentSit; | 945 | ControllingClient.OnAgentSit += HandleAgentSit; |
879 | ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; | 946 | ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; |
@@ -927,6 +994,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
927 | /// <summary> | 994 | /// <summary> |
928 | /// Turns a child agent into a root agent. | 995 | /// Turns a child agent into a root agent. |
929 | /// </summary> | 996 | /// </summary> |
997 | /// <remarks> | ||
930 | /// 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 |
931 | /// avatar is actual in the sim. They can perform all actions. | 999 | /// avatar is actual in the sim. They can perform all actions. |
932 | /// 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, |
@@ -934,48 +1002,56 @@ namespace OpenSim.Region.Framework.Scenes | |||
934 | /// | 1002 | /// |
935 | /// 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 |
936 | /// delays that crossing. | 1004 | /// delays that crossing. |
937 | /// </summary> | 1005 | /// </remarks> |
938 | public void MakeRootAgent(Vector3 pos, bool isFlying) | 1006 | private bool MakeRootAgent(Vector3 pos, bool isFlying) |
939 | { | 1007 | { |
940 | m_log.DebugFormat( | 1008 | lock (m_completeMovementLock) |
941 | "[SCENE]: Upgrading child to root agent for {0} in {1}", | ||
942 | Name, m_scene.RegionInfo.RegionName); | ||
943 | |||
944 | if (ParentUUID != UUID.Zero) | ||
945 | { | 1009 | { |
946 | m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); | 1010 | if (!IsChildAgent) |
947 | SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); | 1011 | return false; |
948 | 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) | ||
949 | { | 1020 | { |
950 | 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"); | ||
951 | } | 1042 | } |
952 | else | 1043 | else |
953 | { | 1044 | { |
954 | part.ParentGroup.AddAvatar(UUID); | 1045 | IsLoggingIn = false; |
955 | if (part.SitTargetPosition != Vector3.Zero) | ||
956 | part.SitTargetAvatar = UUID; | ||
957 | // ParentPosition = part.GetWorldPosition(); | ||
958 | ParentID = part.LocalId; | ||
959 | ParentPart = part; | ||
960 | m_pos = PrevSitOffset; | ||
961 | // pos = ParentPosition; | ||
962 | pos = part.GetWorldPosition(); | ||
963 | } | 1046 | } |
964 | ParentUUID = UUID.Zero; | ||
965 | 1047 | ||
966 | IsChildAgent = false; | 1048 | IsChildAgent = false; |
967 | |||
968 | // Animator.TrySetMovementAnimation("SIT"); | ||
969 | } | 1049 | } |
970 | else | ||
971 | { | ||
972 | IsChildAgent = false; | ||
973 | IsLoggingIn = false; | ||
974 | } | ||
975 | |||
976 | //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); | ||
977 | 1050 | ||
978 | IsChildAgent = false; | 1051 | // Must reset this here so that a teleport to a region next to an existing region does not keep the flag |
1052 | // set and prevent the close of the connection on a subsequent re-teleport. | ||
1053 | // Should not be needed if we are not trying to tell this region to close | ||
1054 | // DoNotCloseAfterTeleport = false; | ||
979 | 1055 | ||
980 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); | 1056 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); |
981 | if (gm != null) | 1057 | if (gm != null) |
@@ -1116,22 +1192,36 @@ namespace OpenSim.Region.Framework.Scenes | |||
1116 | // 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 |
1117 | // 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 |
1118 | // not transporting the required data. | 1194 | // not transporting the required data. |
1119 | 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) | ||
1120 | { | 1215 | { |
1121 | if (HasAttachments()) | 1216 | m_log.DebugFormat( |
1122 | { | 1217 | "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); |
1123 | m_log.DebugFormat( | ||
1124 | "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); | ||
1125 | 1218 | ||
1126 | // Resume scripts | 1219 | // Resume scripts |
1127 | Util.FireAndForget(delegate(object x) { | 1220 | foreach (SceneObjectGroup sog in attachments) |
1128 | foreach (SceneObjectGroup sog in m_attachments) | 1221 | { |
1129 | { | 1222 | sog.ScheduleGroupForFullUpdate(); |
1130 | sog.ScheduleGroupForFullUpdate(); | 1223 | sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); |
1131 | sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); | 1224 | sog.ResumeScripts(); |
1132 | sog.ResumeScripts(); | ||
1133 | } | ||
1134 | }); | ||
1135 | } | 1225 | } |
1136 | } | 1226 | } |
1137 | } | 1227 | } |
@@ -1153,7 +1243,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1153 | 1243 | ||
1154 | m_scene.EventManager.TriggerOnMakeRootAgent(this); | 1244 | m_scene.EventManager.TriggerOnMakeRootAgent(this); |
1155 | 1245 | ||
1156 | m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd; | 1246 | return true; |
1157 | } | 1247 | } |
1158 | 1248 | ||
1159 | public int GetStateSource() | 1249 | public int GetStateSource() |
@@ -1306,7 +1396,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
1306 | 1396 | ||
1307 | public void StopFlying() | 1397 | public void StopFlying() |
1308 | { | 1398 | { |
1309 | ControllingClient.StopFlying(this); | 1399 | Vector3 pos = AbsolutePosition; |
1400 | if (Appearance.AvatarHeight != 127.0f) | ||
1401 | pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f)); | ||
1402 | else | ||
1403 | pos += new Vector3(0f, 0f, (1.56f / 6f)); | ||
1404 | |||
1405 | AbsolutePosition = pos; | ||
1406 | |||
1407 | // attach a suitable collision plane regardless of the actual situation to force the LLClient to land. | ||
1408 | // Collision plane below the avatar's position a 6th of the avatar's height is suitable. | ||
1409 | // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a | ||
1410 | // certain amount.. because the LLClient wouldn't land in that situation anyway. | ||
1411 | |||
1412 | // why are we still testing for this really old height value default??? | ||
1413 | if (Appearance.AvatarHeight != 127.0f) | ||
1414 | CollisionPlane = new Vector4(0, 0, 0, pos.Z - Appearance.AvatarHeight / 6f); | ||
1415 | else | ||
1416 | CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f)); | ||
1417 | |||
1418 | ControllingClient.SendAgentTerseUpdate(this); | ||
1310 | } | 1419 | } |
1311 | 1420 | ||
1312 | /// <summary> | 1421 | /// <summary> |
@@ -1480,6 +1589,37 @@ namespace OpenSim.Region.Framework.Scenes | |||
1480 | 1589 | ||
1481 | } | 1590 | } |
1482 | 1591 | ||
1592 | private bool WaitForUpdateAgent(IClientAPI client) | ||
1593 | { | ||
1594 | // Before the source region executes UpdateAgent | ||
1595 | // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination, | ||
1596 | // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the | ||
1597 | // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero | ||
1598 | int count = 50; | ||
1599 | UUID originID; | ||
1600 | |||
1601 | lock (m_originRegionIDAccessLock) | ||
1602 | originID = m_originRegionID; | ||
1603 | |||
1604 | while (originID.Equals(UUID.Zero) && count-- > 0) | ||
1605 | { | ||
1606 | lock (m_originRegionIDAccessLock) | ||
1607 | originID = m_originRegionID; | ||
1608 | |||
1609 | m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name); | ||
1610 | Thread.Sleep(200); | ||
1611 | } | ||
1612 | |||
1613 | if (originID.Equals(UUID.Zero)) | ||
1614 | { | ||
1615 | // Movement into region will fail | ||
1616 | m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name); | ||
1617 | return false; | ||
1618 | } | ||
1619 | |||
1620 | return true; | ||
1621 | } | ||
1622 | |||
1483 | /// <summary> | 1623 | /// <summary> |
1484 | /// Complete Avatar's movement into the region. | 1624 | /// Complete Avatar's movement into the region. |
1485 | /// </summary> | 1625 | /// </summary> |
@@ -1493,9 +1633,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
1493 | { | 1633 | { |
1494 | // DateTime startTime = DateTime.Now; | 1634 | // DateTime startTime = DateTime.Now; |
1495 | 1635 | ||
1496 | m_log.DebugFormat( | 1636 | m_log.InfoFormat( |
1497 | "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", | 1637 | "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", |
1498 | client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); | 1638 | client.Name, Scene.Name, AbsolutePosition); |
1639 | |||
1640 | // Make sure it's not a login agent. We don't want to wait for updates during login | ||
1641 | if (PresenceType != PresenceType.Npc && (m_teleportFlags & TeleportFlags.ViaLogin) == 0) | ||
1642 | { | ||
1643 | // Let's wait until UpdateAgent (called by departing region) is done | ||
1644 | if (!WaitForUpdateAgent(client)) | ||
1645 | // The sending region never sent the UpdateAgent data, we have to refuse | ||
1646 | return; | ||
1647 | } | ||
1499 | 1648 | ||
1500 | Vector3 look = Velocity; | 1649 | Vector3 look = Velocity; |
1501 | 1650 | ||
@@ -1517,12 +1666,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
1517 | } | 1666 | } |
1518 | 1667 | ||
1519 | bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); | 1668 | bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); |
1520 | 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 | } | ||
1677 | |||
1678 | // Tell the client that we're totally ready | ||
1521 | ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); | 1679 | ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); |
1522 | 1680 | ||
1681 | // Remember in HandleUseCircuitCode, we delayed this to here | ||
1682 | if (m_teleportFlags > 0) | ||
1683 | SendInitialDataToMe(); | ||
1684 | |||
1523 | // m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); | 1685 | // m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); |
1524 | 1686 | ||
1525 | if ((m_callbackURI != null) && !m_callbackURI.Equals("")) | 1687 | if (!string.IsNullOrEmpty(m_callbackURI)) |
1526 | { | 1688 | { |
1527 | // We cannot sleep here since this would hold up the inbound packet processing thread, as | 1689 | // We cannot sleep here since this would hold up the inbound packet processing thread, as |
1528 | // CompleteMovement() is executed synchronously. However, it might be better to delay the release | 1690 | // CompleteMovement() is executed synchronously. However, it might be better to delay the release |
@@ -1535,7 +1697,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1535 | "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", | 1697 | "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", |
1536 | client.Name, client.AgentId, m_callbackURI); | 1698 | client.Name, client.AgentId, m_callbackURI); |
1537 | 1699 | ||
1538 | Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); | 1700 | UUID originID; |
1701 | |||
1702 | lock (m_originRegionIDAccessLock) | ||
1703 | originID = m_originRegionID; | ||
1704 | |||
1705 | Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI); | ||
1539 | m_callbackURI = null; | 1706 | m_callbackURI = null; |
1540 | } | 1707 | } |
1541 | // else | 1708 | // else |
@@ -1550,7 +1717,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1550 | // Create child agents in neighbouring regions | 1717 | // Create child agents in neighbouring regions |
1551 | if (openChildAgents && !IsChildAgent) | 1718 | if (openChildAgents && !IsChildAgent) |
1552 | { | 1719 | { |
1553 | |||
1554 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); | 1720 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); |
1555 | if (m_agentTransfer != null) | 1721 | if (m_agentTransfer != null) |
1556 | m_agentTransfer.EnableChildAgents(this); | 1722 | m_agentTransfer.EnableChildAgents(this); |
@@ -1573,6 +1739,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1573 | // m_log.DebugFormat( | 1739 | // m_log.DebugFormat( |
1574 | // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", | 1740 | // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", |
1575 | // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); | 1741 | // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); |
1742 | |||
1576 | } | 1743 | } |
1577 | 1744 | ||
1578 | /// <summary> | 1745 | /// <summary> |
@@ -1653,9 +1820,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1653 | /// </summary> | 1820 | /// </summary> |
1654 | public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) | 1821 | public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) |
1655 | { | 1822 | { |
1656 | // m_log.DebugFormat( | 1823 | //m_log.DebugFormat( |
1657 | // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", | 1824 | // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", |
1658 | // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); | 1825 | // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); |
1659 | 1826 | ||
1660 | if (IsChildAgent) | 1827 | if (IsChildAgent) |
1661 | { | 1828 | { |
@@ -1663,10 +1830,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1663 | return; | 1830 | return; |
1664 | } | 1831 | } |
1665 | 1832 | ||
1666 | ++m_movementUpdateCount; | ||
1667 | if (m_movementUpdateCount < 1) | ||
1668 | m_movementUpdateCount = 1; | ||
1669 | |||
1670 | #region Sanity Checking | 1833 | #region Sanity Checking |
1671 | 1834 | ||
1672 | // This is irritating. Really. | 1835 | // This is irritating. Really. |
@@ -1697,21 +1860,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1697 | 1860 | ||
1698 | AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; | 1861 | AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; |
1699 | 1862 | ||
1700 | // Camera location in world. We'll need to raytrace | ||
1701 | // from this location from time to time. | ||
1702 | CameraPosition = agentData.CameraCenter; | ||
1703 | if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance) | ||
1704 | { | ||
1705 | ReprioritizeUpdates(); | ||
1706 | m_lastCameraPosition = CameraPosition; | ||
1707 | } | ||
1708 | |||
1709 | // Use these three vectors to figure out what the agent is looking at | ||
1710 | // Convert it to a Matrix and/or Quaternion | ||
1711 | CameraAtAxis = agentData.CameraAtAxis; | ||
1712 | CameraLeftAxis = agentData.CameraLeftAxis; | ||
1713 | CameraUpAxis = agentData.CameraUpAxis; | ||
1714 | |||
1715 | // The Agent's Draw distance setting | 1863 | // The Agent's Draw distance setting |
1716 | // When we get to the point of re-computing neighbors everytime this | 1864 | // When we get to the point of re-computing neighbors everytime this |
1717 | // changes, then start using the agent's drawdistance rather than the | 1865 | // changes, then start using the agent's drawdistance rather than the |
@@ -1783,9 +1931,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1783 | // Here's where you get them. | 1931 | // Here's where you get them. |
1784 | m_AgentControlFlags = flags; | 1932 | m_AgentControlFlags = flags; |
1785 | m_headrotation = agentData.HeadRotation; | 1933 | m_headrotation = agentData.HeadRotation; |
1934 | byte oldState = State; | ||
1786 | State = agentData.State; | 1935 | State = agentData.State; |
1787 | 1936 | ||
1937 | // We need to send this back to the client in order to stop the edit beams | ||
1938 | if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None) | ||
1939 | ControllingClient.SendAgentTerseUpdate(this); | ||
1940 | |||
1788 | PhysicsActor actor = PhysicsActor; | 1941 | PhysicsActor actor = PhysicsActor; |
1942 | |||
1943 | // This will be the case if the agent is sitting on the groudn or on an object. | ||
1789 | if (actor == null) | 1944 | if (actor == null) |
1790 | { | 1945 | { |
1791 | SendControlsToScripts(flagsForScripts); | 1946 | SendControlsToScripts(flagsForScripts); |
@@ -1794,12 +1949,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1794 | 1949 | ||
1795 | if (AllowMovement && !SitGround) | 1950 | if (AllowMovement && !SitGround) |
1796 | { | 1951 | { |
1797 | Quaternion bodyRotation = agentData.BodyRotation; | 1952 | // m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name); |
1953 | |||
1798 | bool update_rotation = false; | 1954 | bool update_rotation = false; |
1799 | 1955 | ||
1800 | if (bodyRotation != Rotation) | 1956 | if (agentData.BodyRotation != Rotation) |
1801 | { | 1957 | { |
1802 | Rotation = bodyRotation; | 1958 | Rotation = agentData.BodyRotation; |
1803 | update_rotation = true; | 1959 | update_rotation = true; |
1804 | } | 1960 | } |
1805 | 1961 | ||
@@ -1845,10 +2001,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1845 | else | 2001 | else |
1846 | dirVectors = Dir_Vectors; | 2002 | dirVectors = Dir_Vectors; |
1847 | 2003 | ||
1848 | // The fact that MovementFlag is a byte needs to be fixed | ||
1849 | // it really should be a uint | ||
1850 | // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. | 2004 | // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. |
1851 | uint nudgehack = 250; | ||
1852 | foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) | 2005 | foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) |
1853 | { | 2006 | { |
1854 | if (((uint)flags & (uint)DCF) != 0) | 2007 | if (((uint)flags & (uint)DCF) != 0) |
@@ -1865,29 +2018,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
1865 | // Why did I get this? | 2018 | // Why did I get this? |
1866 | } | 2019 | } |
1867 | 2020 | ||
1868 | if ((MovementFlag & (byte)(uint)DCF) == 0) | 2021 | if (((MovementFlag & (uint)DCF) == 0) & !AgentControlStopActive) |
1869 | { | 2022 | { |
1870 | if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE || | ||
1871 | DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE) | ||
1872 | { | ||
1873 | MovementFlag |= (byte)nudgehack; | ||
1874 | } | ||
1875 | |||
1876 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); | 2023 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); |
1877 | MovementFlag += (byte)(uint)DCF; | 2024 | MovementFlag += (uint)DCF; |
1878 | update_movementflag = true; | 2025 | update_movementflag = true; |
1879 | } | 2026 | } |
1880 | } | 2027 | } |
1881 | else | 2028 | else |
1882 | { | 2029 | { |
1883 | if ((MovementFlag & (byte)(uint)DCF) != 0 || | 2030 | if ((MovementFlag & (uint)DCF) != 0) |
1884 | ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE || | ||
1885 | DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE) | ||
1886 | && ((MovementFlag & (byte)nudgehack) == nudgehack)) | ||
1887 | ) // This or is for Nudge forward | ||
1888 | { | 2031 | { |
1889 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); | 2032 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); |
1890 | MovementFlag -= ((byte)(uint)DCF); | 2033 | MovementFlag -= (uint)DCF; |
1891 | update_movementflag = true; | 2034 | update_movementflag = true; |
1892 | 2035 | ||
1893 | /* | 2036 | /* |
@@ -1907,6 +2050,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1907 | i++; | 2050 | i++; |
1908 | } | 2051 | } |
1909 | 2052 | ||
2053 | // Detect AGENT_CONTROL_STOP state changes | ||
2054 | if (AgentControlStopActive != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0)) | ||
2055 | { | ||
2056 | AgentControlStopActive = !AgentControlStopActive; | ||
2057 | update_movementflag = true; | ||
2058 | } | ||
2059 | |||
1910 | if (MovingToTarget) | 2060 | if (MovingToTarget) |
1911 | { | 2061 | { |
1912 | // If the user has pressed a key then we want to cancel any move to target. | 2062 | // If the user has pressed a key then we want to cancel any move to target. |
@@ -1932,53 +2082,79 @@ namespace OpenSim.Region.Framework.Scenes | |||
1932 | // Only do this if we're flying | 2082 | // Only do this if we're flying |
1933 | if (Flying && !ForceFly) | 2083 | if (Flying && !ForceFly) |
1934 | { | 2084 | { |
1935 | // Landing detection code | 2085 | // Need to stop in mid air if user holds down AGENT_CONTROL_STOP |
1936 | 2086 | if (AgentControlStopActive) | |
1937 | // Are the landing controls requirements filled? | ||
1938 | bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || | ||
1939 | ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); | ||
1940 | |||
1941 | //m_log.Debug("[CONTROL]: " +flags); | ||
1942 | // Applies a satisfying roll effect to the avatar when flying. | ||
1943 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) | ||
1944 | { | ||
1945 | ApplyFlyingRoll( | ||
1946 | FLY_ROLL_RADIANS_PER_UPDATE, | ||
1947 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | ||
1948 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | ||
1949 | } | ||
1950 | else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && | ||
1951 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) | ||
1952 | { | 2087 | { |
1953 | ApplyFlyingRoll( | 2088 | agent_control_v3 = Vector3.Zero; |
1954 | -FLY_ROLL_RADIANS_PER_UPDATE, | ||
1955 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | ||
1956 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | ||
1957 | } | 2089 | } |
1958 | else | 2090 | else |
1959 | { | 2091 | { |
1960 | if (m_AngularVelocity.Z != 0) | 2092 | // Landing detection code |
1961 | m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); | ||
1962 | } | ||
1963 | 2093 | ||
1964 | if (Flying && IsColliding && controlland) | 2094 | // Are the landing controls requirements filled? |
1965 | { | 2095 | bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || |
1966 | // nesting this check because LengthSquared() is expensive and we don't | 2096 | ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); |
1967 | // want to do it every step when flying. | 2097 | |
1968 | if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) | 2098 | //m_log.Debug("[CONTROL]: " +flags); |
1969 | StopFlying(); | 2099 | // Applies a satisfying roll effect to the avatar when flying. |
2100 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) | ||
2101 | { | ||
2102 | ApplyFlyingRoll( | ||
2103 | FLY_ROLL_RADIANS_PER_UPDATE, | ||
2104 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | ||
2105 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | ||
2106 | } | ||
2107 | else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && | ||
2108 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) | ||
2109 | { | ||
2110 | ApplyFlyingRoll( | ||
2111 | -FLY_ROLL_RADIANS_PER_UPDATE, | ||
2112 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | ||
2113 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | ||
2114 | } | ||
2115 | else | ||
2116 | { | ||
2117 | if (m_AngularVelocity.Z != 0) | ||
2118 | m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); | ||
2119 | } | ||
2120 | |||
2121 | if (Flying && IsColliding && controlland) | ||
2122 | { | ||
2123 | // nesting this check because LengthSquared() is expensive and we don't | ||
2124 | // want to do it every step when flying. | ||
2125 | if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) | ||
2126 | StopFlying(); | ||
2127 | } | ||
1970 | } | 2128 | } |
1971 | } | 2129 | } |
1972 | 2130 | ||
2131 | // m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name); | ||
2132 | |||
1973 | // If the agent update does move the avatar, then calculate the force ready for the velocity update, | 2133 | // If the agent update does move the avatar, then calculate the force ready for the velocity update, |
1974 | // which occurs later in the main scene loop | 2134 | // which occurs later in the main scene loop |
1975 | if (update_movementflag || (update_rotation && DCFlagKeyPressed)) | 2135 | // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they |
2136 | // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update | ||
2137 | // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the | ||
2138 | // avatar location in place). | ||
2139 | if (update_movementflag | ||
2140 | || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0))) | ||
1976 | { | 2141 | { |
1977 | // m_log.DebugFormat( | 2142 | // if (update_movementflag || !AgentControlStopActive || MovementFlag != 0) |
1978 | // "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}", | 2143 | // { |
1979 | // m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation); | 2144 | // m_log.DebugFormat( |
2145 | // "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, mf = {4}, ur = {5}", | ||
2146 | // m_scene.RegionInfo.RegionName, agent_control_v3, Name, | ||
2147 | // update_movementflag, MovementFlag, update_rotation); | ||
1980 | 2148 | ||
1981 | AddNewMovement(agent_control_v3); | 2149 | float speedModifier; |
2150 | |||
2151 | if (AgentControlStopActive) | ||
2152 | speedModifier = AgentControlStopSlowWhilstMoving; | ||
2153 | else | ||
2154 | speedModifier = 1; | ||
2155 | |||
2156 | AddNewMovement(agent_control_v3, speedModifier); | ||
2157 | // } | ||
1982 | } | 2158 | } |
1983 | // else | 2159 | // else |
1984 | // { | 2160 | // { |
@@ -1991,15 +2167,86 @@ namespace OpenSim.Region.Framework.Scenes | |||
1991 | // } | 2167 | // } |
1992 | 2168 | ||
1993 | if (update_movementflag && ParentID == 0) | 2169 | if (update_movementflag && ParentID == 0) |
2170 | { | ||
2171 | // m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name); | ||
1994 | Animator.UpdateMovementAnimations(); | 2172 | Animator.UpdateMovementAnimations(); |
2173 | } | ||
1995 | 2174 | ||
1996 | SendControlsToScripts(flagsForScripts); | 2175 | SendControlsToScripts(flagsForScripts); |
1997 | } | 2176 | } |
1998 | 2177 | ||
2178 | // We need to send this back to the client in order to see the edit beams | ||
2179 | if ((State & (uint)AgentState.Editing) != 0) | ||
2180 | ControllingClient.SendAgentTerseUpdate(this); | ||
2181 | |||
1999 | m_scene.EventManager.TriggerOnClientMovement(this); | 2182 | m_scene.EventManager.TriggerOnClientMovement(this); |
2000 | TriggerScenePresenceUpdated(); | ||
2001 | } | 2183 | } |
2002 | 2184 | ||
2185 | |||
2186 | /// <summary> | ||
2187 | /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering. | ||
2188 | /// </summary> | ||
2189 | private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) | ||
2190 | { | ||
2191 | //m_log.DebugFormat( | ||
2192 | // "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}", | ||
2193 | // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); | ||
2194 | |||
2195 | if (IsChildAgent) | ||
2196 | { | ||
2197 | // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); | ||
2198 | return; | ||
2199 | } | ||
2200 | |||
2201 | ++m_movementUpdateCount; | ||
2202 | if (m_movementUpdateCount < 1) | ||
2203 | m_movementUpdateCount = 1; | ||
2204 | |||
2205 | // AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; | ||
2206 | |||
2207 | // Camera location in world. We'll need to raytrace | ||
2208 | // from this location from time to time. | ||
2209 | CameraPosition = agentData.CameraCenter; | ||
2210 | if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance) | ||
2211 | { | ||
2212 | ReprioritizeUpdates(); | ||
2213 | m_lastCameraPosition = CameraPosition; | ||
2214 | } | ||
2215 | |||
2216 | // Use these three vectors to figure out what the agent is looking at | ||
2217 | // Convert it to a Matrix and/or Quaternion | ||
2218 | CameraAtAxis = agentData.CameraAtAxis; | ||
2219 | CameraLeftAxis = agentData.CameraLeftAxis; | ||
2220 | CameraUpAxis = agentData.CameraUpAxis; | ||
2221 | |||
2222 | // The Agent's Draw distance setting | ||
2223 | // When we get to the point of re-computing neighbors everytime this | ||
2224 | // changes, then start using the agent's drawdistance rather than the | ||
2225 | // region's draw distance. | ||
2226 | // DrawDistance = agentData.Far; | ||
2227 | DrawDistance = Scene.DefaultDrawDistance; | ||
2228 | |||
2229 | // Check if Client has camera in 'follow cam' or 'build' mode. | ||
2230 | Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation); | ||
2231 | |||
2232 | m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f) | ||
2233 | && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; | ||
2234 | |||
2235 | |||
2236 | //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); | ||
2237 | // Raycast from the avatar's head to the camera to see if there's anything blocking the view | ||
2238 | if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) | ||
2239 | { | ||
2240 | if (m_followCamAuto) | ||
2241 | { | ||
2242 | Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; | ||
2243 | m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback); | ||
2244 | } | ||
2245 | } | ||
2246 | |||
2247 | TriggerScenePresenceUpdated(); | ||
2248 | } | ||
2249 | |||
2003 | /// <summary> | 2250 | /// <summary> |
2004 | /// Calculate an update to move the presence to the set target. | 2251 | /// Calculate an update to move the presence to the set target. |
2005 | /// </summary> | 2252 | /// </summary> |
@@ -2252,17 +2499,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2252 | { | 2499 | { |
2253 | // m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); | 2500 | // m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); |
2254 | 2501 | ||
2502 | bool satOnObject = IsSatOnObject; | ||
2503 | SceneObjectPart part = ParentPart; | ||
2255 | SitGround = false; | 2504 | SitGround = false; |
2256 | 2505 | ||
2257 | /* move this down so avatar gets physical in the new position and not where it is siting | 2506 | if (satOnObject) |
2258 | if (PhysicsActor == null) | ||
2259 | AddToPhysicalScene(false); | ||
2260 | */ | ||
2261 | |||
2262 | if (ParentID != 0) | ||
2263 | { | 2507 | { |
2264 | PrevSitOffset = m_pos; // Save sit offset | 2508 | PrevSitOffset = m_pos; // Save sit offset |
2265 | SceneObjectPart part = ParentPart; | ||
2266 | UnRegisterSeatControls(part.ParentGroup.UUID); | 2509 | UnRegisterSeatControls(part.ParentGroup.UUID); |
2267 | 2510 | ||
2268 | TaskInventoryDictionary taskIDict = part.TaskInventory; | 2511 | TaskInventoryDictionary taskIDict = part.TaskInventory; |
@@ -2281,34 +2524,71 @@ namespace OpenSim.Region.Framework.Scenes | |||
2281 | } | 2524 | } |
2282 | 2525 | ||
2283 | part.ParentGroup.DeleteAvatar(UUID); | 2526 | part.ParentGroup.DeleteAvatar(UUID); |
2284 | // ParentPosition = part.GetWorldPosition(); | 2527 | Vector3 sitPartWorldPosition = part.GetWorldPosition(); |
2285 | ControllingClient.SendClearFollowCamProperties(part.ParentUUID); | 2528 | ControllingClient.SendClearFollowCamProperties(part.ParentUUID); |
2286 | 2529 | ||
2287 | // m_pos += ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); | ||
2288 | // ParentPosition = Vector3.Zero; | ||
2289 | m_pos = part.AbsolutePosition + (m_pos * part.GetWorldRotation()) + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); | ||
2290 | if (part.SitTargetAvatar == UUID) | ||
2291 | m_bodyRot = part.GetWorldRotation() * part.SitTargetOrientation; | ||
2292 | |||
2293 | ParentID = 0; | 2530 | ParentID = 0; |
2294 | ParentPart = null; | 2531 | ParentPart = null; |
2295 | 2532 | ||
2296 | if (PhysicsActor == null) | 2533 | Quaternion standRotation; |
2297 | AddToPhysicalScene(false); | ||
2298 | 2534 | ||
2535 | if (part.SitTargetAvatar == UUID) | ||
2536 | { | ||
2537 | standRotation = part.GetWorldRotation(); | ||
2538 | |||
2539 | if (!part.IsRoot) | ||
2540 | standRotation = standRotation * part.SitTargetOrientation; | ||
2541 | // standRotation = part.RotationOffset * part.SitTargetOrientation; | ||
2542 | // else | ||
2543 | // standRotation = part.SitTargetOrientation; | ||
2544 | |||
2545 | } | ||
2546 | else | ||
2547 | { | ||
2548 | standRotation = Rotation; | ||
2549 | } | ||
2550 | |||
2551 | //Vector3 standPos = ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); | ||
2552 | //Vector3 standPos = ParentPosition; | ||
2553 | |||
2554 | // Vector3 standPositionAdjustment | ||
2555 | // = part.SitTargetPosition + new Vector3(0.5f, 0f, m_sitAvatarHeight / 2f); | ||
2556 | Vector3 adjustmentForSitPosition = part.SitTargetPosition * part.GetWorldRotation(); | ||
2557 | |||
2558 | // XXX: This is based on the physics capsule sizes. Need to find a better way to read this rather than | ||
2559 | // hardcoding here. | ||
2560 | Vector3 adjustmentForSitPose = new Vector3(0.74f, 0f, 0f) * standRotation; | ||
2561 | |||
2562 | Vector3 standPos = sitPartWorldPosition + adjustmentForSitPosition + adjustmentForSitPose; | ||
2563 | |||
2564 | // m_log.DebugFormat( | ||
2565 | // "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}", | ||
2566 | // standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name); | ||
2567 | |||
2568 | Rotation = standRotation; | ||
2569 | AbsolutePosition = standPos; | ||
2570 | } | ||
2571 | |||
2572 | // We need to wait until we have calculated proper stand positions before sitting up the physical | ||
2573 | // avatar to avoid race conditions. | ||
2574 | if (PhysicsActor == null) | ||
2575 | AddToPhysicalScene(false); | ||
2576 | |||
2577 | if (satOnObject) | ||
2578 | { | ||
2299 | SendAvatarDataToAllAgents(); | 2579 | SendAvatarDataToAllAgents(); |
2300 | m_requestedSitTargetID = 0; | 2580 | m_requestedSitTargetID = 0; |
2301 | 2581 | ||
2302 | part.RemoveSittingAvatar(UUID); | 2582 | part.RemoveSittingAvatar(UUID); |
2303 | 2583 | ||
2304 | if (part != null) | 2584 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); |
2305 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); | ||
2306 | } | 2585 | } |
2307 | 2586 | ||
2308 | else if (PhysicsActor == null) | 2587 | else if (PhysicsActor == null) |
2309 | AddToPhysicalScene(false); | 2588 | AddToPhysicalScene(false); |
2310 | 2589 | ||
2311 | Animator.TrySetMovementAnimation("STAND"); | 2590 | Animator.TrySetMovementAnimation("STAND"); |
2591 | TriggerScenePresenceUpdated(); | ||
2312 | } | 2592 | } |
2313 | 2593 | ||
2314 | private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) | 2594 | private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) |
@@ -2359,7 +2639,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2359 | m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; | 2639 | m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; |
2360 | 2640 | ||
2361 | bool canSit = false; | 2641 | bool canSit = false; |
2362 | Vector3 pos = part.AbsolutePosition + offset; | ||
2363 | 2642 | ||
2364 | if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) | 2643 | if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) |
2365 | { | 2644 | { |
@@ -2369,6 +2648,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2369 | 2648 | ||
2370 | offset = part.SitTargetPosition; | 2649 | offset = part.SitTargetPosition; |
2371 | sitOrientation = part.SitTargetOrientation; | 2650 | sitOrientation = part.SitTargetOrientation; |
2651 | |||
2652 | if (!part.IsRoot) | ||
2653 | { | ||
2654 | // m_log.DebugFormat("Old sit orient {0}", sitOrientation); | ||
2655 | sitOrientation = part.RotationOffset * sitOrientation; | ||
2656 | // m_log.DebugFormat("New sit orient {0}", sitOrientation); | ||
2657 | // m_log.DebugFormat("Old sit offset {0}", offset); | ||
2658 | offset = offset * part.RotationOffset; | ||
2659 | // m_log.DebugFormat("New sit offset {0}", offset); | ||
2660 | } | ||
2661 | |||
2372 | canSit = true; | 2662 | canSit = true; |
2373 | } | 2663 | } |
2374 | else | 2664 | else |
@@ -2376,9 +2666,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
2376 | if (PhysicsSit(part,offset)) // physics engine | 2666 | if (PhysicsSit(part,offset)) // physics engine |
2377 | return; | 2667 | return; |
2378 | 2668 | ||
2669 | Vector3 pos = part.AbsolutePosition + offset; | ||
2670 | |||
2379 | if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) | 2671 | if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) |
2380 | { | 2672 | { |
2381 | |||
2382 | AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); | 2673 | AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); |
2383 | canSit = true; | 2674 | canSit = true; |
2384 | } | 2675 | } |
@@ -2404,10 +2695,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
2404 | cameraEyeOffset = part.GetCameraEyeOffset(); | 2695 | cameraEyeOffset = part.GetCameraEyeOffset(); |
2405 | forceMouselook = part.GetForceMouselook(); | 2696 | forceMouselook = part.GetForceMouselook(); |
2406 | 2697 | ||
2698 | // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is | ||
2699 | // being sat upon. | ||
2700 | offset += part.OffsetPosition; | ||
2701 | |||
2407 | ControllingClient.SendSitResponse( | 2702 | ControllingClient.SendSitResponse( |
2408 | part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); | 2703 | part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); |
2409 | 2704 | ||
2410 | m_requestedSitTargetUUID = targetID; | 2705 | m_requestedSitTargetUUID = part.UUID; |
2411 | 2706 | ||
2412 | HandleAgentSit(ControllingClient, UUID); | 2707 | HandleAgentSit(ControllingClient, UUID); |
2413 | 2708 | ||
@@ -2435,7 +2730,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2435 | if (part != null) | 2730 | if (part != null) |
2436 | { | 2731 | { |
2437 | m_requestedSitTargetID = part.LocalId; | 2732 | m_requestedSitTargetID = part.LocalId; |
2438 | m_requestedSitTargetUUID = targetID; | 2733 | m_requestedSitTargetUUID = part.UUID; |
2439 | 2734 | ||
2440 | } | 2735 | } |
2441 | else | 2736 | else |
@@ -2554,6 +2849,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2554 | 2849 | ||
2555 | public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) | 2850 | public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) |
2556 | { | 2851 | { |
2852 | if (IsChildAgent) | ||
2853 | return; | ||
2854 | |||
2557 | SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); | 2855 | SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); |
2558 | 2856 | ||
2559 | if (part != null) | 2857 | if (part != null) |
@@ -2603,24 +2901,40 @@ namespace OpenSim.Region.Framework.Scenes | |||
2603 | Vector3 up = new Vector3((float)x, (float)y, (float)z); | 2901 | Vector3 up = new Vector3((float)x, (float)y, (float)z); |
2604 | Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; | 2902 | Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; |
2605 | 2903 | ||
2606 | m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; | 2904 | Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; |
2905 | Quaternion newRot; | ||
2906 | |||
2907 | if (part.IsRoot) | ||
2908 | { | ||
2909 | newRot = sitTargetOrient; | ||
2910 | } | ||
2911 | else | ||
2912 | { | ||
2913 | newPos = newPos * part.RotationOffset; | ||
2914 | newRot = part.RotationOffset * sitTargetOrient; | ||
2915 | } | ||
2916 | |||
2917 | newPos += part.OffsetPosition; | ||
2918 | |||
2919 | m_pos = newPos; | ||
2920 | Rotation = newRot; | ||
2607 | 2921 | ||
2608 | // m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset; | ||
2609 | Rotation = sitTargetOrient; | ||
2610 | // ParentPosition = part.AbsolutePosition; | 2922 | // ParentPosition = part.AbsolutePosition; |
2611 | part.ParentGroup.AddAvatar(UUID); | ||
2612 | } | 2923 | } |
2613 | else | 2924 | else |
2614 | { | 2925 | { |
2615 | m_pos -= part.AbsolutePosition; | 2926 | // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is |
2927 | // being sat upon. | ||
2928 | m_pos -= part.GroupPosition; | ||
2929 | |||
2616 | // ParentPosition = part.AbsolutePosition; | 2930 | // ParentPosition = part.AbsolutePosition; |
2617 | part.ParentGroup.AddAvatar(UUID); | ||
2618 | 2931 | ||
2619 | // m_log.DebugFormat( | 2932 | // m_log.DebugFormat( |
2620 | // "[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", |
2621 | // Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); | 2934 | // Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); |
2622 | } | 2935 | } |
2623 | 2936 | ||
2937 | part.ParentGroup.AddAvatar(UUID); | ||
2624 | ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); | 2938 | ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); |
2625 | ParentID = m_requestedSitTargetID; | 2939 | ParentID = m_requestedSitTargetID; |
2626 | m_AngularVelocity = Vector3.Zero; | 2940 | m_AngularVelocity = Vector3.Zero; |
@@ -2634,14 +2948,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
2634 | } | 2948 | } |
2635 | Animator.TrySetMovementAnimation(sitAnimation); | 2949 | Animator.TrySetMovementAnimation(sitAnimation); |
2636 | SendAvatarDataToAllAgents(); | 2950 | SendAvatarDataToAllAgents(); |
2951 | TriggerScenePresenceUpdated(); | ||
2637 | } | 2952 | } |
2638 | } | 2953 | } |
2639 | 2954 | ||
2640 | public void HandleAgentSitOnGround() | 2955 | public void HandleAgentSitOnGround() |
2641 | { | 2956 | { |
2957 | if (IsChildAgent) | ||
2958 | return; | ||
2959 | |||
2642 | // m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. | 2960 | // m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. |
2643 | m_AngularVelocity = Vector3.Zero; | 2961 | m_AngularVelocity = Vector3.Zero; |
2644 | Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); | 2962 | Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); |
2963 | TriggerScenePresenceUpdated(); | ||
2645 | SitGround = true; | 2964 | SitGround = true; |
2646 | RemoveFromPhysicalScene(); | 2965 | RemoveFromPhysicalScene(); |
2647 | } | 2966 | } |
@@ -2658,11 +2977,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2658 | public void HandleStartAnim(IClientAPI remoteClient, UUID animID) | 2977 | public void HandleStartAnim(IClientAPI remoteClient, UUID animID) |
2659 | { | 2978 | { |
2660 | Animator.AddAnimation(animID, UUID.Zero); | 2979 | Animator.AddAnimation(animID, UUID.Zero); |
2980 | TriggerScenePresenceUpdated(); | ||
2661 | } | 2981 | } |
2662 | 2982 | ||
2663 | public void HandleStopAnim(IClientAPI remoteClient, UUID animID) | 2983 | public void HandleStopAnim(IClientAPI remoteClient, UUID animID) |
2664 | { | 2984 | { |
2665 | Animator.RemoveAnimation(animID, false); | 2985 | Animator.RemoveAnimation(animID, false); |
2986 | TriggerScenePresenceUpdated(); | ||
2666 | } | 2987 | } |
2667 | 2988 | ||
2668 | public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) | 2989 | public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) |
@@ -2676,10 +2997,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2676 | /// Rotate the avatar to the given rotation and apply a movement in the given relative vector | 2997 | /// Rotate the avatar to the given rotation and apply a movement in the given relative vector |
2677 | /// </summary> | 2998 | /// </summary> |
2678 | /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> | 2999 | /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> |
2679 | public void AddNewMovement(Vector3 vec) | 3000 | /// <param name="thisAddSpeedModifier"> |
3001 | /// Optional additional speed modifier for this particular add. Default is 1</param> | ||
3002 | public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1) | ||
2680 | { | 3003 | { |
2681 | // m_log.DebugFormat( | 3004 | // m_log.DebugFormat( |
2682 | // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1} for {2}", vec, Rotation, Name); | 3005 | // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}", |
3006 | // vec, Rotation, thisAddSpeedModifier, Name); | ||
2683 | 3007 | ||
2684 | Vector3 direc = vec * Rotation; | 3008 | Vector3 direc = vec * Rotation; |
2685 | direc.Normalize(); | 3009 | direc.Normalize(); |
@@ -2697,7 +3021,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2697 | if ((vec.Z == 0f) && !Flying) | 3021 | if ((vec.Z == 0f) && !Flying) |
2698 | direc.Z = 0f; // Prevent camera WASD up. | 3022 | direc.Z = 0f; // Prevent camera WASD up. |
2699 | 3023 | ||
2700 | direc *= 0.03f * 128f * SpeedModifier; | 3024 | direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier; |
2701 | 3025 | ||
2702 | // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); | 3026 | // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); |
2703 | 3027 | ||
@@ -2843,6 +3167,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2843 | lastTerseUpdateToAllClientsTick = currentTick; | 3167 | lastTerseUpdateToAllClientsTick = currentTick; |
2844 | lastPositionSentToAllClients = OffsetPosition; | 3168 | lastPositionSentToAllClients = OffsetPosition; |
2845 | 3169 | ||
3170 | // Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name); | ||
2846 | m_scene.ForEachClient(SendTerseUpdateToClient); | 3171 | m_scene.ForEachClient(SendTerseUpdateToClient); |
2847 | } | 3172 | } |
2848 | TriggerScenePresenceUpdated(); | 3173 | TriggerScenePresenceUpdated(); |
@@ -2880,11 +3205,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2880 | SendOtherAgentsAppearanceToMe(); | 3205 | SendOtherAgentsAppearanceToMe(); |
2881 | 3206 | ||
2882 | EntityBase[] entities = Scene.Entities.GetEntities(); | 3207 | EntityBase[] entities = Scene.Entities.GetEntities(); |
2883 | foreach(EntityBase e in entities) | 3208 | foreach (EntityBase e in entities) |
2884 | { | 3209 | { |
2885 | if (e != null && e is SceneObjectGroup) | 3210 | if (e != null && e is SceneObjectGroup) |
2886 | ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); | 3211 | ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); |
2887 | } | 3212 | } |
3213 | |||
2888 | }); | 3214 | }); |
2889 | } | 3215 | } |
2890 | 3216 | ||
@@ -2919,12 +3245,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
2919 | // 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 |
2920 | // appearance goes into the avatar update packet | 3246 | // appearance goes into the avatar update packet |
2921 | SendAvatarDataToAllAgents(); | 3247 | SendAvatarDataToAllAgents(); |
3248 | |||
3249 | // This invocation always shows up in the viewer logs as an error. Is it needed? | ||
2922 | SendAppearanceToAgent(this); | 3250 | SendAppearanceToAgent(this); |
2923 | 3251 | ||
2924 | // 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 |
2925 | if (cachedappearance) | 3253 | if (cachedappearance) |
2926 | { | 3254 | { |
2927 | m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name); | 3255 | m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name); |
2928 | 3256 | ||
2929 | // If the avatars baked textures are all in the cache, then we have a | 3257 | // If the avatars baked textures are all in the cache, then we have a |
2930 | // complete appearance... send it out, if not, then we'll send it when | 3258 | // complete appearance... send it out, if not, then we'll send it when |
@@ -3079,11 +3407,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
3079 | } | 3407 | } |
3080 | 3408 | ||
3081 | // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m | 3409 | // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m |
3082 | if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || | 3410 | if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance) |
3083 | Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance) | ||
3084 | { | 3411 | { |
3085 | m_lastChildAgentUpdatePosition = AbsolutePosition; | 3412 | m_lastChildAgentUpdatePosition = AbsolutePosition; |
3086 | m_lastChildAgentUpdateCamPosition = CameraPosition; | 3413 | // m_lastChildAgentUpdateCamPosition = CameraPosition; |
3087 | 3414 | ||
3088 | ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); | 3415 | ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); |
3089 | cadu.ActiveGroupID = UUID.Zero.Guid; | 3416 | cadu.ActiveGroupID = UUID.Zero.Guid; |
@@ -3110,7 +3437,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3110 | cadu.Velocity = Velocity; | 3437 | cadu.Velocity = Velocity; |
3111 | 3438 | ||
3112 | AgentPosition agentpos = new AgentPosition(); | 3439 | AgentPosition agentpos = new AgentPosition(); |
3113 | agentpos.CopyFrom(cadu); | 3440 | agentpos.CopyFrom(cadu, ControllingClient.SessionId); |
3114 | 3441 | ||
3115 | // Let's get this out of the update loop | 3442 | // Let's get this out of the update loop |
3116 | Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); | 3443 | Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); |
@@ -3294,11 +3621,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3294 | } | 3621 | } |
3295 | } | 3622 | } |
3296 | 3623 | ||
3297 | public void RestoreInCurrentScene() | ||
3298 | { | ||
3299 | AddToPhysicalScene(false); // not exactly false | ||
3300 | } | ||
3301 | |||
3302 | public void Reset() | 3624 | public void Reset() |
3303 | { | 3625 | { |
3304 | // m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); | 3626 | // m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); |
@@ -3348,10 +3670,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3348 | if (byebyeRegions.Count > 0) | 3670 | if (byebyeRegions.Count > 0) |
3349 | { | 3671 | { |
3350 | m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); | 3672 | m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); |
3351 | Util.FireAndForget(delegate | 3673 | |
3352 | { | 3674 | AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID); |
3353 | m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, byebyeRegions); | 3675 | string auth = string.Empty; |
3354 | }); | 3676 | if (acd != null) |
3677 | auth = acd.SessionID.ToString(); | ||
3678 | m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions); | ||
3355 | } | 3679 | } |
3356 | 3680 | ||
3357 | foreach (ulong handle in byebyeRegions) | 3681 | foreach (ulong handle in byebyeRegions) |
@@ -3392,7 +3716,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3392 | 3716 | ||
3393 | #region Child Agent Updates | 3717 | #region Child Agent Updates |
3394 | 3718 | ||
3395 | public void ChildAgentDataUpdate(AgentData cAgentData) | 3719 | public void UpdateChildAgent(AgentData cAgentData) |
3396 | { | 3720 | { |
3397 | // m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); | 3721 | // m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); |
3398 | if (!IsChildAgent) | 3722 | if (!IsChildAgent) |
@@ -3402,15 +3726,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
3402 | } | 3726 | } |
3403 | 3727 | ||
3404 | private static Vector3 marker = new Vector3(-1f, -1f, -1f); | 3728 | private static Vector3 marker = new Vector3(-1f, -1f, -1f); |
3729 | |||
3405 | private void RaiseUpdateThrottles() | 3730 | private void RaiseUpdateThrottles() |
3406 | { | 3731 | { |
3407 | m_scene.EventManager.TriggerThrottleUpdate(this); | 3732 | m_scene.EventManager.TriggerThrottleUpdate(this); |
3408 | } | 3733 | } |
3734 | |||
3409 | /// <summary> | 3735 | /// <summary> |
3410 | /// This updates important decision making data about a child agent | 3736 | /// This updates important decision making data about a child agent |
3411 | /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region | 3737 | /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region |
3412 | /// </summary> | 3738 | /// </summary> |
3413 | public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) | 3739 | public void UpdateChildAgent(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) |
3414 | { | 3740 | { |
3415 | if (!IsChildAgent) | 3741 | if (!IsChildAgent) |
3416 | return; | 3742 | return; |
@@ -3452,6 +3778,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3452 | 3778 | ||
3453 | cAgent.AgentID = UUID; | 3779 | cAgent.AgentID = UUID; |
3454 | cAgent.RegionID = Scene.RegionInfo.RegionID; | 3780 | cAgent.RegionID = Scene.RegionInfo.RegionID; |
3781 | cAgent.SessionID = ControllingClient.SessionId; | ||
3455 | 3782 | ||
3456 | cAgent.Position = AbsolutePosition; | 3783 | cAgent.Position = AbsolutePosition; |
3457 | cAgent.Velocity = m_velocity; | 3784 | cAgent.Velocity = m_velocity; |
@@ -3517,7 +3844,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3517 | 3844 | ||
3518 | private void CopyFrom(AgentData cAgent) | 3845 | private void CopyFrom(AgentData cAgent) |
3519 | { | 3846 | { |
3520 | m_originRegionID = cAgent.RegionID; | 3847 | lock (m_originRegionIDAccessLock) |
3848 | m_originRegionID = cAgent.RegionID; | ||
3521 | 3849 | ||
3522 | m_callbackURI = cAgent.CallbackURI; | 3850 | m_callbackURI = cAgent.CallbackURI; |
3523 | // m_log.DebugFormat( | 3851 | // m_log.DebugFormat( |
@@ -3611,8 +3939,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3611 | { | 3939 | { |
3612 | Vector3 force = m_forceToApply.Value; | 3940 | Vector3 force = m_forceToApply.Value; |
3613 | 3941 | ||
3614 | Updated = true; | ||
3615 | |||
3616 | Velocity = force; | 3942 | Velocity = force; |
3617 | 3943 | ||
3618 | m_forceToApply = null; | 3944 | m_forceToApply = null; |
@@ -3694,7 +4020,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3694 | 4020 | ||
3695 | // if (m_updateCount > 0) | 4021 | // if (m_updateCount > 0) |
3696 | // { | 4022 | // { |
3697 | Animator.UpdateMovementAnimations(); | 4023 | if (Animator.UpdateMovementAnimations()) |
4024 | TriggerScenePresenceUpdated(); | ||
3698 | // m_updateCount--; | 4025 | // m_updateCount--; |
3699 | // } | 4026 | // } |
3700 | 4027 | ||
@@ -3858,6 +4185,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3858 | // Animator.Close(); | 4185 | // Animator.Close(); |
3859 | Animator = null; | 4186 | Animator = null; |
3860 | 4187 | ||
4188 | LifecycleState = ScenePresenceState.Removed; | ||
3861 | } | 4189 | } |
3862 | 4190 | ||
3863 | public void AddAttachment(SceneObjectGroup gobj) | 4191 | public void AddAttachment(SceneObjectGroup gobj) |