diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4969 |
1 files changed, 3336 insertions, 1633 deletions
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 1fddd91..74f765d 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -90,7 +90,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
90 | m_scene.EventManager.TriggerScenePresenceUpdated(this); | 90 | m_scene.EventManager.TriggerScenePresenceUpdated(this); |
91 | } | 91 | } |
92 | 92 | ||
93 | public PresenceType PresenceType { get; private set; } | 93 | public bool IsNPC { get; private set; } |
94 | |||
95 | // simple yes or no isGOD from god level >= 200 | ||
96 | // should only be set by GodController | ||
97 | // we have two to suport legacy behaviour | ||
98 | // IsViewerUIGod was controlled by viewer in older versions | ||
99 | // IsGod may now be also controled by viewer acording to options | ||
100 | public bool IsViewerUIGod { get; set; } | ||
101 | public bool IsGod { get; set; } | ||
102 | |||
103 | private PresenceType m_presenceType; | ||
104 | public PresenceType PresenceType | ||
105 | { | ||
106 | get {return m_presenceType;} | ||
107 | private set | ||
108 | { | ||
109 | m_presenceType = value; | ||
110 | IsNPC = (m_presenceType == PresenceType.Npc); | ||
111 | } | ||
112 | } | ||
94 | 113 | ||
95 | private ScenePresenceStateMachine m_stateMachine; | 114 | private ScenePresenceStateMachine m_stateMachine; |
96 | 115 | ||
@@ -98,8 +117,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
98 | /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine | 117 | /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine |
99 | /// for more details. | 118 | /// for more details. |
100 | /// </summary> | 119 | /// </summary> |
101 | public ScenePresenceState LifecycleState | 120 | public ScenePresenceState LifecycleState |
102 | { | 121 | { |
103 | get | 122 | get |
104 | { | 123 | { |
105 | return m_stateMachine.GetState(); | 124 | return m_stateMachine.GetState(); |
@@ -116,7 +135,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
116 | /// the viewer fires these in quick succession. | 135 | /// the viewer fires these in quick succession. |
117 | /// </summary> | 136 | /// </summary> |
118 | /// <remarks> | 137 | /// <remarks> |
119 | /// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement | 138 | /// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement |
120 | /// regulation done there. | 139 | /// regulation done there. |
121 | /// </remarks> | 140 | /// </remarks> |
122 | private object m_completeMovementLock = new object(); | 141 | private object m_completeMovementLock = new object(); |
@@ -124,7 +143,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
124 | // private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); | 143 | // private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); |
125 | private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); | 144 | private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); |
126 | private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); | 145 | private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); |
127 | 146 | ||
128 | /// <summary> | 147 | /// <summary> |
129 | /// Experimentally determined "fudge factor" to make sit-target positions | 148 | /// Experimentally determined "fudge factor" to make sit-target positions |
130 | /// the same as in SecondLife. Fudge factor was tested for 36 different | 149 | /// the same as in SecondLife. Fudge factor was tested for 36 different |
@@ -134,21 +153,116 @@ namespace OpenSim.Region.Framework.Scenes | |||
134 | /// issue #1716 | 153 | /// issue #1716 |
135 | /// </summary> | 154 | /// </summary> |
136 | public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f); | 155 | public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f); |
156 | public bool LegacySitOffsets = true; | ||
137 | 157 | ||
138 | /// <summary> | 158 | /// <summary> |
139 | /// Movement updates for agents in neighboring regions are sent directly to clients. | 159 | /// Movement updates for agents in neighboring regions are sent directly to clients. |
140 | /// This value only affects how often agent positions are sent to neighbor regions | 160 | /// This value only affects how often agent positions are sent to neighbor regions |
141 | /// for things such as distance-based update prioritization | 161 | /// for things such as distance-based update prioritization |
162 | /// this are the square of real distances | ||
142 | /// </summary> | 163 | /// </summary> |
143 | public static readonly float SIGNIFICANT_MOVEMENT = 2.0f; | 164 | public static readonly float MOVEMENT = .25f; |
165 | public static readonly float SIGNIFICANT_MOVEMENT = 16.0f; | ||
166 | public static readonly float CHILDUPDATES_MOVEMENT = 100.0f; | ||
167 | public static readonly float CHILDUPDATES_TIME = 2000f; // min time between child updates (ms) | ||
144 | 168 | ||
145 | public UUID currentParcelUUID = UUID.Zero; | 169 | private UUID m_previusParcelUUID = UUID.Zero; |
170 | private UUID m_currentParcelUUID = UUID.Zero; | ||
171 | private bool m_previusParcelHide = false; | ||
172 | private bool m_currentParcelHide = false; | ||
173 | private object parcelLock = new Object(); | ||
174 | public double ParcelDwellTickMS; | ||
175 | |||
176 | public UUID currentParcelUUID | ||
177 | { | ||
178 | get { return m_currentParcelUUID; } | ||
179 | set | ||
180 | { | ||
181 | lock (parcelLock) | ||
182 | { | ||
183 | bool oldhide = m_currentParcelHide; | ||
184 | bool checksame = true; | ||
185 | if (value != m_currentParcelUUID) | ||
186 | { | ||
187 | ParcelDwellTickMS = Util.GetTimeStampMS(); | ||
188 | m_previusParcelHide = m_currentParcelHide; | ||
189 | m_previusParcelUUID = m_currentParcelUUID; | ||
190 | checksame = false; | ||
191 | } | ||
192 | m_currentParcelUUID = value; | ||
193 | m_currentParcelHide = false; | ||
194 | |||
195 | ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y); | ||
196 | if (land != null && !land.LandData.SeeAVs) | ||
197 | m_currentParcelHide = true; | ||
198 | |||
199 | if (m_previusParcelUUID != UUID.Zero || checksame) | ||
200 | ParcelCrossCheck(m_currentParcelUUID, m_previusParcelUUID, m_currentParcelHide, m_previusParcelHide, oldhide,checksame); | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | |||
205 | public void sitSOGmoved() | ||
206 | { | ||
207 | /* | ||
208 | if (IsDeleted || !IsSatOnObject) | ||
209 | //what me? nahh | ||
210 | return; | ||
211 | if (IsInTransit) | ||
212 | return; | ||
213 | |||
214 | ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y); | ||
215 | if (land == null) | ||
216 | return; //?? | ||
217 | UUID parcelID = land.LandData.GlobalID; | ||
218 | if (m_currentParcelUUID != parcelID) | ||
219 | currentParcelUUID = parcelID; | ||
220 | */ | ||
221 | } | ||
222 | |||
223 | public bool ParcelAllowThisAvatarSounds | ||
224 | { | ||
225 | get | ||
226 | { | ||
227 | try | ||
228 | { | ||
229 | lock (parcelLock) | ||
230 | { | ||
231 | ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y); | ||
232 | if (land == null) | ||
233 | return true; | ||
234 | if (land.LandData.AnyAVSounds) | ||
235 | return true; | ||
236 | if (!land.LandData.GroupAVSounds) | ||
237 | return false; | ||
238 | return ControllingClient.IsGroupMember(land.LandData.GroupID); | ||
239 | } | ||
240 | } | ||
241 | catch | ||
242 | { | ||
243 | return true; | ||
244 | } | ||
245 | } | ||
246 | } | ||
247 | |||
248 | public bool ParcelHideThisAvatar | ||
249 | { | ||
250 | get | ||
251 | { | ||
252 | return m_currentParcelHide; | ||
253 | } | ||
254 | } | ||
146 | 255 | ||
147 | /// <value> | 256 | /// <value> |
148 | /// The animator for this avatar | 257 | /// The animator for this avatar |
149 | /// </value> | 258 | /// </value> |
150 | public ScenePresenceAnimator Animator { get; private set; } | 259 | public ScenePresenceAnimator Animator { get; private set; } |
151 | 260 | ||
261 | /// <value> | ||
262 | /// Server Side Animation Override | ||
263 | /// </value> | ||
264 | public MovementAnimationOverrides Overrides { get; private set; } | ||
265 | public String sitAnimation = "SIT"; | ||
152 | /// <summary> | 266 | /// <summary> |
153 | /// Attachments recorded on this avatar. | 267 | /// Attachments recorded on this avatar. |
154 | /// </summary> | 268 | /// </summary> |
@@ -164,21 +278,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
164 | private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO; | 278 | private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO; |
165 | private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO; | 279 | private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO; |
166 | private bool MouseDown = false; | 280 | private bool MouseDown = false; |
167 | // private SceneObjectGroup proxyObjectGroup; | ||
168 | //private SceneObjectPart proxyObjectPart = null; | ||
169 | public Vector3 lastKnownAllowedPosition; | 281 | public Vector3 lastKnownAllowedPosition; |
170 | public bool sentMessageAboutRestrictedParcelFlyingDown; | 282 | public bool sentMessageAboutRestrictedParcelFlyingDown; |
283 | |||
171 | public Vector4 CollisionPlane = Vector4.UnitW; | 284 | public Vector4 CollisionPlane = Vector4.UnitW; |
172 | 285 | ||
286 | public Vector4 m_lastCollisionPlane = Vector4.UnitW; | ||
287 | private byte m_lastState; | ||
173 | private Vector3 m_lastPosition; | 288 | private Vector3 m_lastPosition; |
174 | private Quaternion m_lastRotation; | 289 | private Quaternion m_lastRotation; |
175 | private Vector3 m_lastVelocity; | 290 | private Vector3 m_lastVelocity; |
176 | private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); | 291 | private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); |
292 | private bool SentInitialData = false; | ||
177 | 293 | ||
178 | private bool m_followCamAuto = false; | ||
179 | |||
180 | |||
181 | private Vector3? m_forceToApply; | ||
182 | private int m_userFlags; | 294 | private int m_userFlags; |
183 | public int UserFlags | 295 | public int UserFlags |
184 | { | 296 | { |
@@ -192,23 +304,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
192 | set { PhysicsActor.Flying = value; } | 304 | set { PhysicsActor.Flying = value; } |
193 | } | 305 | } |
194 | 306 | ||
195 | // add for fly velocity control | 307 | public bool IsColliding |
196 | private bool FlyingOld {get; set;} | ||
197 | public bool WasFlying | ||
198 | { | ||
199 | get; private set; | ||
200 | } | ||
201 | |||
202 | public bool IsColliding | ||
203 | { | 308 | { |
204 | get { return PhysicsActor != null && PhysicsActor.IsColliding; } | 309 | get { return PhysicsActor != null && PhysicsActor.IsColliding; } |
205 | // We would expect setting IsColliding to be private but it's used by a hack in Scene | 310 | // We would expect setting IsColliding to be private but it's used by a hack in Scene |
206 | set { PhysicsActor.IsColliding = value; } | 311 | set { PhysicsActor.IsColliding = value; } |
207 | } | 312 | } |
208 | 313 | ||
209 | // private int m_lastColCount = -1; //KF: Look for Collision chnages | 314 | private List<uint> m_lastColliders = new List<uint>(); |
210 | // private int m_updateCount = 0; //KF: Update Anims for a while | ||
211 | // private static readonly int UPDATE_COUNT = 10; // how many frames to update for | ||
212 | 315 | ||
213 | private TeleportFlags m_teleportFlags; | 316 | private TeleportFlags m_teleportFlags; |
214 | public TeleportFlags TeleportFlags | 317 | public TeleportFlags TeleportFlags |
@@ -233,9 +336,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
233 | 336 | ||
234 | private float m_sitAvatarHeight = 2.0f; | 337 | private float m_sitAvatarHeight = 2.0f; |
235 | 338 | ||
339 | private bool m_childUpdatesBusy = false; | ||
340 | private int m_lastChildUpdatesTime; | ||
341 | private int m_lastChildAgentUpdateGodLevel; | ||
342 | private float m_lastChildAgentUpdateDrawDistance; | ||
236 | private Vector3 m_lastChildAgentUpdatePosition; | 343 | private Vector3 m_lastChildAgentUpdatePosition; |
237 | // private Vector3 m_lastChildAgentUpdateCamPosition; | 344 | // private Vector3 m_lastChildAgentUpdateCamPosition; |
238 | 345 | ||
346 | private Vector3 m_lastCameraRayCastCam; | ||
347 | private Vector3 m_lastCameraRayCastPos; | ||
348 | |||
349 | private float m_FOV = 1.04f; | ||
350 | |||
239 | private const int LAND_VELOCITYMAG_MAX = 12; | 351 | private const int LAND_VELOCITYMAG_MAX = 12; |
240 | 352 | ||
241 | private const float FLY_ROLL_MAX_RADIANS = 1.1f; | 353 | private const float FLY_ROLL_MAX_RADIANS = 1.1f; |
@@ -244,32 +356,51 @@ namespace OpenSim.Region.Framework.Scenes | |||
244 | private const float FLY_ROLL_RESET_RADIANS_PER_UPDATE = 0.02f; | 356 | private const float FLY_ROLL_RESET_RADIANS_PER_UPDATE = 0.02f; |
245 | 357 | ||
246 | private float m_health = 100f; | 358 | private float m_health = 100f; |
359 | private float m_healRate = 1f; | ||
360 | private float m_healRatePerFrame = 0.05f; | ||
247 | 361 | ||
248 | protected ulong crossingFromRegion; | 362 | private readonly Vector3[] Dir_Vectors = new Vector3[12]; |
249 | 363 | ||
250 | private readonly Vector3[] Dir_Vectors = new Vector3[11]; | 364 | protected int m_reprioritizationLastTime; |
251 | 365 | protected bool m_reprioritizationBusy; | |
252 | protected Timer m_reprioritization_timer; | 366 | protected Vector3 m_reprioritizationLastPosition; |
253 | protected bool m_reprioritizing; | 367 | protected float m_reprioritizationLastDrawDistance; |
254 | protected bool m_reprioritization_called; | ||
255 | 368 | ||
256 | private Quaternion m_headrotation = Quaternion.Identity; | 369 | private Quaternion m_headrotation = Quaternion.Identity; |
257 | 370 | ||
258 | //PauPaw:Proper PID Controler for autopilot************ | 371 | //PauPaw:Proper PID Controler for autopilot************ |
259 | public bool MovingToTarget { get; private set; } | 372 | |
260 | public Vector3 MoveToPositionTarget { get; private set; } | 373 | private bool m_movingToTarget; |
374 | public bool MovingToTarget | ||
375 | { | ||
376 | get {return m_movingToTarget;} | ||
377 | private set {m_movingToTarget = value; } | ||
378 | } | ||
379 | |||
380 | private Vector3 m_moveToPositionTarget; | ||
381 | public Vector3 MoveToPositionTarget | ||
382 | { | ||
383 | get {return m_moveToPositionTarget;} | ||
384 | private set {m_moveToPositionTarget = value; } | ||
385 | } | ||
386 | |||
387 | private float m_moveToSpeed; | ||
388 | public float MoveToSpeed | ||
389 | { | ||
390 | get {return m_moveToSpeed;} | ||
391 | private set {m_moveToSpeed = value; } | ||
392 | } | ||
393 | |||
394 | private double m_delayedStop = -1.0; | ||
261 | 395 | ||
262 | /// <summary> | 396 | /// <summary> |
263 | /// Controls whether an avatar automatically moving to a target will land when it gets there (if flying). | 397 | /// Controls whether an avatar automatically moving to a target will land when it gets there (if flying). |
264 | /// </summary> | 398 | /// </summary> |
265 | public bool LandAtTarget { get; private set; } | 399 | public bool LandAtTarget { get; private set; } |
266 | 400 | ||
267 | private int m_movementUpdateCount; | ||
268 | private const int NumMovementsBetweenRayCast = 5; | ||
269 | |||
270 | private bool CameraConstraintActive; | 401 | private bool CameraConstraintActive; |
271 | //private int m_moveToPositionStateStatus; | 402 | |
272 | //***************************************************** | 403 | private object m_collisionEventLock = new Object(); |
273 | 404 | ||
274 | private int m_movementAnimationUpdateCounter = 0; | 405 | private int m_movementAnimationUpdateCounter = 0; |
275 | 406 | ||
@@ -287,7 +418,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
287 | } | 418 | } |
288 | } | 419 | } |
289 | 420 | ||
290 | public bool SentInitialDataToClient { get; private set; } | ||
291 | 421 | ||
292 | /// <summary> | 422 | /// <summary> |
293 | /// Copy of the script states while the agent is in transit. This state may | 423 | /// Copy of the script states while the agent is in transit. This state may |
@@ -303,7 +433,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
303 | /// <summary> | 433 | /// <summary> |
304 | /// Implemented Control Flags | 434 | /// Implemented Control Flags |
305 | /// </summary> | 435 | /// </summary> |
306 | private enum Dir_ControlFlags | 436 | private enum Dir_ControlFlags:uint |
307 | { | 437 | { |
308 | DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, | 438 | DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, |
309 | DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, | 439 | DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, |
@@ -315,13 +445,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
315 | DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, | 445 | DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, |
316 | DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, | 446 | DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, |
317 | DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, | 447 | DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, |
448 | DIR_CONTROL_FLAG_UP_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS, | ||
318 | DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG | 449 | DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG |
319 | } | 450 | } |
320 | 451 | ||
321 | /// <summary> | 452 | /// <summary> |
322 | /// Position at which a significant movement was made | 453 | /// Position at which a significant movement was made |
323 | /// </summary> | 454 | /// </summary> |
324 | private Vector3 posLastSignificantMove; | 455 | private Vector3 posLastSignificantMove; |
456 | private Vector3 posLastMove; | ||
325 | 457 | ||
326 | #region For teleports and crossings callbacks | 458 | #region For teleports and crossings callbacks |
327 | 459 | ||
@@ -346,10 +478,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
346 | /// </summary> | 478 | /// </summary> |
347 | private object m_originRegionIDAccessLock = new object(); | 479 | private object m_originRegionIDAccessLock = new object(); |
348 | 480 | ||
349 | /// <summary> | 481 | |
350 | /// Triggered on entity transfer after to allow CompleteMovement() to proceed after we have received an | ||
351 | /// UpdateAgent from the originating region.ddkjjkj | ||
352 | /// </summary> | ||
353 | private AutoResetEvent m_updateAgentReceivedAfterTransferEvent = new AutoResetEvent(false); | 482 | private AutoResetEvent m_updateAgentReceivedAfterTransferEvent = new AutoResetEvent(false); |
354 | 483 | ||
355 | /// <summary> | 484 | /// <summary> |
@@ -366,6 +495,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
366 | /// </value> | 495 | /// </value> |
367 | private IScriptModule[] m_scriptEngines; | 496 | private IScriptModule[] m_scriptEngines; |
368 | 497 | ||
498 | private enum LandingPointBehavior | ||
499 | { | ||
500 | OS = 1, | ||
501 | SL = 2 | ||
502 | } | ||
503 | |||
504 | private LandingPointBehavior m_LandingPointBehavior = LandingPointBehavior.OS; | ||
505 | |||
369 | #region Properties | 506 | #region Properties |
370 | 507 | ||
371 | /// <summary> | 508 | /// <summary> |
@@ -379,11 +516,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
379 | public uint MovementFlag { get; private set; } | 516 | public uint MovementFlag { get; private set; } |
380 | 517 | ||
381 | /// <summary> | 518 | /// <summary> |
382 | /// Set this if we need to force a movement update on the next received AgentUpdate from the viewer. | ||
383 | /// </summary> | ||
384 | private const uint ForceUpdateMovementFlagValue = uint.MaxValue; | ||
385 | |||
386 | /// <summary> | ||
387 | /// Is the agent stop control flag currently active? | 519 | /// Is the agent stop control flag currently active? |
388 | /// </summary> | 520 | /// </summary> |
389 | public bool AgentControlStopActive { get; private set; } | 521 | public bool AgentControlStopActive { get; private set; } |
@@ -396,28 +528,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
396 | get { return m_invulnerable; } | 528 | get { return m_invulnerable; } |
397 | } | 529 | } |
398 | 530 | ||
399 | private int m_userLevel; | 531 | public GodController GodController { get; private set; } |
400 | |||
401 | public int UserLevel | ||
402 | { | ||
403 | get { return m_userLevel; } | ||
404 | private set { m_userLevel = value; } | ||
405 | } | ||
406 | |||
407 | private int m_godLevel; | ||
408 | |||
409 | public int GodLevel | ||
410 | { | ||
411 | get { return m_godLevel; } | ||
412 | private set { m_godLevel = value; } | ||
413 | } | ||
414 | 532 | ||
415 | private ulong m_rootRegionHandle; | 533 | private ulong m_rootRegionHandle; |
534 | private Vector3 m_rootRegionPosition = new Vector3(); | ||
416 | 535 | ||
417 | public ulong RegionHandle | 536 | public ulong RegionHandle |
418 | { | 537 | { |
419 | get { return m_rootRegionHandle; } | 538 | get { return m_rootRegionHandle; } |
420 | private set { m_rootRegionHandle = value; } | 539 | private set |
540 | { | ||
541 | m_rootRegionHandle = value; | ||
542 | // position rounded to lower multiple of 256m | ||
543 | m_rootRegionPosition.X = (float)((m_rootRegionHandle >> 32) & 0xffffff00); | ||
544 | m_rootRegionPosition.Y = (float)(m_rootRegionHandle & 0xffffff00); | ||
545 | } | ||
421 | } | 546 | } |
422 | 547 | ||
423 | #region Client Camera | 548 | #region Client Camera |
@@ -425,17 +550,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
425 | /// <summary> | 550 | /// <summary> |
426 | /// Position of agent's camera in world (region cordinates) | 551 | /// Position of agent's camera in world (region cordinates) |
427 | /// </summary> | 552 | /// </summary> |
428 | protected Vector3 m_lastCameraPosition; | 553 | // protected Vector3 m_lastCameraPosition; |
429 | 554 | ||
430 | private Vector4 m_lastCameraCollisionPlane = new Vector4(0f, 0f, 0f, 1); | 555 | private Vector4 m_lastCameraCollisionPlane = new Vector4(0f, 0f, 0f, 1); |
431 | private bool m_doingCamRayCast = false; | 556 | private bool m_doingCamRayCast = false; |
432 | 557 | ||
433 | public Vector3 CameraPosition { get; set; } | 558 | public Vector3 CameraPosition { get; set; } |
434 | 559 | public Quaternion CameraRotation { get; private set; } | |
435 | public Quaternion CameraRotation | ||
436 | { | ||
437 | get { return Util.Axes2Rot(CameraAtAxis, CameraLeftAxis, CameraUpAxis); } | ||
438 | } | ||
439 | 560 | ||
440 | // Use these three vectors to figure out what the agent is looking at | 561 | // Use these three vectors to figure out what the agent is looking at |
441 | // Convert it to a Matrix and/or Quaternion | 562 | // Convert it to a Matrix and/or Quaternion |
@@ -449,39 +570,51 @@ namespace OpenSim.Region.Framework.Scenes | |||
449 | get | 570 | get |
450 | { | 571 | { |
451 | Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0); | 572 | Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0); |
452 | 573 | a.Normalize(); | |
453 | if (a == Vector3.Zero) | 574 | return a; |
454 | return a; | ||
455 | |||
456 | return Util.GetNormalizedVector(a); | ||
457 | } | 575 | } |
458 | } | 576 | } |
459 | #endregion | 577 | #endregion |
460 | 578 | ||
461 | public string Firstname { get; private set; } | 579 | public string Firstname { get; private set; } |
462 | public string Lastname { get; private set; } | 580 | public string Lastname { get; private set; } |
463 | 581 | ||
582 | public bool haveGroupInformation; | ||
583 | public bool gotCrossUpdate; | ||
584 | public byte crossingFlags; | ||
585 | |||
464 | public string Grouptitle | 586 | public string Grouptitle |
465 | { | 587 | { |
466 | get { return UseFakeGroupTitle ? "(Loading)" : m_groupTitle; } | 588 | get { return m_groupTitle; } |
467 | set { m_groupTitle = value; } | 589 | set { m_groupTitle = value; } |
468 | } | 590 | } |
469 | private string m_groupTitle; | 591 | private string m_groupTitle; |
470 | 592 | ||
471 | /// <summary> | ||
472 | /// When this is 'true', return a dummy group title instead of the real group title. This is | ||
473 | /// used as part of a hack to force viewers to update the displayed avatar name. | ||
474 | /// </summary> | ||
475 | public bool UseFakeGroupTitle { get; set; } | ||
476 | |||
477 | |||
478 | // Agent's Draw distance. | 593 | // Agent's Draw distance. |
479 | public float DrawDistance { get; set; } | 594 | private float m_drawDistance = 255f; |
595 | public float DrawDistance | ||
596 | { | ||
597 | get | ||
598 | { | ||
599 | return m_drawDistance; | ||
600 | } | ||
601 | set | ||
602 | { | ||
603 | m_drawDistance = Util.Clamp(value, 32f, m_scene.MaxDrawDistance); | ||
604 | } | ||
605 | } | ||
606 | |||
607 | public float RegionViewDistance | ||
608 | { | ||
609 | get | ||
610 | { | ||
611 | return Util.Clamp(m_drawDistance, 32f, m_scene.MaxRegionViewDistance); | ||
612 | } | ||
613 | } | ||
480 | 614 | ||
481 | public bool AllowMovement { get; set; } | 615 | public bool AllowMovement { get; set; } |
482 | 616 | ||
483 | private bool m_setAlwaysRun; | 617 | private bool m_setAlwaysRun; |
484 | |||
485 | public bool SetAlwaysRun | 618 | public bool SetAlwaysRun |
486 | { | 619 | { |
487 | get | 620 | get |
@@ -557,12 +690,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
557 | // in the sim unless the avatar is on a sit target. While | 690 | // in the sim unless the avatar is on a sit target. While |
558 | // on a sit target, m_pos will contain the desired offset | 691 | // on a sit target, m_pos will contain the desired offset |
559 | // without the parent rotation applied. | 692 | // without the parent rotation applied. |
560 | SceneObjectPart sitPart = ParentPart; | 693 | if (ParentPart != null) |
561 | 694 | { | |
562 | if (sitPart != null) | 695 | SceneObjectPart rootPart = ParentPart.ParentGroup.RootPart; |
563 | return sitPart.ParentGroup.AbsolutePosition + (m_pos * sitPart.GetWorldRotation()); | 696 | // if (sitPart != null) |
697 | // return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation()); | ||
698 | if (rootPart != null) | ||
699 | return rootPart.AbsolutePosition + (m_pos * rootPart.GetWorldRotation()); | ||
700 | } | ||
564 | } | 701 | } |
565 | 702 | ||
566 | return m_pos; | 703 | return m_pos; |
567 | } | 704 | } |
568 | set | 705 | set |
@@ -614,11 +751,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
614 | } | 751 | } |
615 | 752 | ||
616 | /// <summary> | 753 | /// <summary> |
617 | /// Velocity of the avatar with respect to its local reference frame. | 754 | /// Current velocity of the avatar. |
618 | /// </summary> | 755 | /// </summary> |
619 | /// <remarks> | ||
620 | /// So when sat on a vehicle this will be 0. To get velocity with respect to the world use GetWorldVelocity() | ||
621 | /// </remarks> | ||
622 | public override Vector3 Velocity | 756 | public override Vector3 Velocity |
623 | { | 757 | { |
624 | get | 758 | get |
@@ -631,21 +765,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
631 | // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", | 765 | // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", |
632 | // m_velocity, Name, Scene.RegionInfo.RegionName); | 766 | // m_velocity, Name, Scene.RegionInfo.RegionName); |
633 | } | 767 | } |
634 | // else if (ParentPart != null) | ||
635 | // { | ||
636 | // return ParentPart.ParentGroup.Velocity; | ||
637 | // } | ||
638 | 768 | ||
639 | return m_velocity; | 769 | return m_velocity; |
640 | } | 770 | } |
641 | 771 | ||
642 | set | 772 | set |
643 | { | 773 | { |
644 | // Util.PrintCallStack(); | ||
645 | // m_log.DebugFormat( | ||
646 | // "[SCENE PRESENCE]: In {0} set velocity of {1} to {2}", | ||
647 | // Scene.RegionInfo.RegionName, Name, value); | ||
648 | |||
649 | if (PhysicsActor != null) | 774 | if (PhysicsActor != null) |
650 | { | 775 | { |
651 | try | 776 | try |
@@ -658,27 +783,42 @@ namespace OpenSim.Region.Framework.Scenes | |||
658 | } | 783 | } |
659 | } | 784 | } |
660 | 785 | ||
661 | m_velocity = value; | 786 | m_velocity = value; |
787 | |||
788 | // m_log.DebugFormat( | ||
789 | // "[SCENE PRESENCE]: In {0} set velocity of {1} to {2}", | ||
790 | // Scene.RegionInfo.RegionName, Name, m_velocity); | ||
662 | } | 791 | } |
663 | } | 792 | } |
664 | /* | 793 | |
665 | public override Vector3 AngularVelocity | 794 | // requested Velocity for physics engines avatar motors |
795 | // only makes sense if there is a physical rep | ||
796 | public Vector3 TargetVelocity | ||
666 | { | 797 | { |
667 | get | 798 | get |
668 | { | 799 | { |
669 | if (PhysicsActor != null) | 800 | if (PhysicsActor != null) |
670 | { | 801 | return PhysicsActor.TargetVelocity; |
671 | m_rotationalvelocity = PhysicsActor.RotationalVelocity; | 802 | else |
803 | return Vector3.Zero; | ||
804 | } | ||
672 | 805 | ||
673 | // m_log.DebugFormat( | 806 | set |
674 | // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", | 807 | { |
675 | // m_velocity, Name, Scene.RegionInfo.RegionName); | 808 | if (PhysicsActor != null) |
809 | { | ||
810 | try | ||
811 | { | ||
812 | PhysicsActor.TargetVelocity = value; | ||
813 | } | ||
814 | catch (Exception e) | ||
815 | { | ||
816 | m_log.Error("[SCENE PRESENCE]: TARGETVELOCITY " + e.Message); | ||
817 | } | ||
676 | } | 818 | } |
677 | |||
678 | return m_rotationalvelocity; | ||
679 | } | 819 | } |
680 | } | 820 | } |
681 | */ | 821 | |
682 | private Quaternion m_bodyRot = Quaternion.Identity; | 822 | private Quaternion m_bodyRot = Quaternion.Identity; |
683 | 823 | ||
684 | /// <summary> | 824 | /// <summary> |
@@ -691,9 +831,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
691 | /// </remarks> | 831 | /// </remarks> |
692 | public Quaternion Rotation | 832 | public Quaternion Rotation |
693 | { | 833 | { |
694 | get | 834 | get |
695 | { | 835 | { |
696 | return m_bodyRot; | 836 | return m_bodyRot; |
697 | } | 837 | } |
698 | 838 | ||
699 | set | 839 | set |
@@ -758,16 +898,42 @@ namespace OpenSim.Region.Framework.Scenes | |||
758 | set { m_health = value; } | 898 | set { m_health = value; } |
759 | } | 899 | } |
760 | 900 | ||
901 | public float HealRate | ||
902 | { | ||
903 | get { return m_healRate; } | ||
904 | set | ||
905 | { | ||
906 | if(value > 100.0f) | ||
907 | m_healRate = 100.0f; | ||
908 | else if (value <= 0.0) | ||
909 | m_healRate = 0.0f; | ||
910 | else | ||
911 | m_healRate = value; | ||
912 | |||
913 | if(Scene != null) | ||
914 | m_healRatePerFrame = m_healRate * Scene.FrameTime; | ||
915 | else | ||
916 | m_healRatePerFrame = 0.05f; | ||
917 | } | ||
918 | } | ||
919 | |||
920 | |||
761 | /// <summary> | 921 | /// <summary> |
762 | /// Get rotation relative to the world. | 922 | /// Gets the world rotation of this presence. |
763 | /// </summary> | 923 | /// </summary> |
924 | /// <remarks> | ||
925 | /// Unlike Rotation, this returns the world rotation no matter whether the avatar is sitting on a prim or not. | ||
926 | /// </remarks> | ||
764 | /// <returns></returns> | 927 | /// <returns></returns> |
765 | public Quaternion GetWorldRotation() | 928 | public Quaternion GetWorldRotation() |
766 | { | 929 | { |
767 | SceneObjectPart sitPart = ParentPart; | 930 | if (IsSatOnObject) |
931 | { | ||
932 | SceneObjectPart sitPart = ParentPart; | ||
768 | 933 | ||
769 | if (sitPart != null) | 934 | if (sitPart != null) |
770 | return sitPart.GetWorldRotation() * Rotation; | 935 | return sitPart.GetWorldRotation() * Rotation; |
936 | } | ||
771 | 937 | ||
772 | return Rotation; | 938 | return Rotation; |
773 | } | 939 | } |
@@ -793,26 +959,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
793 | seeds = Scene.CapsModule.GetChildrenSeeds(UUID); | 959 | seeds = Scene.CapsModule.GetChildrenSeeds(UUID); |
794 | else | 960 | else |
795 | seeds = new Dictionary<ulong, string>(); | 961 | seeds = new Dictionary<ulong, string>(); |
796 | |||
797 | List<ulong> old = new List<ulong>(); | ||
798 | foreach (ulong handle in seeds.Keys) | ||
799 | { | ||
800 | uint x, y; | ||
801 | Util.RegionHandleToRegionLoc(handle, out x, out y); | ||
802 | |||
803 | if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY)) | ||
804 | { | ||
805 | old.Add(handle); | ||
806 | } | ||
807 | } | ||
808 | DropOldNeighbours(old); | ||
809 | |||
810 | if (Scene.CapsModule != null) | ||
811 | Scene.CapsModule.SetChildrenSeed(UUID, seeds); | ||
812 | |||
813 | KnownRegions = seeds; | 962 | KnownRegions = seeds; |
814 | //m_log.Debug(" ++++++++++AFTER+++++++++++++ "); | ||
815 | //DumpKnownRegions(); | ||
816 | } | 963 | } |
817 | 964 | ||
818 | public void DumpKnownRegions() | 965 | public void DumpKnownRegions() |
@@ -827,20 +974,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
827 | } | 974 | } |
828 | 975 | ||
829 | private bool m_mouseLook; | 976 | private bool m_mouseLook; |
830 | // private bool m_leftButtonDown; | 977 | private bool m_leftButtonDown; |
831 | 978 | ||
832 | private bool m_inTransit; | 979 | private bool m_inTransit; |
833 | 980 | ||
834 | /// <summary> | 981 | /// <summary> |
835 | /// This signals whether the presence is in transit between neighbouring regions. | 982 | /// This signals whether the presence is in transit between neighbouring regions. |
836 | /// </summary> | 983 | /// </summary> |
837 | /// <remarks> | 984 | /// <remarks> |
838 | /// It is not set when the presence is teleporting or logging in/out directly to a region. | 985 | /// It is not set when the presence is teleporting or logging in/out directly to a region. |
839 | /// </remarks> | 986 | /// </remarks> |
840 | public bool IsInTransit | 987 | public bool IsInTransit |
841 | { | 988 | { |
842 | get { return m_inTransit; } | 989 | get { return m_inTransit; } |
843 | set { | 990 | set { |
844 | if(value) | 991 | if(value) |
845 | { | 992 | { |
846 | if (Flying) | 993 | if (Flying) |
@@ -851,14 +998,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
851 | m_inTransit = value; | 998 | m_inTransit = value; |
852 | } | 999 | } |
853 | } | 1000 | } |
1001 | // this is is only valid if IsInTransit is true | ||
1002 | // only false on HG tps | ||
1003 | // used work arounf viewers asking source region about destination user | ||
1004 | public bool IsInLocalTransit {get; set; } | ||
854 | 1005 | ||
855 | private float m_speedModifier = 1.0f; | ||
856 | |||
857 | public float SpeedModifier | ||
858 | { | ||
859 | get { return m_speedModifier; } | ||
860 | set { m_speedModifier = value; } | ||
861 | } | ||
862 | 1006 | ||
863 | /// <summary> | 1007 | /// <summary> |
864 | /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running | 1008 | /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running |
@@ -866,7 +1010,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
866 | /// <remarks> | 1010 | /// <remarks> |
867 | /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers. | 1011 | /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers. |
868 | /// </remarks> | 1012 | /// </remarks> |
869 | private float AgentControlStopSlowWhilstMoving = 0.5f; | 1013 | private const float AgentControlStopSlowVel = 0.2f; |
1014 | // velocities | ||
1015 | public const float AgentControlNudgeVel = 1.0f; // setting this diferent from normal as no effect currently | ||
1016 | public const float AgentControlNormalVel = 1.0f; | ||
1017 | |||
1018 | // old normal speed was tuned to match sl normal plus Fast modifiers | ||
1019 | // so we need to rescale it | ||
1020 | private float m_speedModifier = 1.0f; | ||
1021 | |||
1022 | public float SpeedModifier | ||
1023 | { | ||
1024 | get { return m_speedModifier; } | ||
1025 | set { m_speedModifier = value; } | ||
1026 | } | ||
870 | 1027 | ||
871 | private bool m_forceFly; | 1028 | private bool m_forceFly; |
872 | 1029 | ||
@@ -889,35 +1046,32 @@ namespace OpenSim.Region.Framework.Scenes | |||
889 | get { return Util.GetViewerName(m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode)); } | 1046 | get { return Util.GetViewerName(m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode)); } |
890 | } | 1047 | } |
891 | 1048 | ||
892 | /// <summary> | ||
893 | /// Count of how many terse updates we have sent out. It doesn't matter if this overflows. | ||
894 | /// </summary> | ||
895 | private int m_terseUpdateCount; | ||
896 | |||
897 | #endregion | 1049 | #endregion |
898 | 1050 | ||
899 | #region Constructor(s) | 1051 | #region Constructor(s) |
900 | 1052 | ||
901 | public ScenePresence( | 1053 | public ScenePresence( |
902 | IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) | 1054 | IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) |
903 | { | 1055 | { |
1056 | m_scene = world; | ||
904 | AttachmentsSyncLock = new Object(); | 1057 | AttachmentsSyncLock = new Object(); |
905 | AllowMovement = true; | 1058 | AllowMovement = true; |
906 | IsChildAgent = true; | 1059 | IsChildAgent = true; |
907 | IsLoggingIn = false; | 1060 | IsLoggingIn = false; |
908 | m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; | 1061 | m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; |
909 | Animator = new ScenePresenceAnimator(this); | 1062 | Animator = new ScenePresenceAnimator(this); |
1063 | Overrides = new MovementAnimationOverrides(); | ||
910 | PresenceType = type; | 1064 | PresenceType = type; |
911 | // DrawDistance = world.DefaultDrawDistance; | 1065 | DrawDistance = world.DefaultDrawDistance; |
912 | DrawDistance = Constants.RegionSize; | ||
913 | RegionHandle = world.RegionInfo.RegionHandle; | 1066 | RegionHandle = world.RegionInfo.RegionHandle; |
914 | ControllingClient = client; | 1067 | ControllingClient = client; |
915 | Firstname = ControllingClient.FirstName; | 1068 | Firstname = ControllingClient.FirstName; |
916 | Lastname = ControllingClient.LastName; | 1069 | Lastname = ControllingClient.LastName; |
917 | m_name = String.Format("{0} {1}", Firstname, Lastname); | 1070 | m_name = String.Format("{0} {1}", Firstname, Lastname); |
918 | m_scene = world; | ||
919 | m_uuid = client.AgentId; | 1071 | m_uuid = client.AgentId; |
920 | LocalId = m_scene.AllocateLocalId(); | 1072 | LocalId = m_scene.AllocateLocalId(); |
1073 | LegacySitOffsets = m_scene.LegacySitOffsets; | ||
1074 | IsInLocalTransit = true; | ||
921 | 1075 | ||
922 | UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); | 1076 | UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); |
923 | if (account != null) | 1077 | if (account != null) |
@@ -925,32 +1079,52 @@ namespace OpenSim.Region.Framework.Scenes | |||
925 | else | 1079 | else |
926 | m_userFlags = 0; | 1080 | m_userFlags = 0; |
927 | 1081 | ||
1082 | int userlevel = 0; | ||
928 | if (account != null) | 1083 | if (account != null) |
929 | UserLevel = account.UserLevel; | 1084 | userlevel = account.UserLevel; |
1085 | |||
1086 | GodController = new GodController(world, this, userlevel); | ||
930 | 1087 | ||
931 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); | 1088 | // IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); |
932 | if (gm != null) | 1089 | // if (gm != null) |
933 | Grouptitle = gm.GetGroupTitle(m_uuid); | 1090 | // Grouptitle = gm.GetGroupTitle(m_uuid); |
934 | 1091 | ||
935 | m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>(); | 1092 | m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>(); |
936 | |||
937 | AbsolutePosition = posLastSignificantMove = CameraPosition = | ||
938 | m_lastCameraPosition = ControllingClient.StartPos; | ||
939 | 1093 | ||
940 | m_reprioritization_timer = new Timer(world.ReprioritizationInterval); | 1094 | AbsolutePosition = posLastMove = posLastSignificantMove = CameraPosition = |
941 | m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize); | 1095 | m_reprioritizationLastPosition = ControllingClient.StartPos; |
942 | m_reprioritization_timer.AutoReset = false; | 1096 | |
1097 | m_reprioritizationLastDrawDistance = DrawDistance; | ||
1098 | |||
1099 | // disable updates workjobs for now | ||
1100 | m_childUpdatesBusy = true; | ||
1101 | m_reprioritizationBusy = true; | ||
943 | 1102 | ||
944 | AdjustKnownSeeds(); | 1103 | AdjustKnownSeeds(); |
945 | 1104 | ||
946 | RegisterToEvents(); | 1105 | RegisterToClientEvents(); |
947 | SetDirectionVectors(); | 1106 | SetDirectionVectors(); |
948 | 1107 | ||
949 | Appearance = appearance; | 1108 | Appearance = appearance; |
950 | 1109 | ||
951 | m_stateMachine = new ScenePresenceStateMachine(this); | 1110 | m_stateMachine = new ScenePresenceStateMachine(this); |
1111 | |||
1112 | HealRate = 0.5f; | ||
1113 | |||
1114 | IConfig sconfig = m_scene.Config.Configs["EntityTransfer"]; | ||
1115 | if (sconfig != null) | ||
1116 | { | ||
1117 | string lpb = sconfig.GetString("LandingPointBehavior", "LandingPointBehavior_OS"); | ||
1118 | if (lpb == "LandingPointBehavior_SL") | ||
1119 | m_LandingPointBehavior = LandingPointBehavior.SL; | ||
1120 | } | ||
1121 | |||
1122 | ControllingClient.RefreshGroupMembership(); | ||
1123 | |||
952 | } | 1124 | } |
953 | 1125 | ||
1126 | private float lastHealthSent = 0; | ||
1127 | |||
954 | private void RegionHeartbeatEnd(Scene scene) | 1128 | private void RegionHeartbeatEnd(Scene scene) |
955 | { | 1129 | { |
956 | if (IsChildAgent) | 1130 | if (IsChildAgent) |
@@ -973,12 +1147,29 @@ namespace OpenSim.Region.Framework.Scenes | |||
973 | } | 1147 | } |
974 | else | 1148 | else |
975 | { | 1149 | { |
976 | m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; | 1150 | // m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; |
1151 | } | ||
1152 | } | ||
1153 | |||
1154 | if(m_healRatePerFrame != 0f && Health != 100.0f) | ||
1155 | { | ||
1156 | float last = Health; | ||
1157 | Health += m_healRatePerFrame; | ||
1158 | if(Health > 100.0f) | ||
1159 | { | ||
1160 | Health = 100.0f; | ||
1161 | lastHealthSent = Health; | ||
1162 | ControllingClient.SendHealth(Health); | ||
1163 | } | ||
1164 | else if(Math.Abs(Health - lastHealthSent) > 1.0) | ||
1165 | { | ||
1166 | lastHealthSent = Health; | ||
1167 | ControllingClient.SendHealth(Health); | ||
977 | } | 1168 | } |
978 | } | 1169 | } |
979 | } | 1170 | } |
980 | 1171 | ||
981 | public void RegisterToEvents() | 1172 | public void RegisterToClientEvents() |
982 | { | 1173 | { |
983 | ControllingClient.OnCompleteMovementToRegion += CompleteMovement; | 1174 | ControllingClient.OnCompleteMovementToRegion += CompleteMovement; |
984 | ControllingClient.OnAgentUpdate += HandleAgentUpdate; | 1175 | ControllingClient.OnAgentUpdate += HandleAgentUpdate; |
@@ -988,28 +1179,48 @@ namespace OpenSim.Region.Framework.Scenes | |||
988 | ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; | 1179 | ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; |
989 | ControllingClient.OnStartAnim += HandleStartAnim; | 1180 | ControllingClient.OnStartAnim += HandleStartAnim; |
990 | ControllingClient.OnStopAnim += HandleStopAnim; | 1181 | ControllingClient.OnStopAnim += HandleStopAnim; |
1182 | ControllingClient.OnChangeAnim += avnHandleChangeAnim; | ||
991 | ControllingClient.OnForceReleaseControls += HandleForceReleaseControls; | 1183 | ControllingClient.OnForceReleaseControls += HandleForceReleaseControls; |
992 | ControllingClient.OnAutoPilotGo += MoveToTarget; | 1184 | ControllingClient.OnAutoPilotGo += MoveToTargetHandle; |
1185 | ControllingClient.OnUpdateThrottles += RaiseUpdateThrottles; | ||
1186 | // ControllingClient.OnAgentFOV += HandleAgentFOV; | ||
993 | 1187 | ||
994 | // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); | 1188 | // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); |
995 | // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); | 1189 | // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); |
996 | } | 1190 | } |
997 | 1191 | ||
998 | private void SetDirectionVectors() | 1192 | public void RemoveClientEvents() |
999 | { | 1193 | { |
1000 | Dir_Vectors[0] = Vector3.UnitX; //FORWARD | 1194 | ControllingClient.OnCompleteMovementToRegion -= CompleteMovement; |
1001 | Dir_Vectors[1] = -Vector3.UnitX; //BACK | 1195 | ControllingClient.OnAgentUpdate -= HandleAgentUpdate; |
1002 | Dir_Vectors[2] = Vector3.UnitY; //LEFT | 1196 | ControllingClient.OnAgentCameraUpdate -= HandleAgentCamerasUpdate; |
1003 | Dir_Vectors[3] = -Vector3.UnitY; //RIGHT | 1197 | ControllingClient.OnAgentRequestSit -= HandleAgentRequestSit; |
1004 | Dir_Vectors[4] = Vector3.UnitZ; //UP | 1198 | ControllingClient.OnAgentSit -= HandleAgentSit; |
1005 | Dir_Vectors[5] = -Vector3.UnitZ; //DOWN | 1199 | ControllingClient.OnSetAlwaysRun -= HandleSetAlwaysRun; |
1006 | Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE | 1200 | ControllingClient.OnStartAnim -= HandleStartAnim; |
1007 | Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE | 1201 | ControllingClient.OnStopAnim -= HandleStopAnim; |
1008 | Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE | 1202 | ControllingClient.OnChangeAnim -= avnHandleChangeAnim; |
1009 | Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE | 1203 | ControllingClient.OnForceReleaseControls -= HandleForceReleaseControls; |
1010 | Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge | 1204 | ControllingClient.OnAutoPilotGo -= MoveToTargetHandle; |
1205 | ControllingClient.OnUpdateThrottles -= RaiseUpdateThrottles; | ||
1206 | // ControllingClient.OnAgentFOV += HandleAgentFOV; | ||
1011 | } | 1207 | } |
1012 | 1208 | ||
1209 | private void SetDirectionVectors() | ||
1210 | { | ||
1211 | Dir_Vectors[0] = new Vector3(AgentControlNormalVel,0,0); //FORWARD | ||
1212 | Dir_Vectors[1] = new Vector3(-AgentControlNormalVel,0,0);; //BACK | ||
1213 | Dir_Vectors[2] = new Vector3(0,AgentControlNormalVel,0); //LEFT | ||
1214 | Dir_Vectors[3] = new Vector3(0,-AgentControlNormalVel,0); //RIGHT | ||
1215 | Dir_Vectors[4] = new Vector3(0,0,AgentControlNormalVel); //UP | ||
1216 | Dir_Vectors[5] = new Vector3(0,0,-AgentControlNormalVel); //DOWN | ||
1217 | Dir_Vectors[6] = new Vector3(AgentControlNudgeVel, 0f, 0f); //FORWARD_NUDGE | ||
1218 | Dir_Vectors[7] = new Vector3(-AgentControlNudgeVel, 0f, 0f); //BACK_NUDGE | ||
1219 | Dir_Vectors[8] = new Vector3(0f, AgentControlNudgeVel, 0f); //LEFT_NUDGE | ||
1220 | Dir_Vectors[9] = new Vector3(0f, -AgentControlNudgeVel, 0f); //RIGHT_NUDGE | ||
1221 | Dir_Vectors[10] = new Vector3(0f, 0f, AgentControlNudgeVel); //UP_Nudge | ||
1222 | Dir_Vectors[11] = new Vector3(0f, 0f, -AgentControlNudgeVel); //DOWN_Nudge | ||
1223 | } | ||
1013 | #endregion | 1224 | #endregion |
1014 | 1225 | ||
1015 | #region Status Methods | 1226 | #region Status Methods |
@@ -1026,18 +1237,29 @@ namespace OpenSim.Region.Framework.Scenes | |||
1026 | /// This method is on the critical path for transferring an avatar from one region to another. Delay here | 1237 | /// This method is on the critical path for transferring an avatar from one region to another. Delay here |
1027 | /// delays that crossing. | 1238 | /// delays that crossing. |
1028 | /// </remarks> | 1239 | /// </remarks> |
1029 | private bool MakeRootAgent(Vector3 pos, bool isFlying) | 1240 | |
1241 | // constants for physics position search | ||
1242 | const float PhysSearchHeight = 600f; | ||
1243 | const float PhysMinSkipGap = 50f; | ||
1244 | const int PhysNumberCollisions = 30; | ||
1245 | |||
1246 | // only in use as part of completemovement | ||
1247 | // other uses need fix | ||
1248 | private bool MakeRootAgent(Vector3 pos, bool isFlying, ref Vector3 lookat) | ||
1030 | { | 1249 | { |
1250 | //int ts = Util.EnvironmentTickCount(); | ||
1251 | |||
1031 | lock (m_completeMovementLock) | 1252 | lock (m_completeMovementLock) |
1032 | { | 1253 | { |
1033 | if (!IsChildAgent) | 1254 | if (!IsChildAgent) |
1034 | return false; | 1255 | return false; |
1035 | 1256 | ||
1257 | //m_log.DebugFormat("[MakeRootAgent] enter lock: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1036 | //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); | 1258 | //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); |
1037 | 1259 | ||
1038 | // m_log.InfoFormat( | 1260 | // m_log.InfoFormat( |
1039 | // "[SCENE]: Upgrading child to root agent for {0} in {1}", | 1261 | // "[SCENE]: Upgrading child to root agent for {0} in {1}", |
1040 | // Name, m_scene.RegionInfo.RegionName); | 1262 | // Name, m_scene.RegionInfo.RegionName); |
1041 | 1263 | ||
1042 | if (ParentUUID != UUID.Zero) | 1264 | if (ParentUUID != UUID.Zero) |
1043 | { | 1265 | { |
@@ -1046,20 +1268,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
1046 | if (part == null) | 1268 | if (part == null) |
1047 | { | 1269 | { |
1048 | m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); | 1270 | m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); |
1271 | ParentID = 0; | ||
1272 | ParentPart = null; | ||
1273 | PrevSitOffset = Vector3.Zero; | ||
1274 | HandleForceReleaseControls(ControllingClient, UUID); // needs testing | ||
1275 | IsLoggingIn = false; | ||
1049 | } | 1276 | } |
1050 | else | 1277 | else |
1051 | { | 1278 | { |
1052 | part.AddSittingAvatar(this); | 1279 | part.AddSittingAvatar(this); |
1053 | // ParentPosition = part.GetWorldPosition(); | 1280 | // if not actually on the target invalidate it |
1281 | if(gotCrossUpdate && (crossingFlags & 0x04) == 0) | ||
1282 | part.SitTargetAvatar = UUID.Zero; | ||
1283 | |||
1054 | ParentID = part.LocalId; | 1284 | ParentID = part.LocalId; |
1055 | ParentPart = part; | 1285 | ParentPart = part; |
1056 | m_pos = PrevSitOffset; | 1286 | m_pos = PrevSitOffset; |
1057 | // pos = ParentPosition; | ||
1058 | pos = part.GetWorldPosition(); | 1287 | pos = part.GetWorldPosition(); |
1288 | PhysicsActor partPhysActor = part.PhysActor; | ||
1289 | if(partPhysActor != null) | ||
1290 | { | ||
1291 | partPhysActor.OnPhysicsRequestingCameraData -= | ||
1292 | physActor_OnPhysicsRequestingCameraData; | ||
1293 | partPhysActor.OnPhysicsRequestingCameraData += | ||
1294 | physActor_OnPhysicsRequestingCameraData; | ||
1295 | } | ||
1059 | } | 1296 | } |
1060 | ParentUUID = UUID.Zero; | 1297 | ParentUUID = UUID.Zero; |
1061 | |||
1062 | // Animator.TrySetMovementAnimation("SIT"); | ||
1063 | } | 1298 | } |
1064 | else | 1299 | else |
1065 | { | 1300 | { |
@@ -1069,135 +1304,144 @@ namespace OpenSim.Region.Framework.Scenes | |||
1069 | IsChildAgent = false; | 1304 | IsChildAgent = false; |
1070 | } | 1305 | } |
1071 | 1306 | ||
1307 | //m_log.DebugFormat("[MakeRootAgent] out lock: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1308 | |||
1072 | // Must reset this here so that a teleport to a region next to an existing region does not keep the flag | 1309 | // Must reset this here so that a teleport to a region next to an existing region does not keep the flag |
1073 | // set and prevent the close of the connection on a subsequent re-teleport. | 1310 | // set and prevent the close of the connection on a subsequent re-teleport. |
1074 | // Should not be needed if we are not trying to tell this region to close | 1311 | // Should not be needed if we are not trying to tell this region to close |
1075 | // DoNotCloseAfterTeleport = false; | 1312 | // DoNotCloseAfterTeleport = false; |
1076 | |||
1077 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); | ||
1078 | if (gm != null) | ||
1079 | Grouptitle = gm.GetGroupTitle(m_uuid); | ||
1080 | |||
1081 | AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode); | ||
1082 | uint teleportFlags = (aCircuit == null) ? 0 : aCircuit.teleportFlags; | ||
1083 | if ((teleportFlags & (uint)TeleportFlags.ViaHGLogin) != 0) | ||
1084 | { | ||
1085 | // The avatar is arriving from another grid. This means that we may have changed the | ||
1086 | // avatar's name to or from the special Hypergrid format ("First.Last @grid.example.com"). | ||
1087 | // Unfortunately, due to a viewer bug, viewers don't always show the new name. | ||
1088 | // But we have a trick that can force them to update the name anyway. | ||
1089 | ForceViewersUpdateName(); | ||
1090 | } | ||
1091 | 1313 | ||
1092 | RegionHandle = m_scene.RegionInfo.RegionHandle; | 1314 | RegionHandle = m_scene.RegionInfo.RegionHandle; |
1093 | 1315 | ||
1094 | m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); | 1316 | m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); |
1317 | //m_log.DebugFormat("[MakeRootAgent] TriggerSetRootAgentScene: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1095 | 1318 | ||
1096 | UUID groupUUID = ControllingClient.ActiveGroupId; | 1319 | if (ParentID == 0) |
1097 | string groupName = string.Empty; | ||
1098 | ulong groupPowers = 0; | ||
1099 | |||
1100 | // ---------------------------------- | ||
1101 | // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status | ||
1102 | try | ||
1103 | { | 1320 | { |
1104 | if (groupUUID != UUID.Zero && gm != null) | 1321 | bool positionChanged = false; |
1105 | { | 1322 | bool success = true; |
1106 | GroupRecord record = gm.GetGroupRecord(groupUUID); | 1323 | if (m_LandingPointBehavior == LandingPointBehavior.OS) |
1107 | if (record != null) | 1324 | success = CheckAndAdjustLandingPoint_OS(ref pos, ref lookat, ref positionChanged); |
1108 | groupName = record.GroupName; | 1325 | else |
1326 | success = CheckAndAdjustLandingPoint_SL(ref pos, ref lookat, ref positionChanged); | ||
1109 | 1327 | ||
1110 | GroupMembershipData groupMembershipData = gm.GetMembershipData(groupUUID, m_uuid); | 1328 | if (!success) |
1329 | m_log.DebugFormat("[SCENE PRESENCE MakeRootAgent]: houston we have a problem.. {0} ({1} got banned)", Name, UUID); | ||
1111 | 1330 | ||
1112 | if (groupMembershipData != null) | 1331 | if (pos.X < 0f || pos.Y < 0f |
1113 | groupPowers = groupMembershipData.GroupPowers; | 1332 | || pos.X >= m_scene.RegionInfo.RegionSizeX |
1333 | || pos.Y >= m_scene.RegionInfo.RegionSizeY) | ||
1334 | { | ||
1335 | m_log.WarnFormat( | ||
1336 | "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", | ||
1337 | pos, Name, UUID); | ||
1338 | |||
1339 | if (pos.X < 0f) | ||
1340 | pos.X = 0.5f; | ||
1341 | else if(pos.X >= m_scene.RegionInfo.RegionSizeX) | ||
1342 | pos.X = m_scene.RegionInfo.RegionSizeX - 0.5f; | ||
1343 | if (pos.Y < 0f) | ||
1344 | pos.Y = 0.5f; | ||
1345 | else if(pos.Y >= m_scene.RegionInfo.RegionSizeY) | ||
1346 | pos.Y = m_scene.RegionInfo.RegionSizeY - 0.5f; | ||
1114 | } | 1347 | } |
1115 | 1348 | ||
1116 | ControllingClient.SendAgentDataUpdate( | 1349 | float groundHeight = m_scene.GetGroundHeight(pos.X, pos.Y) + .01f; |
1117 | m_uuid, groupUUID, Firstname, Lastname, groupPowers, groupName, Grouptitle); | 1350 | float physTestHeight; |
1118 | } | ||
1119 | catch (Exception e) | ||
1120 | { | ||
1121 | m_log.Error("[AGENTUPDATE]: Error ", e); | ||
1122 | } | ||
1123 | // ------------------------------------ | ||
1124 | 1351 | ||
1125 | if (ParentID == 0) | 1352 | if(PhysSearchHeight < groundHeight + 100f) |
1126 | { | 1353 | physTestHeight = groundHeight + 100f; |
1127 | // Moved this from SendInitialData to ensure that Appearance is initialized | 1354 | else |
1128 | // before the inventory is processed in MakeRootAgent. This fixes a race condition | 1355 | physTestHeight = PhysSearchHeight; |
1129 | // related to the handling of attachments | ||
1130 | //m_scene.GetAvatarAppearance(ControllingClient, out Appearance); | ||
1131 | 1356 | ||
1132 | /* RA 20140111: Commented out these TestBorderCross's. | 1357 | float localAVHalfHeight = 0.8f; |
1133 | * Not sure why this code is here. It is not checking all the borders | 1358 | if (Appearance != null && Appearance.AvatarHeight > 0) |
1134 | * and 'in region' sanity checking is done in CheckAndAdjustLandingPoint and below. | 1359 | localAVHalfHeight = 0.5f * Appearance.AvatarHeight; |
1135 | if (m_scene.TestBorderCross(pos, Cardinals.E)) | ||
1136 | { | ||
1137 | Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); | ||
1138 | pos.X = crossedBorder.BorderLine.Z - 1; | ||
1139 | } | ||
1140 | 1360 | ||
1141 | if (m_scene.TestBorderCross(pos, Cardinals.N)) | 1361 | groundHeight += localAVHalfHeight; |
1142 | { | 1362 | if (groundHeight > pos.Z) |
1143 | Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); | 1363 | pos.Z = groundHeight; |
1144 | pos.Y = crossedBorder.BorderLine.Z - 1; | ||
1145 | } | ||
1146 | */ | ||
1147 | 1364 | ||
1148 | CheckAndAdjustLandingPoint(ref pos); | 1365 | bool checkPhysics = !positionChanged && |
1366 | m_scene.SupportsRayCastFiltered() && | ||
1367 | pos.Z < physTestHeight && | ||
1368 | ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == | ||
1369 | (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) | ||
1370 | || (m_teleportFlags & TeleportFlags.ViaLocation) != 0 | ||
1371 | || (m_teleportFlags & TeleportFlags.ViaHGLogin) != 0); | ||
1149 | 1372 | ||
1150 | if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) | 1373 | if(checkPhysics) |
1151 | { | 1374 | { |
1152 | m_log.WarnFormat( | 1375 | // land check was done above |
1153 | "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", | 1376 | RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull; |
1154 | pos, Name, UUID); | 1377 | rayfilter |= RayFilterFlags.PrimsNonPhantomAgents; |
1155 | 1378 | ||
1156 | if (pos.X < 0f) pos.X = 0f; | 1379 | int physcount = PhysNumberCollisions; |
1157 | if (pos.Y < 0f) pos.Y = 0f; | ||
1158 | if (pos.Z < 0f) pos.Z = 0f; | ||
1159 | } | ||
1160 | 1380 | ||
1161 | float localAVHeight = 1.56f; | 1381 | float dist = physTestHeight - groundHeight + localAVHalfHeight; |
1162 | if (Appearance.AvatarHeight > 0) | ||
1163 | localAVHeight = Appearance.AvatarHeight; | ||
1164 | 1382 | ||
1165 | float posZLimit = 0; | 1383 | Vector3 direction = new Vector3(0f, 0f, -1f); |
1384 | Vector3 RayStart = pos; | ||
1385 | RayStart.Z = physTestHeight; | ||
1166 | 1386 | ||
1167 | if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY) | 1387 | List<ContactResult> physresults = |
1168 | posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; | 1388 | (List<ContactResult>)m_scene.RayCastFiltered(RayStart, direction, dist, physcount, rayfilter); |
1169 | 1389 | if (physresults != null && physresults.Count > 0) | |
1170 | float newPosZ = posZLimit + localAVHeight / 2; | 1390 | { |
1171 | if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) | 1391 | float dest = physresults[0].Pos.Z; |
1172 | { | 1392 | |
1173 | pos.Z = newPosZ; | 1393 | if(physresults.Count > 1) |
1394 | { | ||
1395 | physresults.Sort(delegate(ContactResult a, ContactResult b) | ||
1396 | { | ||
1397 | return a.Depth.CompareTo(b.Depth); | ||
1398 | }); | ||
1399 | |||
1400 | int sel = 0; | ||
1401 | int count = physresults.Count; | ||
1402 | float curd = physresults[0].Depth; | ||
1403 | float nextd = curd + PhysMinSkipGap; | ||
1404 | float maxDepth = dist - pos.Z; | ||
1405 | for(int i = 1; i < count; i++) | ||
1406 | { | ||
1407 | curd = physresults[i].Depth; | ||
1408 | if(curd >= nextd) | ||
1409 | { | ||
1410 | sel = i; | ||
1411 | if(curd >= maxDepth) | ||
1412 | break; | ||
1413 | } | ||
1414 | nextd = curd + PhysMinSkipGap; | ||
1415 | } | ||
1416 | dest = physresults[sel].Pos.Z; | ||
1417 | } | ||
1418 | |||
1419 | dest += localAVHalfHeight; | ||
1420 | if(dest > pos.Z) | ||
1421 | pos.Z = dest; | ||
1422 | } | ||
1174 | } | 1423 | } |
1424 | |||
1175 | AbsolutePosition = pos; | 1425 | AbsolutePosition = pos; |
1176 | 1426 | ||
1177 | // m_log.DebugFormat( | 1427 | // m_log.DebugFormat( |
1178 | // "Set pos {0}, vel {1} in {1} to {2} from input position of {3} on MakeRootAgent", | 1428 | // "Set pos {0}, vel {1} in {1} to {2} from input position of {3} on MakeRootAgent", |
1179 | // Name, Scene.Name, AbsolutePosition, pos); | 1429 | // Name, Scene.Name, AbsolutePosition, pos); |
1180 | // | 1430 | // |
1181 | if (m_teleportFlags == TeleportFlags.Default) | 1431 | if (m_teleportFlags == TeleportFlags.Default) |
1182 | { | 1432 | { |
1433 | Vector3 vel = Velocity; | ||
1183 | AddToPhysicalScene(isFlying); | 1434 | AddToPhysicalScene(isFlying); |
1184 | // | 1435 | if (PhysicsActor != null) |
1185 | // Console.WriteLine( | 1436 | PhysicsActor.SetMomentum(vel); |
1186 | // "Set velocity of {0} in {1} to {2} from input velocity of {3} on MakeRootAgent", | ||
1187 | // Name, Scene.Name, PhysicsActor.Velocity, vel); | ||
1188 | // } | ||
1189 | } | 1437 | } |
1190 | else | 1438 | else |
1191 | { | 1439 | { |
1192 | AddToPhysicalScene(isFlying); | 1440 | AddToPhysicalScene(isFlying); |
1193 | } | ||
1194 | 1441 | ||
1195 | // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a | 1442 | // reset camera to avatar pos |
1196 | // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it | 1443 | CameraPosition = pos; |
1197 | // since it requires a physics actor to be present. If it is left any later, then physics appears to reset | 1444 | } |
1198 | // the value to a negative position which does not trigger the border cross. | ||
1199 | // This may not be the best location for this. | ||
1200 | CheckForBorderCrossing(); | ||
1201 | 1445 | ||
1202 | if (ForceFly) | 1446 | if (ForceFly) |
1203 | { | 1447 | { |
@@ -1209,53 +1453,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1209 | } | 1453 | } |
1210 | } | 1454 | } |
1211 | 1455 | ||
1212 | // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying | 1456 | //m_log.DebugFormat("[MakeRootAgent] position and physical: {0}ms", Util.EnvironmentTickCountSubtract(ts)); |
1213 | // avatar to return to the standing position in mid-air. On login it looks like this is being sent | ||
1214 | // elsewhere anyway | ||
1215 | // Animator.SendAnimPack(); | ||
1216 | |||
1217 | m_scene.SwapRootAgentCount(false); | 1457 | m_scene.SwapRootAgentCount(false); |
1218 | 1458 | ||
1219 | if (Scene.AttachmentsModule != null) | ||
1220 | { | ||
1221 | // The initial login scene presence is already root when it gets here | ||
1222 | // and it has already rezzed the attachments and started their scripts. | ||
1223 | // We do the following only for non-login agents, because their scripts | ||
1224 | // haven't started yet. | ||
1225 | if (PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags)) | ||
1226 | { | ||
1227 | WorkManager.RunJob( | ||
1228 | "RezAttachments", | ||
1229 | o => Scene.AttachmentsModule.RezAttachments(this), | ||
1230 | null, | ||
1231 | string.Format("Rez attachments for {0} in {1}", Name, Scene.Name)); | ||
1232 | } | ||
1233 | else | ||
1234 | { | ||
1235 | WorkManager.RunJob( | ||
1236 | "StartAttachmentScripts", | ||
1237 | o => RestartAttachmentScripts(), | ||
1238 | null, | ||
1239 | string.Format("Start attachment scripts for {0} in {1}", Name, Scene.Name), | ||
1240 | true); | ||
1241 | } | ||
1242 | } | ||
1243 | |||
1244 | SendAvatarDataToAllClients(); | ||
1245 | |||
1246 | // send the animations of the other presences to me | ||
1247 | m_scene.ForEachRootScenePresence(delegate(ScenePresence presence) | ||
1248 | { | ||
1249 | if (presence != this) | ||
1250 | presence.Animator.SendAnimPackToClient(ControllingClient); | ||
1251 | }); | ||
1252 | |||
1253 | // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will | 1459 | // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will |
1254 | // stall on the border crossing since the existing child agent will still have the last movement | 1460 | // stall on the border crossing since the existing child agent will still have the last movement |
1255 | // recorded, which stops the input from being processed. | 1461 | // recorded, which stops the input from being processed. |
1256 | MovementFlag = ForceUpdateMovementFlagValue; | 1462 | MovementFlag = 0; |
1257 | 1463 | ||
1258 | m_scene.EventManager.TriggerOnMakeRootAgent(this); | 1464 | m_scene.EventManager.TriggerOnMakeRootAgent(this); |
1465 | //m_log.DebugFormat("[MakeRootAgent] TriggerOnMakeRootAgent and done: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1259 | 1466 | ||
1260 | return true; | 1467 | return true; |
1261 | } | 1468 | } |
@@ -1304,12 +1511,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1304 | /// Group Title. So the following trick makes viewers update the avatar's name by briefly changing | 1511 | /// Group Title. So the following trick makes viewers update the avatar's name by briefly changing |
1305 | /// the group title (to "(Loading)"), and then restoring it. | 1512 | /// the group title (to "(Loading)"), and then restoring it. |
1306 | /// </remarks> | 1513 | /// </remarks> |
1514 | /* | ||
1307 | public void ForceViewersUpdateName() | 1515 | public void ForceViewersUpdateName() |
1308 | { | 1516 | { |
1309 | m_log.DebugFormat("[SCENE PRESENCE]: Forcing viewers to update the avatar name for " + Name); | 1517 | m_log.DebugFormat("[SCENE PRESENCE]: Forcing viewers to update the avatar name for " + Name); |
1310 | 1518 | ||
1311 | UseFakeGroupTitle = true; | 1519 | UseFakeGroupTitle = true; |
1312 | SendAvatarDataToAllClients(false); | 1520 | |
1313 | 1521 | ||
1314 | Util.FireAndForget(o => | 1522 | Util.FireAndForget(o => |
1315 | { | 1523 | { |
@@ -1323,7 +1531,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1323 | SendAvatarDataToAllClients(false); | 1531 | SendAvatarDataToAllClients(false); |
1324 | }, null, "Scenepresence.ForceViewersUpdateName"); | 1532 | }, null, "Scenepresence.ForceViewersUpdateName"); |
1325 | } | 1533 | } |
1326 | 1534 | */ | |
1327 | public int GetStateSource() | 1535 | public int GetStateSource() |
1328 | { | 1536 | { |
1329 | AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(UUID); | 1537 | AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(UUID); |
@@ -1347,11 +1555,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1347 | /// It doesn't get called for a teleport. Reason being, an agent that | 1555 | /// It doesn't get called for a teleport. Reason being, an agent that |
1348 | /// teleports out may not end up anywhere near this region | 1556 | /// teleports out may not end up anywhere near this region |
1349 | /// </remarks> | 1557 | /// </remarks> |
1350 | public void MakeChildAgent() | 1558 | public void MakeChildAgent(ulong newRegionHandle) |
1351 | { | 1559 | { |
1560 | haveGroupInformation = false; | ||
1561 | gotCrossUpdate = false; | ||
1562 | crossingFlags = 0; | ||
1352 | m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; | 1563 | m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; |
1353 | 1564 | ||
1354 | m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); | 1565 | RegionHandle = newRegionHandle; |
1566 | |||
1567 | m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1} from root region {2}", | ||
1568 | Name, Scene.RegionInfo.RegionName, newRegionHandle); | ||
1355 | 1569 | ||
1356 | // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating | 1570 | // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating |
1357 | // from the source simulator has completed on a V2 teleport. | 1571 | // from the source simulator has completed on a V2 teleport. |
@@ -1371,7 +1585,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1371 | else | 1585 | else |
1372 | Animator.ResetAnimations(); | 1586 | Animator.ResetAnimations(); |
1373 | 1587 | ||
1374 | 1588 | ||
1375 | // m_log.DebugFormat( | 1589 | // m_log.DebugFormat( |
1376 | // "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", | 1590 | // "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", |
1377 | // Name, UUID, m_scene.RegionInfo.RegionName); | 1591 | // Name, UUID, m_scene.RegionInfo.RegionName); |
@@ -1379,14 +1593,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
1379 | // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing, | 1593 | // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing, |
1380 | // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated. | 1594 | // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated. |
1381 | //Velocity = new Vector3(0, 0, 0); | 1595 | //Velocity = new Vector3(0, 0, 0); |
1382 | 1596 | ||
1383 | IsChildAgent = true; | 1597 | IsChildAgent = true; |
1384 | m_scene.SwapRootAgentCount(true); | 1598 | m_scene.SwapRootAgentCount(true); |
1385 | RemoveFromPhysicalScene(); | 1599 | RemoveFromPhysicalScene(); |
1386 | ParentID = 0; // Child agents can't be sitting | 1600 | ParentID = 0; // Child agents can't be sitting |
1387 | 1601 | ||
1602 | // we dont have land information for child | ||
1603 | m_previusParcelHide = false; | ||
1604 | m_previusParcelUUID = UUID.Zero; | ||
1605 | m_currentParcelHide = false; | ||
1606 | m_currentParcelUUID = UUID.Zero; | ||
1388 | // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into | 1607 | // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into |
1389 | 1608 | ||
1609 | CollisionPlane = Vector4.UnitW; | ||
1610 | |||
1390 | m_scene.EventManager.TriggerOnMakeChildAgent(this); | 1611 | m_scene.EventManager.TriggerOnMakeChildAgent(this); |
1391 | } | 1612 | } |
1392 | 1613 | ||
@@ -1398,9 +1619,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
1398 | if (PhysicsActor != null) | 1619 | if (PhysicsActor != null) |
1399 | { | 1620 | { |
1400 | // PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; | 1621 | // PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; |
1401 | PhysicsActor.UnSubscribeEvents(); | 1622 | |
1402 | PhysicsActor.OnOutOfBounds -= OutOfBoundsCall; | 1623 | PhysicsActor.OnOutOfBounds -= OutOfBoundsCall; |
1403 | PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; | 1624 | PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; |
1625 | PhysicsActor.UnSubscribeEvents(); | ||
1404 | m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); | 1626 | m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); |
1405 | PhysicsActor = null; | 1627 | PhysicsActor = null; |
1406 | } | 1628 | } |
@@ -1423,12 +1645,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1423 | 1645 | ||
1424 | public void TeleportWithMomentum(Vector3 pos, Vector3? v) | 1646 | public void TeleportWithMomentum(Vector3 pos, Vector3? v) |
1425 | { | 1647 | { |
1648 | if(!CheckLocalTPLandingPoint(ref pos)) | ||
1649 | return; | ||
1650 | |||
1426 | if (ParentID != (uint)0) | 1651 | if (ParentID != (uint)0) |
1427 | StandUp(); | 1652 | StandUp(); |
1653 | |||
1428 | bool isFlying = Flying; | 1654 | bool isFlying = Flying; |
1429 | Vector3 vel = Velocity; | 1655 | Vector3 vel = Velocity; |
1430 | RemoveFromPhysicalScene(); | 1656 | RemoveFromPhysicalScene(); |
1431 | CheckLandingPoint(ref pos); | 1657 | |
1432 | AbsolutePosition = pos; | 1658 | AbsolutePosition = pos; |
1433 | AddToPhysicalScene(isFlying); | 1659 | AddToPhysicalScene(isFlying); |
1434 | if (PhysicsActor != null) | 1660 | if (PhysicsActor != null) |
@@ -1438,11 +1664,29 @@ namespace OpenSim.Region.Framework.Scenes | |||
1438 | else | 1664 | else |
1439 | PhysicsActor.SetMomentum(vel); | 1665 | PhysicsActor.SetMomentum(vel); |
1440 | } | 1666 | } |
1667 | |||
1668 | SendTerseUpdateToAllClients(); | ||
1669 | } | ||
1670 | |||
1671 | public void TeleportOnEject(Vector3 pos) | ||
1672 | { | ||
1673 | if (ParentID != (uint)0) | ||
1674 | StandUp(); | ||
1675 | |||
1676 | bool isFlying = Flying; | ||
1677 | RemoveFromPhysicalScene(); | ||
1678 | |||
1679 | AbsolutePosition = pos; | ||
1680 | |||
1681 | AddToPhysicalScene(isFlying); | ||
1682 | SendTerseUpdateToAllClients(); | ||
1441 | } | 1683 | } |
1442 | 1684 | ||
1443 | public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY) | 1685 | public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY) |
1444 | { | 1686 | { |
1445 | CheckLandingPoint(ref newpos); | 1687 | if(!CheckLocalTPLandingPoint(ref newpos)) |
1688 | return; | ||
1689 | |||
1446 | AbsolutePosition = newpos; | 1690 | AbsolutePosition = newpos; |
1447 | 1691 | ||
1448 | if (newvel.HasValue) | 1692 | if (newvel.HasValue) |
@@ -1469,11 +1713,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
1469 | } | 1713 | } |
1470 | } | 1714 | } |
1471 | } | 1715 | } |
1716 | SendTerseUpdateToAllClients(); | ||
1472 | } | 1717 | } |
1473 | 1718 | ||
1474 | public void StopFlying() | 1719 | public void StopFlying() |
1475 | { | 1720 | { |
1476 | Vector3 pos = AbsolutePosition; | 1721 | if (IsInTransit) |
1722 | return; | ||
1723 | |||
1724 | Vector3 pos = AbsolutePosition; | ||
1477 | if (Appearance.AvatarHeight != 127.0f) | 1725 | if (Appearance.AvatarHeight != 127.0f) |
1478 | pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f)); | 1726 | pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f)); |
1479 | else | 1727 | else |
@@ -1492,7 +1740,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1492 | else | 1740 | else |
1493 | CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f)); | 1741 | CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f)); |
1494 | 1742 | ||
1495 | ControllingClient.SendAgentTerseUpdate(this); | 1743 | SendAgentTerseUpdate(this); |
1496 | } | 1744 | } |
1497 | 1745 | ||
1498 | /// <summary> | 1746 | /// <summary> |
@@ -1501,7 +1749,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1501 | /// <param name="amount">Postive or negative roll amount in radians</param> | 1749 | /// <param name="amount">Postive or negative roll amount in radians</param> |
1502 | private void ApplyFlyingRoll(float amount, bool PressingUp, bool PressingDown) | 1750 | private void ApplyFlyingRoll(float amount, bool PressingUp, bool PressingDown) |
1503 | { | 1751 | { |
1504 | 1752 | ||
1505 | float rollAmount = Util.Clamp(m_AngularVelocity.Z + amount, -FLY_ROLL_MAX_RADIANS, FLY_ROLL_MAX_RADIANS); | 1753 | float rollAmount = Util.Clamp(m_AngularVelocity.Z + amount, -FLY_ROLL_MAX_RADIANS, FLY_ROLL_MAX_RADIANS); |
1506 | m_AngularVelocity.Z = rollAmount; | 1754 | m_AngularVelocity.Z = rollAmount; |
1507 | 1755 | ||
@@ -1553,17 +1801,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1553 | 1801 | ||
1554 | if (m_AngularVelocity.Z > 0) | 1802 | if (m_AngularVelocity.Z > 0) |
1555 | { | 1803 | { |
1556 | |||
1557 | float leftOverToMin = m_AngularVelocity.Z - rollMinRadians; | 1804 | float leftOverToMin = m_AngularVelocity.Z - rollMinRadians; |
1558 | if (amount > leftOverToMin) | 1805 | if (amount > leftOverToMin) |
1559 | return -leftOverToMin; | 1806 | return -leftOverToMin; |
1560 | else | 1807 | else |
1561 | return -amount; | 1808 | return -amount; |
1562 | |||
1563 | } | 1809 | } |
1564 | else | 1810 | else |
1565 | { | 1811 | { |
1566 | |||
1567 | float leftOverToMin = -m_AngularVelocity.Z - rollMinRadians; | 1812 | float leftOverToMin = -m_AngularVelocity.Z - rollMinRadians; |
1568 | if (amount > leftOverToMin) | 1813 | if (amount > leftOverToMin) |
1569 | return leftOverToMin; | 1814 | return leftOverToMin; |
@@ -1571,22 +1816,65 @@ namespace OpenSim.Region.Framework.Scenes | |||
1571 | return amount; | 1816 | return amount; |
1572 | } | 1817 | } |
1573 | } | 1818 | } |
1574 | |||
1575 | |||
1576 | 1819 | ||
1577 | // neighbouring regions we have enabled a child agent in | 1820 | // neighbouring regions we have enabled a child agent in |
1578 | // holds the seed cap for the child agent in that region | 1821 | // holds the seed cap for the child agent in that region |
1579 | private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>(); | 1822 | private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>(); |
1580 | 1823 | ||
1581 | public void AddNeighbourRegion(ulong regionHandle, string cap) | 1824 | struct spRegionSizeInfo |
1825 | { | ||
1826 | public int sizeX; | ||
1827 | public int sizeY; | ||
1828 | } | ||
1829 | |||
1830 | private Dictionary<ulong, spRegionSizeInfo> m_knownChildRegionsSizeInfo = new Dictionary<ulong, spRegionSizeInfo>(); | ||
1831 | |||
1832 | public void AddNeighbourRegion(GridRegion region, string capsPath) | ||
1833 | { | ||
1834 | lock (m_knownChildRegions) | ||
1835 | { | ||
1836 | ulong regionHandle = region.RegionHandle; | ||
1837 | m_knownChildRegions.Add(regionHandle,capsPath); | ||
1838 | |||
1839 | spRegionSizeInfo sizeInfo = new spRegionSizeInfo(); | ||
1840 | sizeInfo.sizeX = region.RegionSizeX; | ||
1841 | sizeInfo.sizeY = region.RegionSizeY; | ||
1842 | m_knownChildRegionsSizeInfo[regionHandle] = sizeInfo; | ||
1843 | } | ||
1844 | } | ||
1845 | |||
1846 | public void AddNeighbourRegionSizeInfo(GridRegion region) | ||
1847 | { | ||
1848 | lock (m_knownChildRegions) | ||
1849 | { | ||
1850 | spRegionSizeInfo sizeInfo = new spRegionSizeInfo(); | ||
1851 | sizeInfo.sizeX = region.RegionSizeX; | ||
1852 | sizeInfo.sizeY = region.RegionSizeY; | ||
1853 | ulong regionHandle = region.RegionHandle; | ||
1854 | |||
1855 | if (!m_knownChildRegionsSizeInfo.ContainsKey(regionHandle)) | ||
1856 | { | ||
1857 | m_knownChildRegionsSizeInfo.Add(regionHandle, sizeInfo); | ||
1858 | |||
1859 | } | ||
1860 | else | ||
1861 | m_knownChildRegionsSizeInfo[regionHandle] = sizeInfo; | ||
1862 | } | ||
1863 | } | ||
1864 | |||
1865 | public void SetNeighbourRegionSizeInfo(List<GridRegion> regionsList) | ||
1582 | { | 1866 | { |
1583 | lock (m_knownChildRegions) | 1867 | lock (m_knownChildRegions) |
1584 | { | 1868 | { |
1585 | if (!m_knownChildRegions.ContainsKey(regionHandle)) | 1869 | m_knownChildRegionsSizeInfo.Clear(); |
1870 | |||
1871 | foreach (GridRegion region in regionsList) | ||
1586 | { | 1872 | { |
1587 | uint x, y; | 1873 | spRegionSizeInfo sizeInfo = new spRegionSizeInfo(); |
1588 | Utils.LongToUInts(regionHandle, out x, out y); | 1874 | sizeInfo.sizeX = region.RegionSizeX; |
1589 | m_knownChildRegions.Add(regionHandle, cap); | 1875 | sizeInfo.sizeY = region.RegionSizeY; |
1876 | ulong regionHandle = region.RegionHandle; | ||
1877 | m_knownChildRegionsSizeInfo.Add(regionHandle, sizeInfo); | ||
1590 | } | 1878 | } |
1591 | } | 1879 | } |
1592 | } | 1880 | } |
@@ -1600,9 +1888,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1600 | //if (m_knownChildRegions.ContainsKey(regionHandle)) | 1888 | //if (m_knownChildRegions.ContainsKey(regionHandle)) |
1601 | // m_log.DebugFormat(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count); | 1889 | // m_log.DebugFormat(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count); |
1602 | m_knownChildRegions.Remove(regionHandle); | 1890 | m_knownChildRegions.Remove(regionHandle); |
1891 | m_knownChildRegionsSizeInfo.Remove(regionHandle); | ||
1603 | } | 1892 | } |
1604 | } | 1893 | } |
1605 | 1894 | ||
1895 | public bool knowsNeighbourRegion(ulong regionHandle) | ||
1896 | { | ||
1897 | lock (m_knownChildRegions) | ||
1898 | return m_knownChildRegions.ContainsKey(regionHandle); | ||
1899 | } | ||
1900 | |||
1606 | public void DropOldNeighbours(List<ulong> oldRegions) | 1901 | public void DropOldNeighbours(List<ulong> oldRegions) |
1607 | { | 1902 | { |
1608 | foreach (ulong handle in oldRegions) | 1903 | foreach (ulong handle in oldRegions) |
@@ -1612,6 +1907,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1612 | } | 1907 | } |
1613 | } | 1908 | } |
1614 | 1909 | ||
1910 | public void DropThisRootRegionFromNeighbours() | ||
1911 | { | ||
1912 | ulong handle = m_scene.RegionInfo.RegionHandle; | ||
1913 | RemoveNeighbourRegion(handle); | ||
1914 | Scene.CapsModule.DropChildSeed(UUID, handle); | ||
1915 | } | ||
1916 | |||
1615 | public Dictionary<ulong, string> KnownRegions | 1917 | public Dictionary<ulong, string> KnownRegions |
1616 | { | 1918 | { |
1617 | get | 1919 | get |
@@ -1632,7 +1934,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1632 | { | 1934 | { |
1633 | get | 1935 | get |
1634 | { | 1936 | { |
1635 | return new List<ulong>(KnownRegions.Keys); | 1937 | lock (m_knownChildRegions) |
1938 | return new List<ulong>(m_knownChildRegions.Keys); | ||
1636 | } | 1939 | } |
1637 | } | 1940 | } |
1638 | 1941 | ||
@@ -1662,35 +1965,66 @@ namespace OpenSim.Region.Framework.Scenes | |||
1662 | public void SetSize(Vector3 size, float feetoffset) | 1965 | public void SetSize(Vector3 size, float feetoffset) |
1663 | { | 1966 | { |
1664 | if (PhysicsActor != null && !IsChildAgent) | 1967 | if (PhysicsActor != null && !IsChildAgent) |
1665 | { | 1968 | PhysicsActor.setAvatarSize(size, feetoffset); |
1666 | // Eventually there will be a physics call that sets avatar size that includes offset info. | ||
1667 | // For the moment, just set the size as passed. | ||
1668 | PhysicsActor.Size = size; | ||
1669 | // PhysicsActor.setAvatarSize(size, feetoffset); | ||
1670 | } | ||
1671 | } | 1969 | } |
1672 | 1970 | ||
1673 | private bool WaitForUpdateAgent(IClientAPI client) | 1971 | private bool WaitForUpdateAgent(IClientAPI client) |
1674 | { | 1972 | { |
1675 | // Before the source region executes UpdateAgent | 1973 | // Before the source region executes UpdateAgent |
1676 | // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination, | 1974 | // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination, |
1677 | // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the | 1975 | // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the |
1678 | // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero | 1976 | // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero |
1679 | m_updateAgentReceivedAfterTransferEvent.WaitOne(10000); | ||
1680 | 1977 | ||
1681 | UUID originID = UUID.Zero; | 1978 | try |
1979 | { | ||
1980 | if(m_updateAgentReceivedAfterTransferEvent.WaitOne(10000)) | ||
1981 | { | ||
1982 | UUID originID = UUID.Zero; | ||
1682 | 1983 | ||
1683 | lock (m_originRegionIDAccessLock) | 1984 | lock (m_originRegionIDAccessLock) |
1684 | originID = m_originRegionID; | 1985 | originID = m_originRegionID; |
1986 | if (originID.Equals(UUID.Zero)) | ||
1987 | { | ||
1988 | // Movement into region will fail | ||
1989 | m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} at {1} got invalid origin region id ", client.Name, Scene.Name); | ||
1990 | return false; | ||
1991 | } | ||
1992 | return true; | ||
1993 | } | ||
1994 | else | ||
1995 | { | ||
1996 | m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} at {1} did not receive agent update ", client.Name, Scene.Name); | ||
1997 | return false; | ||
1998 | } | ||
1999 | } | ||
2000 | catch { } | ||
1685 | 2001 | ||
1686 | if (originID.Equals(UUID.Zero)) | 2002 | return false; |
2003 | } | ||
2004 | |||
2005 | public void RotateToLookAt(Vector3 lookAt) | ||
2006 | { | ||
2007 | if(ParentID == 0) | ||
1687 | { | 2008 | { |
1688 | // Movement into region will fail | 2009 | float n = lookAt.X * lookAt.X + lookAt.Y * lookAt.Y; |
1689 | m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name); | 2010 | if(n < 0.0001f) |
1690 | return false; | 2011 | { |
2012 | Rotation = Quaternion.Identity; | ||
2013 | return; | ||
2014 | } | ||
2015 | n = lookAt.X/(float)Math.Sqrt(n); | ||
2016 | float angle = (float)Math.Acos(n); | ||
2017 | angle *= 0.5f; | ||
2018 | float s = (float)Math.Sin(angle); | ||
2019 | if(lookAt.Y < 0) | ||
2020 | s = -s; | ||
2021 | Rotation = new Quaternion( | ||
2022 | 0f, | ||
2023 | 0f, | ||
2024 | s, | ||
2025 | (float)Math.Cos(angle) | ||
2026 | ); | ||
1691 | } | 2027 | } |
1692 | |||
1693 | return true; | ||
1694 | } | 2028 | } |
1695 | 2029 | ||
1696 | /// <summary> | 2030 | /// <summary> |
@@ -1704,62 +2038,72 @@ namespace OpenSim.Region.Framework.Scenes | |||
1704 | /// </param> | 2038 | /// </param> |
1705 | public void CompleteMovement(IClientAPI client, bool openChildAgents) | 2039 | public void CompleteMovement(IClientAPI client, bool openChildAgents) |
1706 | { | 2040 | { |
1707 | // DateTime startTime = DateTime.Now; | 2041 | int ts = Util.EnvironmentTickCount(); |
1708 | 2042 | ||
1709 | m_log.InfoFormat( | 2043 | m_log.InfoFormat( |
1710 | "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", | 2044 | "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", |
1711 | client.Name, Scene.Name, AbsolutePosition); | 2045 | client.Name, Scene.Name, AbsolutePosition); |
1712 | 2046 | ||
1713 | bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); // Get this ahead of time because IsInTransit modifies 'm_AgentControlFlags' | 2047 | m_inTransit = true; |
1714 | 2048 | ||
1715 | IsInTransit = true; | ||
1716 | try | 2049 | try |
1717 | { | 2050 | { |
1718 | // Make sure it's not a login agent. We don't want to wait for updates during login | 2051 | // Make sure it's not a login agent. We don't want to wait for updates during login |
1719 | if (!(PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags))) | 2052 | if (!IsNPC && !IsRealLogin(m_teleportFlags)) |
1720 | { | 2053 | { |
2054 | |||
1721 | // Let's wait until UpdateAgent (called by departing region) is done | 2055 | // Let's wait until UpdateAgent (called by departing region) is done |
1722 | if (!WaitForUpdateAgent(client)) | 2056 | if (!WaitForUpdateAgent(client)) |
1723 | // The sending region never sent the UpdateAgent data, we have to refuse | 2057 | // The sending region never sent the UpdateAgent data, we have to refuse |
1724 | return; | 2058 | return; |
1725 | } | 2059 | } |
1726 | 2060 | ||
1727 | Vector3 look = Velocity; | 2061 | //m_log.DebugFormat("[CompleteMovement] WaitForUpdateAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); |
1728 | 2062 | ||
1729 | // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) | 2063 | bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); |
1730 | if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1)) | ||
1731 | { | ||
1732 | look = new Vector3(0.99f, 0.042f, 0); | ||
1733 | } | ||
1734 | 2064 | ||
1735 | // Prevent teleporting to an underground location | 2065 | Vector3 look = Lookat; |
1736 | // (may crash client otherwise) | 2066 | look.Z = 0f; |
1737 | // | 2067 | if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01)) |
1738 | Vector3 pos = AbsolutePosition; | ||
1739 | float ground = m_scene.GetGroundHeight(pos.X, pos.Y); | ||
1740 | if (pos.Z < ground + 1.5f) | ||
1741 | { | 2068 | { |
1742 | pos.Z = ground + 1.5f; | 2069 | look = Velocity; |
1743 | AbsolutePosition = pos; | 2070 | look.Normalize(); |
2071 | if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01) ) | ||
2072 | look = new Vector3(0.99f, 0.042f, 0); | ||
1744 | } | 2073 | } |
1745 | 2074 | ||
1746 | if (!MakeRootAgent(AbsolutePosition, flying)) | 2075 | // Check Default Location (Also See EntityTransferModule.TeleportAgentWithinRegion) |
2076 | if (AbsolutePosition.X == 128f && AbsolutePosition.Y == 128f && AbsolutePosition.Z == 22.5f) | ||
2077 | AbsolutePosition = Scene.RegionInfo.DefaultLandingPoint; | ||
2078 | |||
2079 | if (!MakeRootAgent(AbsolutePosition, flying, ref look)) | ||
1747 | { | 2080 | { |
1748 | m_log.DebugFormat( | 2081 | m_log.DebugFormat( |
1749 | "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root", | 2082 | "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root", |
1750 | Name, Scene.Name); | 2083 | Name, Scene.Name); |
1751 | 2084 | ||
1752 | return; | 2085 | return; |
1753 | } | 2086 | } |
1754 | 2087 | ||
1755 | // Tell the client that we're totally ready | ||
1756 | ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); | ||
1757 | 2088 | ||
1758 | // Child agents send initial data up in LLUDPServer.HandleUseCircuitCode() | 2089 | //m_log.DebugFormat("[CompleteMovement] MakeRootAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); |
1759 | if (!SentInitialDataToClient) | ||
1760 | SendInitialDataToClient(); | ||
1761 | 2090 | ||
1762 | // m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); | 2091 | if(!haveGroupInformation && !IsChildAgent && !IsNPC) |
2092 | { | ||
2093 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); | ||
2094 | if (gm != null) | ||
2095 | Grouptitle = gm.GetGroupTitle(m_uuid); | ||
2096 | |||
2097 | //m_log.DebugFormat("[CompleteMovement] Missing Grouptitle: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
2098 | |||
2099 | InventoryFolderBase cof = m_scene.InventoryService.GetFolderForType(client.AgentId, (FolderType)46); | ||
2100 | if (cof == null) | ||
2101 | COF = UUID.Zero; | ||
2102 | else | ||
2103 | COF = cof.ID; | ||
2104 | |||
2105 | m_log.DebugFormat("[CompleteMovement]: Missing COF for {0} is {1}", client.AgentId, COF); | ||
2106 | } | ||
1763 | 2107 | ||
1764 | if (!string.IsNullOrEmpty(m_callbackURI)) | 2108 | if (!string.IsNullOrEmpty(m_callbackURI)) |
1765 | { | 2109 | { |
@@ -1768,69 +2112,260 @@ namespace OpenSim.Region.Framework.Scenes | |||
1768 | // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete | 2112 | // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete |
1769 | // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this | 2113 | // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this |
1770 | // region as the current region, meaning that a close sent before then will fail the teleport. | 2114 | // region as the current region, meaning that a close sent before then will fail the teleport. |
1771 | // System.Threading.Thread.Sleep(2000); | 2115 | // System.Threading.Thread.Sleep(2000); |
1772 | 2116 | ||
1773 | m_log.DebugFormat( | 2117 | m_log.DebugFormat( |
1774 | "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", | 2118 | "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", |
1775 | client.Name, client.AgentId, m_callbackURI); | 2119 | client.Name, client.AgentId, m_callbackURI); |
1776 | 2120 | ||
1777 | Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); | 2121 | UUID originID; |
2122 | |||
2123 | lock (m_originRegionIDAccessLock) | ||
2124 | originID = m_originRegionID; | ||
2125 | |||
2126 | Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI); | ||
1778 | m_callbackURI = null; | 2127 | m_callbackURI = null; |
2128 | //m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1779 | } | 2129 | } |
1780 | // else | 2130 | // else |
1781 | // { | 2131 | // { |
1782 | // m_log.DebugFormat( | 2132 | // m_log.DebugFormat( |
1783 | // "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}", | 2133 | // "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}", |
1784 | // client.Name, client.AgentId, m_scene.RegionInfo.RegionName); | 2134 | // client.Name, client.AgentId, m_scene.RegionInfo.RegionName); |
1785 | // } | 2135 | // } |
2136 | |||
2137 | |||
2138 | // Tell the client that we're totally ready | ||
2139 | ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); | ||
2140 | //m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1786 | 2141 | ||
1787 | ValidateAndSendAppearanceAndAgentData(); | 2142 | bool isHGTP = (m_teleportFlags & TeleportFlags.ViaHGLogin) != 0; |
1788 | 2143 | ||
1789 | // Create child agents in neighbouring regions | 2144 | int delayctnr = Util.EnvironmentTickCount(); |
1790 | if (openChildAgents && !IsChildAgent) | 2145 | |
2146 | if (!IsChildAgent) | ||
1791 | { | 2147 | { |
1792 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); | 2148 | if( ParentPart != null && !IsNPC && (crossingFlags & 0x08) != 0) |
1793 | if (m_agentTransfer != null) | ||
1794 | { | 2149 | { |
1795 | // Note: this call can take a while, because it notifies each of the simulator's neighbours. | 2150 | |
1796 | // It's important that we don't allow the avatar to cross regions meanwhile, as that will | 2151 | // SceneObjectPart root = ParentPart.ParentGroup.RootPart; |
1797 | // cause serious errors. We've prevented that from happening by setting IsInTransit=true. | 2152 | // if(root.LocalId != ParentPart.LocalId) |
1798 | m_agentTransfer.EnableChildAgents(this); | 2153 | // ControllingClient.SendEntityTerseUpdateImmediate(root); |
2154 | // ControllingClient.SendEntityTerseUpdateImmediate(ParentPart); | ||
2155 | ParentPart.ParentGroup.SendFullUpdateToClient(ControllingClient); | ||
1799 | } | 2156 | } |
1800 | 2157 | ||
1801 | IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); | 2158 | // verify baked textures and cache |
1802 | if (friendsModule != null) | 2159 | bool cachedbaked = false; |
1803 | friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); | 2160 | |
2161 | if (IsNPC) | ||
2162 | cachedbaked = true; | ||
2163 | else | ||
2164 | { | ||
2165 | if (m_scene.AvatarFactory != null && !isHGTP) | ||
2166 | cachedbaked = m_scene.AvatarFactory.ValidateBakedTextureCache(this); | ||
2167 | |||
2168 | // not sure we need this | ||
2169 | if (!cachedbaked) | ||
2170 | { | ||
2171 | if (m_scene.AvatarFactory != null) | ||
2172 | m_scene.AvatarFactory.QueueAppearanceSave(UUID); | ||
2173 | } | ||
2174 | } | ||
2175 | //m_log.DebugFormat("[CompleteMovement] Baked check: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
2176 | } | ||
2177 | |||
2178 | if(m_teleportFlags > 0) | ||
2179 | { | ||
2180 | gotCrossUpdate = false; // sanity check | ||
2181 | if(Util.EnvironmentTickCountSubtract(delayctnr)< 500) | ||
2182 | Thread.Sleep(500); // let viewers catch us | ||
2183 | } | ||
2184 | |||
2185 | if(!gotCrossUpdate) | ||
2186 | RotateToLookAt(look); | ||
2187 | |||
2188 | // HG | ||
2189 | if(isHGTP) | ||
2190 | { | ||
2191 | // ControllingClient.SendNameReply(m_uuid, Firstname, Lastname); | ||
2192 | m_log.DebugFormat("[CompleteMovement] HG"); | ||
2193 | } | ||
2194 | |||
2195 | m_previusParcelHide = false; | ||
2196 | m_previusParcelUUID = UUID.Zero; | ||
2197 | m_currentParcelHide = false; | ||
2198 | m_currentParcelUUID = UUID.Zero; | ||
2199 | ParcelDwellTickMS = Util.GetTimeStampMS(); | ||
2200 | |||
2201 | if(!IsNPC) | ||
2202 | { | ||
2203 | GodController.SyncViewerState(); | ||
2204 | |||
2205 | // start sending terrain patchs | ||
2206 | if (!gotCrossUpdate) | ||
2207 | Scene.SendLayerData(ControllingClient); | ||
2208 | } | ||
2209 | // send initial land overlay and parcel | ||
2210 | ILandChannel landch = m_scene.LandChannel; | ||
2211 | if (landch != null) | ||
2212 | landch.sendClientInitialLandInfo(client); | ||
2213 | |||
2214 | if (!IsChildAgent) | ||
2215 | { | ||
2216 | List<ScenePresence> allpresences = m_scene.GetScenePresences(); | ||
2217 | |||
2218 | // send avatar object to all presences including us, so they cross it into region | ||
2219 | // then hide if necessary | ||
2220 | |||
2221 | SendInitialAvatarDataToAllAgents(allpresences); | ||
2222 | |||
2223 | // send this look | ||
2224 | SendAppearanceToAgent(this); | ||
2225 | |||
2226 | // send this animations | ||
2227 | |||
2228 | UUID[] animIDs = null; | ||
2229 | int[] animseqs = null; | ||
2230 | UUID[] animsobjs = null; | ||
2231 | |||
2232 | if (Animator != null) | ||
2233 | Animator.GetArrays(out animIDs, out animseqs, out animsobjs); | ||
2234 | |||
2235 | bool haveAnims = (animIDs != null && animseqs != null && animsobjs != null); | ||
2236 | |||
2237 | if (haveAnims) | ||
2238 | SendAnimPackToAgent(this, animIDs, animseqs, animsobjs); | ||
2239 | |||
2240 | // we should be able to receive updates, etc | ||
2241 | // so release them | ||
2242 | m_inTransit = false; | ||
2243 | |||
2244 | // send look and animations to others | ||
2245 | // if not cached we send greys | ||
2246 | // uncomented if will wait till avatar does baking | ||
2247 | //if (cachedbaked) | ||
2248 | { | ||
2249 | foreach (ScenePresence p in allpresences) | ||
2250 | { | ||
2251 | if (p == this) | ||
2252 | continue; | ||
2253 | |||
2254 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) | ||
2255 | continue; | ||
2256 | |||
2257 | SendAppearanceToAgentNF(p); | ||
2258 | if (haveAnims) | ||
2259 | SendAnimPackToAgentNF(p, animIDs, animseqs, animsobjs); | ||
2260 | } | ||
2261 | } // greys if | ||
2262 | |||
2263 | //m_log.DebugFormat("[CompleteMovement] ValidateAndSendAppearanceAndAgentData: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
2264 | |||
2265 | // attachments | ||
2266 | if (IsNPC || IsRealLogin(m_teleportFlags)) | ||
2267 | { | ||
2268 | if (Scene.AttachmentsModule != null) | ||
2269 | // Util.FireAndForget( | ||
2270 | // o => | ||
2271 | // { | ||
2272 | |||
2273 | if (!IsNPC) | ||
2274 | Scene.AttachmentsModule.RezAttachments(this); | ||
2275 | else | ||
2276 | Util.FireAndForget(x => | ||
2277 | { | ||
2278 | Scene.AttachmentsModule.RezAttachments(this); | ||
2279 | }); | ||
2280 | |||
2281 | // }); | ||
2282 | } | ||
2283 | else | ||
2284 | { | ||
2285 | if (m_attachments.Count > 0) | ||
2286 | { | ||
2287 | m_log.DebugFormat( | ||
2288 | "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); | ||
1804 | 2289 | ||
2290 | foreach (SceneObjectGroup sog in m_attachments) | ||
2291 | { | ||
2292 | sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); | ||
2293 | sog.ResumeScripts(); | ||
2294 | } | ||
2295 | |||
2296 | foreach (ScenePresence p in allpresences) | ||
2297 | { | ||
2298 | if (p == this) | ||
2299 | { | ||
2300 | SendAttachmentsToAgentNF(this); | ||
2301 | continue; | ||
2302 | } | ||
2303 | |||
2304 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) | ||
2305 | continue; | ||
2306 | |||
2307 | SendAttachmentsToAgentNF(p); | ||
2308 | } | ||
2309 | } | ||
2310 | } | ||
2311 | |||
2312 | //m_log.DebugFormat("[CompleteMovement] attachments: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
2313 | if (openChildAgents) | ||
2314 | { | ||
2315 | // Create child agents in neighbouring regions | ||
2316 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); | ||
2317 | if (m_agentTransfer != null) | ||
2318 | { | ||
2319 | m_agentTransfer.EnableChildAgents(this); | ||
2320 | } | ||
2321 | } | ||
2322 | // let updates be sent, with some delay | ||
2323 | m_lastChildUpdatesTime = Util.EnvironmentTickCount() + 10000; | ||
2324 | m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; | ||
2325 | m_lastChildAgentUpdateDrawDistance = DrawDistance; | ||
2326 | m_lastChildAgentUpdatePosition = AbsolutePosition; | ||
2327 | m_childUpdatesBusy = false; // allow them | ||
1805 | } | 2328 | } |
1806 | 2329 | ||
1807 | // XXX: If we force an update after activity has completed, then multiple attachments do appear correctly on a destination region | 2330 | //m_log.DebugFormat("[CompleteMovement] openChildAgents: {0}ms", Util.EnvironmentTickCountSubtract(ts)); |
1808 | // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work. | 2331 | |
1809 | // This may be due to viewer code or it may be something we're not doing properly simulator side. | 2332 | // send the rest of the world |
1810 | WorkManager.RunJob( | 2333 | if (m_teleportFlags > 0 && !IsNPC || m_currentParcelHide) |
1811 | "ScheduleAttachmentsForFullUpdate", | 2334 | SendInitialDataToMe(); |
1812 | o => ScheduleAttachmentsForFullUpdate(), | 2335 | |
1813 | null, | 2336 | // priority uses avatar position only |
1814 | string.Format("Schedule attachments for full update for {0} in {1}", Name, Scene.Name), | 2337 | // m_reprioritizationLastPosition = AbsolutePosition; |
1815 | true); | 2338 | // m_reprioritizationLastDrawDistance = DrawDistance; |
2339 | // m_reprioritizationLastTime = Util.EnvironmentTickCount() + 15000; // delay it | ||
2340 | // m_reprioritizationBusy = false; | ||
1816 | 2341 | ||
1817 | // m_log.DebugFormat( | 2342 | //m_log.DebugFormat("[CompleteMovement] SendInitialDataToMe: {0}ms", Util.EnvironmentTickCountSubtract(ts)); |
1818 | // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", | 2343 | |
1819 | // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); | 2344 | if (!IsChildAgent && openChildAgents) |
2345 | { | ||
2346 | IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); | ||
2347 | if (friendsModule != null) | ||
2348 | { | ||
2349 | if(gotCrossUpdate) | ||
2350 | friendsModule.IsNowRoot(this); | ||
2351 | else | ||
2352 | friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); | ||
2353 | } | ||
2354 | //m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
2355 | |||
2356 | } | ||
1820 | } | 2357 | } |
1821 | finally | 2358 | finally |
1822 | { | 2359 | { |
1823 | IsInTransit = false; | 2360 | haveGroupInformation = false; |
2361 | gotCrossUpdate = false; | ||
2362 | crossingFlags = 0; | ||
2363 | m_inTransit = false; | ||
1824 | } | 2364 | } |
1825 | } | 2365 | |
2366 | m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd; | ||
1826 | 2367 | ||
1827 | private void ScheduleAttachmentsForFullUpdate() | 2368 | m_log.DebugFormat("[CompleteMovement] end: {0}ms", Util.EnvironmentTickCountSubtract(ts)); |
1828 | { | ||
1829 | lock (m_attachments) | ||
1830 | { | ||
1831 | foreach (SceneObjectGroup sog in m_attachments) | ||
1832 | sog.ScheduleGroupForFullUpdate(); | ||
1833 | } | ||
1834 | } | 2369 | } |
1835 | 2370 | ||
1836 | /// <summary> | 2371 | /// <summary> |
@@ -1841,7 +2376,54 @@ namespace OpenSim.Region.Framework.Scenes | |||
1841 | /// <param name="collisionPoint"></param> | 2376 | /// <param name="collisionPoint"></param> |
1842 | /// <param name="localid"></param> | 2377 | /// <param name="localid"></param> |
1843 | /// <param name="distance"></param> | 2378 | /// <param name="distance"></param> |
1844 | /// | 2379 | /// |
2380 | |||
2381 | private void checkCameraCollision() | ||
2382 | { | ||
2383 | if(m_doingCamRayCast || !m_scene.PhysicsScene.SupportsRayCast()) | ||
2384 | return; | ||
2385 | |||
2386 | if(m_mouseLook || ParentID != 0) | ||
2387 | { | ||
2388 | if (CameraConstraintActive) | ||
2389 | { | ||
2390 | Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -10000f); // not right... | ||
2391 | UpdateCameraCollisionPlane(plane); | ||
2392 | CameraConstraintActive = false; | ||
2393 | } | ||
2394 | return; | ||
2395 | } | ||
2396 | |||
2397 | Vector3 posAdjusted = AbsolutePosition; | ||
2398 | posAdjusted.Z += 1.0f; // viewer current camera focus point | ||
2399 | |||
2400 | if(posAdjusted.ApproxEquals(m_lastCameraRayCastPos, 0.2f) && | ||
2401 | CameraPosition.ApproxEquals(m_lastCameraRayCastCam, 0.2f)) | ||
2402 | return; | ||
2403 | |||
2404 | m_lastCameraRayCastCam = CameraPosition; | ||
2405 | m_lastCameraRayCastPos = posAdjusted; | ||
2406 | |||
2407 | Vector3 tocam = CameraPosition - posAdjusted; | ||
2408 | |||
2409 | float distTocamlen = tocam.LengthSquared(); | ||
2410 | if (distTocamlen > 0.01f && distTocamlen < 400) | ||
2411 | { | ||
2412 | distTocamlen = (float)Math.Sqrt(distTocamlen); | ||
2413 | tocam *= (1.0f / distTocamlen); | ||
2414 | |||
2415 | m_doingCamRayCast = true; | ||
2416 | m_scene.PhysicsScene.RaycastWorld(posAdjusted, tocam, distTocamlen + 1.0f, RayCastCameraCallback); | ||
2417 | return; | ||
2418 | } | ||
2419 | |||
2420 | if (CameraConstraintActive) | ||
2421 | { | ||
2422 | Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -10000f); // not right... | ||
2423 | UpdateCameraCollisionPlane(plane); | ||
2424 | CameraConstraintActive = false; | ||
2425 | } | ||
2426 | } | ||
1845 | 2427 | ||
1846 | private void UpdateCameraCollisionPlane(Vector4 plane) | 2428 | private void UpdateCameraCollisionPlane(Vector4 plane) |
1847 | { | 2429 | { |
@@ -1854,17 +2436,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1854 | 2436 | ||
1855 | public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal) | 2437 | public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal) |
1856 | { | 2438 | { |
1857 | const float POSITION_TOLERANCE = 0.02f; | ||
1858 | const float ROTATION_TOLERANCE = 0.02f; | ||
1859 | |||
1860 | m_doingCamRayCast = false; | ||
1861 | if (hitYN && localid != LocalId) | 2439 | if (hitYN && localid != LocalId) |
1862 | { | 2440 | { |
1863 | SceneObjectGroup group = m_scene.GetGroupByPrim(localid); | 2441 | if (localid != 0) |
1864 | bool IsPrim = group != null; | ||
1865 | if (IsPrim) | ||
1866 | { | 2442 | { |
1867 | SceneObjectPart part = group.GetPart(localid); | 2443 | SceneObjectPart part = m_scene.GetSceneObjectPart(localid); |
1868 | if (part != null && !part.VolumeDetectActive) | 2444 | if (part != null && !part.VolumeDetectActive) |
1869 | { | 2445 | { |
1870 | CameraConstraintActive = true; | 2446 | CameraConstraintActive = true; |
@@ -1897,13 +2473,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1897 | UpdateCameraCollisionPlane(plane); | 2473 | UpdateCameraCollisionPlane(plane); |
1898 | } | 2474 | } |
1899 | } | 2475 | } |
1900 | else if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || | 2476 | else if(CameraConstraintActive) |
1901 | !Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)) | ||
1902 | { | 2477 | { |
1903 | Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -9000f); // not right... | 2478 | Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -9000f); // not right... |
1904 | UpdateCameraCollisionPlane(plane); | 2479 | UpdateCameraCollisionPlane(plane); |
1905 | CameraConstraintActive = false; | 2480 | CameraConstraintActive = false; |
1906 | } | 2481 | } |
2482 | |||
2483 | m_doingCamRayCast = false; | ||
1907 | } | 2484 | } |
1908 | 2485 | ||
1909 | /// <summary> | 2486 | /// <summary> |
@@ -1921,12 +2498,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1921 | return; | 2498 | return; |
1922 | } | 2499 | } |
1923 | 2500 | ||
2501 | if (IsInTransit) | ||
2502 | return; | ||
2503 | |||
1924 | #region Sanity Checking | 2504 | #region Sanity Checking |
1925 | 2505 | ||
1926 | // This is irritating. Really. | 2506 | // This is irritating. Really. |
1927 | if (!AbsolutePosition.IsFinite()) | 2507 | if (!AbsolutePosition.IsFinite()) |
1928 | { | 2508 | { |
1929 | RemoveFromPhysicalScene(); | 2509 | bool isphysical = PhysicsActor != null; |
2510 | if(isphysical) | ||
2511 | RemoveFromPhysicalScene(); | ||
1930 | m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); | 2512 | m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); |
1931 | 2513 | ||
1932 | m_pos = m_LastFinitePos; | 2514 | m_pos = m_LastFinitePos; |
@@ -1938,7 +2520,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1938 | m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); | 2520 | m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); |
1939 | } | 2521 | } |
1940 | 2522 | ||
1941 | AddToPhysicalScene(false); | 2523 | if(isphysical) |
2524 | AddToPhysicalScene(false); | ||
1942 | } | 2525 | } |
1943 | else | 2526 | else |
1944 | { | 2527 | { |
@@ -1953,18 +2536,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
1953 | 2536 | ||
1954 | // The Agent's Draw distance setting | 2537 | // The Agent's Draw distance setting |
1955 | // When we get to the point of re-computing neighbors everytime this | 2538 | // When we get to the point of re-computing neighbors everytime this |
1956 | // changes, then start using the agent's drawdistance rather than the | 2539 | // changes, then start using the agent's drawdistance rather than the |
1957 | // region's draw distance. | 2540 | // region's draw distance. |
2541 | |||
1958 | DrawDistance = agentData.Far; | 2542 | DrawDistance = agentData.Far; |
1959 | // DrawDistance = Scene.DefaultDrawDistance; | ||
1960 | 2543 | ||
1961 | m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; | 2544 | m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; |
1962 | 2545 | ||
1963 | // FIXME: This does not work as intended because the viewer only sends the lbutton down when the button | 2546 | // FIXME: This does not work as intended because the viewer only sends the lbutton down when the button |
1964 | // is first pressed, not whilst it is held down. If this is required in the future then need to look | 2547 | // is first pressed, not whilst it is held down. If this is required in the future then need to look |
1965 | // for an AGENT_CONTROL_LBUTTON_UP event and make sure to handle cases where an initial DOWN is not | 2548 | // for an AGENT_CONTROL_LBUTTON_UP event and make sure to handle cases where an initial DOWN is not |
1966 | // received (e.g. on holding LMB down on the avatar in a viewer). | 2549 | // received (e.g. on holding LMB down on the avatar in a viewer). |
1967 | // m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; | 2550 | m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; |
1968 | 2551 | ||
1969 | #endregion Inputs | 2552 | #endregion Inputs |
1970 | 2553 | ||
@@ -1977,6 +2560,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1977 | // (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) | 2560 | // (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) |
1978 | // m_updateCount = UPDATE_COUNT; | 2561 | // m_updateCount = UPDATE_COUNT; |
1979 | 2562 | ||
2563 | |||
1980 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) | 2564 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) |
1981 | { | 2565 | { |
1982 | StandUp(); | 2566 | StandUp(); |
@@ -1984,38 +2568,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1984 | 2568 | ||
1985 | // Raycast from the avatar's head to the camera to see if there's anything blocking the view | 2569 | // Raycast from the avatar's head to the camera to see if there's anything blocking the view |
1986 | // this exclude checks may not be complete | 2570 | // this exclude checks may not be complete |
1987 | 2571 | if(agentData.NeedsCameraCollision) // condition parentID may be wrong | |
1988 | if (m_movementUpdateCount % NumMovementsBetweenRayCast == 0 && m_scene.PhysicsScene.SupportsRayCast()) | 2572 | checkCameraCollision(); |
1989 | { | ||
1990 | if (!m_doingCamRayCast && !m_mouseLook && ParentID == 0) | ||
1991 | { | ||
1992 | Vector3 posAdjusted = AbsolutePosition; | ||
1993 | // posAdjusted.Z += 0.5f * Appearance.AvatarSize.Z - 0.5f; | ||
1994 | posAdjusted.Z += 1.0f; // viewer current camera focus point | ||
1995 | Vector3 tocam = CameraPosition - posAdjusted; | ||
1996 | tocam.X = (float)Math.Round(tocam.X, 1); | ||
1997 | tocam.Y = (float)Math.Round(tocam.Y, 1); | ||
1998 | tocam.Z = (float)Math.Round(tocam.Z, 1); | ||
1999 | |||
2000 | float distTocamlen = tocam.Length(); | ||
2001 | if (distTocamlen > 0.3f) | ||
2002 | { | ||
2003 | tocam *= (1.0f / distTocamlen); | ||
2004 | posAdjusted.X = (float)Math.Round(posAdjusted.X, 1); | ||
2005 | posAdjusted.Y = (float)Math.Round(posAdjusted.Y, 1); | ||
2006 | posAdjusted.Z = (float)Math.Round(posAdjusted.Z, 1); | ||
2007 | |||
2008 | m_doingCamRayCast = true; | ||
2009 | m_scene.PhysicsScene.RaycastWorld(posAdjusted, tocam, distTocamlen + 1.0f, RayCastCameraCallback); | ||
2010 | } | ||
2011 | } | ||
2012 | else if (CameraConstraintActive && (m_mouseLook || ParentID != 0)) | ||
2013 | { | ||
2014 | Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -10000f); // not right... | ||
2015 | UpdateCameraCollisionPlane(plane); | ||
2016 | CameraConstraintActive = false; | ||
2017 | } | ||
2018 | } | ||
2019 | 2573 | ||
2020 | uint flagsForScripts = (uint)flags; | 2574 | uint flagsForScripts = (uint)flags; |
2021 | flags = RemoveIgnoredControls(flags, IgnoredControls); | 2575 | flags = RemoveIgnoredControls(flags, IgnoredControls); |
@@ -2032,7 +2586,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2032 | 2586 | ||
2033 | // We need to send this back to the client in order to stop the edit beams | 2587 | // We need to send this back to the client in order to stop the edit beams |
2034 | if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None) | 2588 | if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None) |
2035 | ControllingClient.SendAgentTerseUpdate(this); | 2589 | SendAgentTerseUpdate(this); |
2036 | 2590 | ||
2037 | PhysicsActor actor = PhysicsActor; | 2591 | PhysicsActor actor = PhysicsActor; |
2038 | 2592 | ||
@@ -2046,9 +2600,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2046 | if (AllowMovement && !SitGround) | 2600 | if (AllowMovement && !SitGround) |
2047 | { | 2601 | { |
2048 | // m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name); | 2602 | // m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name); |
2049 | |||
2050 | bool update_rotation = false; | 2603 | bool update_rotation = false; |
2051 | |||
2052 | if (agentData.BodyRotation != Rotation) | 2604 | if (agentData.BodyRotation != Rotation) |
2053 | { | 2605 | { |
2054 | Rotation = agentData.BodyRotation; | 2606 | Rotation = agentData.BodyRotation; |
@@ -2056,31 +2608,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
2056 | } | 2608 | } |
2057 | 2609 | ||
2058 | bool update_movementflag = false; | 2610 | bool update_movementflag = false; |
2059 | 2611 | bool mvToTarget = m_movingToTarget; | |
2060 | // If we were just made root agent then we must perform movement updates for the first AgentUpdate that | ||
2061 | // we get | ||
2062 | if (MovementFlag == ForceUpdateMovementFlagValue) | ||
2063 | { | ||
2064 | MovementFlag = 0; | ||
2065 | update_movementflag = true; | ||
2066 | } | ||
2067 | |||
2068 | if (agentData.UseClientAgentPosition) | 2612 | if (agentData.UseClientAgentPosition) |
2069 | { | 2613 | { |
2070 | MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; | 2614 | m_movingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).LengthSquared() > 0.04f; |
2071 | MoveToPositionTarget = agentData.ClientAgentPosition; | 2615 | m_moveToPositionTarget = agentData.ClientAgentPosition; |
2616 | m_moveToSpeed = -1f; | ||
2072 | } | 2617 | } |
2073 | 2618 | ||
2074 | int i = 0; | 2619 | int i = 0; |
2075 | bool DCFlagKeyPressed = false; | 2620 | bool DCFlagKeyPressed = false; |
2076 | Vector3 agent_control_v3 = Vector3.Zero; | 2621 | Vector3 agent_control_v3 = Vector3.Zero; |
2077 | 2622 | ||
2078 | bool newFlying = actor.Flying; | 2623 | bool newFlying = false; |
2079 | 2624 | ||
2080 | if (ForceFly) | 2625 | if (ForceFly) |
2081 | newFlying = true; | 2626 | newFlying = true; |
2082 | else if (FlyDisabled) | 2627 | else if (FlyDisabled) |
2083 | newFlying = false; | 2628 | newFlying = false; |
2629 | else if(mvToTarget) | ||
2630 | newFlying = actor.Flying; | ||
2084 | else | 2631 | else |
2085 | newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); | 2632 | newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); |
2086 | 2633 | ||
@@ -2096,6 +2643,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2096 | { | 2643 | { |
2097 | bool bAllowUpdateMoveToPosition = false; | 2644 | bool bAllowUpdateMoveToPosition = false; |
2098 | 2645 | ||
2646 | Vector3[] dirVectors; | ||
2647 | |||
2648 | // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying | ||
2649 | // this prevents 'jumping' in inappropriate situations. | ||
2650 | // if (!Flying && (m_mouseLook || m_leftButtonDown)) | ||
2651 | // dirVectors = GetWalkDirectionVectors(); | ||
2652 | // else | ||
2653 | dirVectors = Dir_Vectors; | ||
2654 | |||
2099 | // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. | 2655 | // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. |
2100 | foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) | 2656 | foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) |
2101 | { | 2657 | { |
@@ -2105,9 +2661,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2105 | 2661 | ||
2106 | try | 2662 | try |
2107 | { | 2663 | { |
2108 | // Don't slide against ground when crouching if camera is panned around avatar | 2664 | agent_control_v3 += Dir_Vectors[i]; |
2109 | if (Flying || DCF != Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN) | ||
2110 | agent_control_v3 += Dir_Vectors[i]; | ||
2111 | //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); | 2665 | //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); |
2112 | } | 2666 | } |
2113 | catch (IndexOutOfRangeException) | 2667 | catch (IndexOutOfRangeException) |
@@ -2115,10 +2669,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
2115 | // Why did I get this? | 2669 | // Why did I get this? |
2116 | } | 2670 | } |
2117 | 2671 | ||
2118 | if (((MovementFlag & (uint)DCF) == 0) & !AgentControlStopActive) | 2672 | if (((MovementFlag & (uint)DCF) == 0)) |
2119 | { | 2673 | { |
2120 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); | 2674 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); |
2121 | MovementFlag += (uint)DCF; | 2675 | MovementFlag |= (uint)DCF; |
2122 | update_movementflag = true; | 2676 | update_movementflag = true; |
2123 | } | 2677 | } |
2124 | } | 2678 | } |
@@ -2127,7 +2681,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2127 | if ((MovementFlag & (uint)DCF) != 0) | 2681 | if ((MovementFlag & (uint)DCF) != 0) |
2128 | { | 2682 | { |
2129 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); | 2683 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); |
2130 | MovementFlag -= (uint)DCF; | 2684 | MovementFlag &= (uint)~DCF; |
2131 | update_movementflag = true; | 2685 | update_movementflag = true; |
2132 | 2686 | ||
2133 | /* | 2687 | /* |
@@ -2154,7 +2708,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2154 | update_movementflag = true; | 2708 | update_movementflag = true; |
2155 | } | 2709 | } |
2156 | 2710 | ||
2157 | if (MovingToTarget) | 2711 | if (m_movingToTarget) |
2158 | { | 2712 | { |
2159 | // If the user has pressed a key then we want to cancel any move to target. | 2713 | // If the user has pressed a key then we want to cancel any move to target. |
2160 | if (DCFlagKeyPressed) | 2714 | if (DCFlagKeyPressed) |
@@ -2167,7 +2721,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2167 | // The UseClientAgentPosition is set if parcel ban is forcing the avatar to move to a | 2721 | // The UseClientAgentPosition is set if parcel ban is forcing the avatar to move to a |
2168 | // certain position. It's only check for tolerance on returning to that position is 0.2 | 2722 | // certain position. It's only check for tolerance on returning to that position is 0.2 |
2169 | // rather than 1, at which point it removes its force target. | 2723 | // rather than 1, at which point it removes its force target. |
2170 | if (HandleMoveToTargetUpdate(agentData.UseClientAgentPosition ? 0.2 : 1, ref agent_control_v3)) | 2724 | if (HandleMoveToTargetUpdate(agentData.UseClientAgentPosition ? 0.2f : 1f, ref agent_control_v3)) |
2171 | update_movementflag = true; | 2725 | update_movementflag = true; |
2172 | } | 2726 | } |
2173 | } | 2727 | } |
@@ -2180,11 +2734,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
2180 | if (Flying && !ForceFly) | 2734 | if (Flying && !ForceFly) |
2181 | { | 2735 | { |
2182 | // Need to stop in mid air if user holds down AGENT_CONTROL_STOP | 2736 | // Need to stop in mid air if user holds down AGENT_CONTROL_STOP |
2183 | if (AgentControlStopActive) | 2737 | // if (AgentControlStopActive) |
2184 | { | 2738 | // { |
2185 | agent_control_v3 = Vector3.Zero; | 2739 | // agent_control_v3 = Vector3.Zero; |
2186 | } | 2740 | // } |
2187 | else | 2741 | // else |
2188 | { | 2742 | { |
2189 | // Landing detection code | 2743 | // Landing detection code |
2190 | 2744 | ||
@@ -2192,38 +2746,43 @@ namespace OpenSim.Region.Framework.Scenes | |||
2192 | bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || | 2746 | bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || |
2193 | ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); | 2747 | ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); |
2194 | 2748 | ||
2195 | //m_log.Debug("[CONTROL]: " +flags); | 2749 | //m_log.Debug("[CONTROL]: " +flags); |
2196 | // Applies a satisfying roll effect to the avatar when flying. | 2750 | // Applies a satisfying roll effect to the avatar when flying. |
2197 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) | 2751 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) |
2198 | { | 2752 | { |
2199 | ApplyFlyingRoll( | 2753 | ApplyFlyingRoll( |
2200 | FLY_ROLL_RADIANS_PER_UPDATE, | 2754 | FLY_ROLL_RADIANS_PER_UPDATE, |
2201 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | 2755 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, |
2202 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | 2756 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); |
2203 | } | 2757 | } |
2204 | else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && | 2758 | else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && |
2205 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) | 2759 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) |
2206 | { | 2760 | { |
2207 | ApplyFlyingRoll( | 2761 | ApplyFlyingRoll( |
2208 | -FLY_ROLL_RADIANS_PER_UPDATE, | 2762 | -FLY_ROLL_RADIANS_PER_UPDATE, |
2209 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | 2763 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, |
2210 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | 2764 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); |
2211 | } | 2765 | } |
2212 | else | 2766 | else |
2213 | { | 2767 | { |
2214 | if (m_AngularVelocity.Z != 0) | 2768 | if (m_AngularVelocity.Z != 0) |
2215 | m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); | 2769 | m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); |
2216 | } | ||
2217 | |||
2218 | if (Flying && IsColliding && controlland) | ||
2219 | { | ||
2220 | // nesting this check because LengthSquared() is expensive and we don't | ||
2221 | // want to do it every step when flying. | ||
2222 | if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) | ||
2223 | StopFlying(); | ||
2224 | } | 2770 | } |
2771 | |||
2772 | /* | ||
2773 | if (Flying && IsColliding && controlland) | ||
2774 | { | ||
2775 | // nesting this check because LengthSquared() is expensive and we don't | ||
2776 | // want to do it every step when flying. | ||
2777 | if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) | ||
2778 | StopFlying(); | ||
2779 | } | ||
2780 | */ | ||
2225 | } | 2781 | } |
2226 | } | 2782 | } |
2783 | else if (IsColliding && agent_control_v3.Z < 0f) | ||
2784 | agent_control_v3.Z = 0; | ||
2785 | // else if(AgentControlStopActive %% Velocity.Z <0.01f) | ||
2227 | 2786 | ||
2228 | // m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name); | 2787 | // m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name); |
2229 | 2788 | ||
@@ -2231,54 +2790,60 @@ namespace OpenSim.Region.Framework.Scenes | |||
2231 | // which occurs later in the main scene loop | 2790 | // which occurs later in the main scene loop |
2232 | // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they | 2791 | // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they |
2233 | // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update | 2792 | // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update |
2234 | // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the | 2793 | // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the |
2235 | // avatar location in place). | 2794 | // avatar location in place). |
2236 | if (update_movementflag | 2795 | |
2796 | if (update_movementflag | ||
2237 | || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0))) | 2797 | || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0))) |
2238 | { | 2798 | { |
2239 | // if (update_movementflag || !AgentControlStopActive || MovementFlag != 0) | ||
2240 | // { | ||
2241 | // m_log.DebugFormat( | ||
2242 | // "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, mf = {4}, ur = {5}", | ||
2243 | // m_scene.RegionInfo.RegionName, agent_control_v3, Name, | ||
2244 | // update_movementflag, MovementFlag, update_rotation); | ||
2245 | 2799 | ||
2246 | float speedModifier; | 2800 | if (AgentControlStopActive) |
2247 | 2801 | { | |
2248 | if (AgentControlStopActive) | 2802 | // if (MovementFlag == 0 && Animator.Falling) |
2249 | speedModifier = AgentControlStopSlowWhilstMoving; | 2803 | if (MovementFlag == 0 && Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling) |
2804 | { | ||
2805 | AddNewMovement(agent_control_v3, AgentControlStopSlowVel, true); | ||
2806 | } | ||
2250 | else | 2807 | else |
2251 | speedModifier = 1; | 2808 | AddNewMovement(agent_control_v3, AgentControlStopSlowVel); |
2252 | 2809 | } | |
2253 | AddNewMovement(agent_control_v3, speedModifier); | 2810 | else |
2254 | // } | 2811 | { |
2812 | if(m_movingToTarget || | ||
2813 | (Animator.currentControlState != ScenePresenceAnimator.motionControlStates.flying && | ||
2814 | Animator.currentControlState != ScenePresenceAnimator.motionControlStates.onsurface) | ||
2815 | ) | ||
2816 | AddNewMovement(agent_control_v3); | ||
2817 | else | ||
2818 | { | ||
2819 | if (MovementFlag != 0) | ||
2820 | AddNewMovement(agent_control_v3); | ||
2821 | else | ||
2822 | m_delayedStop = Util.GetTimeStampMS() + 200.0; | ||
2823 | } | ||
2824 | } | ||
2255 | } | 2825 | } |
2256 | // else | 2826 | /* |
2257 | // { | 2827 | if (update_movementflag && ParentID == 0 && m_delayedStop < 0) |
2258 | // if (!update_movementflag) | ||
2259 | // { | ||
2260 | // m_log.DebugFormat( | ||
2261 | // "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false", | ||
2262 | // m_scene.RegionInfo.RegionName, agent_control_v3, Name); | ||
2263 | // } | ||
2264 | // } | ||
2265 | |||
2266 | if (update_movementflag && ParentID == 0) | ||
2267 | { | 2828 | { |
2268 | // m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name); | 2829 | // m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name); |
2269 | Animator.UpdateMovementAnimations(); | 2830 | Animator.UpdateMovementAnimations(); |
2270 | } | 2831 | } |
2271 | 2832 | */ | |
2272 | SendControlsToScripts(flagsForScripts); | 2833 | SendControlsToScripts(flagsForScripts); |
2273 | } | 2834 | } |
2274 | 2835 | ||
2275 | // We need to send this back to the client in order to see the edit beams | 2836 | // We need to send this back to the client in order to see the edit beams |
2276 | if ((State & (uint)AgentState.Editing) != 0) | 2837 | if ((State & (uint)AgentState.Editing) != 0) |
2277 | ControllingClient.SendAgentTerseUpdate(this); | 2838 | SendAgentTerseUpdate(this); |
2278 | 2839 | ||
2279 | m_scene.EventManager.TriggerOnClientMovement(this); | 2840 | // m_scene.EventManager.TriggerOnClientMovement(this); |
2280 | } | 2841 | } |
2281 | 2842 | ||
2843 | private void HandleAgentFOV(IClientAPI remoteClient, float _fov) | ||
2844 | { | ||
2845 | m_FOV = _fov; | ||
2846 | } | ||
2282 | 2847 | ||
2283 | /// <summary> | 2848 | /// <summary> |
2284 | /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering. | 2849 | /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering. |
@@ -2290,60 +2855,37 @@ namespace OpenSim.Region.Framework.Scenes | |||
2290 | // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); | 2855 | // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); |
2291 | 2856 | ||
2292 | if (IsChildAgent) | 2857 | if (IsChildAgent) |
2293 | { | ||
2294 | // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); | ||
2295 | return; | 2858 | return; |
2296 | } | ||
2297 | 2859 | ||
2298 | ++m_movementUpdateCount; | 2860 | if(IsInTransit) |
2299 | if (m_movementUpdateCount < 1) | 2861 | return; |
2300 | m_movementUpdateCount = 1; | ||
2301 | 2862 | ||
2302 | // AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; | 2863 | // AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; |
2303 | 2864 | ||
2304 | // Camera location in world. We'll need to raytrace | 2865 | // Camera location in world. We'll need to raytrace |
2305 | // from this location from time to time. | 2866 | // from this location from time to time. |
2306 | CameraPosition = agentData.CameraCenter; | 2867 | CameraPosition = agentData.CameraCenter; |
2307 | if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance) | ||
2308 | { | ||
2309 | ReprioritizeUpdates(); | ||
2310 | m_lastCameraPosition = CameraPosition; | ||
2311 | } | ||
2312 | |||
2313 | // Use these three vectors to figure out what the agent is looking at | 2868 | // Use these three vectors to figure out what the agent is looking at |
2314 | // Convert it to a Matrix and/or Quaternion | 2869 | // Convert it to a Matrix and/or Quaternion |
2870 | |||
2871 | // this may need lock | ||
2315 | CameraAtAxis = agentData.CameraAtAxis; | 2872 | CameraAtAxis = agentData.CameraAtAxis; |
2316 | CameraLeftAxis = agentData.CameraLeftAxis; | 2873 | CameraLeftAxis = agentData.CameraLeftAxis; |
2317 | CameraUpAxis = agentData.CameraUpAxis; | 2874 | CameraUpAxis = agentData.CameraUpAxis; |
2318 | |||
2319 | // The Agent's Draw distance setting | ||
2320 | // When we get to the point of re-computing neighbors everytime this | ||
2321 | // changes, then start using the agent's drawdistance rather than the | ||
2322 | // region's draw distance. | ||
2323 | DrawDistance = agentData.Far; | 2875 | DrawDistance = agentData.Far; |
2324 | // DrawDistance = Scene.DefaultDrawDistance; | ||
2325 | |||
2326 | // Check if Client has camera in 'follow cam' or 'build' mode. | ||
2327 | Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation); | ||
2328 | 2876 | ||
2329 | m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f) | 2877 | CameraAtAxis.Normalize(); |
2330 | && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; | 2878 | CameraLeftAxis.Normalize(); |
2879 | CameraUpAxis.Normalize(); | ||
2880 | Quaternion camRot = Util.Axes2Rot(CameraAtAxis, CameraLeftAxis, CameraUpAxis); | ||
2881 | CameraRotation = camRot; | ||
2331 | 2882 | ||
2332 | 2883 | if(agentData.NeedsCameraCollision) | |
2333 | //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); | 2884 | checkCameraCollision(); |
2334 | // Raycast from the avatar's head to the camera to see if there's anything blocking the view | ||
2335 | if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) | ||
2336 | { | ||
2337 | if (m_followCamAuto) | ||
2338 | { | ||
2339 | Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; | ||
2340 | m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback); | ||
2341 | } | ||
2342 | } | ||
2343 | 2885 | ||
2344 | TriggerScenePresenceUpdated(); | 2886 | TriggerScenePresenceUpdated(); |
2345 | } | 2887 | } |
2346 | 2888 | ||
2347 | /// <summary> | 2889 | /// <summary> |
2348 | /// Calculate an update to move the presence to the set target. | 2890 | /// Calculate an update to move the presence to the set target. |
2349 | /// </summary> | 2891 | /// </summary> |
@@ -2352,125 +2894,158 @@ namespace OpenSim.Region.Framework.Scenes | |||
2352 | /// </remarks> | 2894 | /// </remarks> |
2353 | /// <param value="agent_control_v3">Cumulative agent movement that this method will update.</param> | 2895 | /// <param value="agent_control_v3">Cumulative agent movement that this method will update.</param> |
2354 | /// <returns>True if movement has been updated in some way. False otherwise.</returns> | 2896 | /// <returns>True if movement has been updated in some way. False otherwise.</returns> |
2355 | public bool HandleMoveToTargetUpdate(double tolerance, ref Vector3 agent_control_v3) | 2897 | public bool HandleMoveToTargetUpdate(float tolerance, ref Vector3 agent_control_v3) |
2356 | { | 2898 | { |
2357 | // m_log.DebugFormat("[SCENE PRESENCE]: Called HandleMoveToTargetUpdate() for {0}", Name); | 2899 | // m_log.DebugFormat("[SCENE PRESENCE]: Called HandleMoveToTargetUpdate() for {0}", Name); |
2358 | 2900 | ||
2359 | bool updated = false; | 2901 | bool updated = false; |
2360 | 2902 | ||
2903 | Vector3 LocalVectorToTarget3D = m_moveToPositionTarget - AbsolutePosition; | ||
2904 | |||
2361 | // m_log.DebugFormat( | 2905 | // m_log.DebugFormat( |
2362 | // "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}", | 2906 | // "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}", |
2363 | // allowUpdate, m_moveToPositionInProgress, m_autopilotMoving); | 2907 | // allowUpdate, m_moveToPositionInProgress, m_autopilotMoving); |
2364 | 2908 | ||
2365 | double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget); | 2909 | float distanceToTarget; |
2910 | if(Flying && !LandAtTarget) | ||
2911 | { | ||
2912 | distanceToTarget = LocalVectorToTarget3D.Length(); | ||
2913 | } | ||
2914 | else | ||
2915 | { | ||
2916 | distanceToTarget = (float)Math.Sqrt(LocalVectorToTarget3D.X * LocalVectorToTarget3D.X + | ||
2917 | LocalVectorToTarget3D.Y * LocalVectorToTarget3D.Y); | ||
2918 | } | ||
2366 | 2919 | ||
2367 | // m_log.DebugFormat( | 2920 | // m_log.DebugFormat( |
2368 | // "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}", | 2921 | // "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}", |
2369 | // Name, AbsolutePosition, MoveToPositionTarget, distanceToTarget); | 2922 | // Name, AbsolutePosition, MoveToPositionTarget, distanceToTarget); |
2370 | 2923 | ||
2371 | // Check the error term of the current position in relation to the target position | 2924 | // Check the error term of the current position in relation to the target position |
2372 | if (distanceToTarget <= tolerance) | 2925 | if (distanceToTarget <= tolerance) |
2373 | { | 2926 | { |
2374 | // We are close enough to the target | 2927 | // We are close enough to the target |
2375 | AbsolutePosition = MoveToPositionTarget; | 2928 | Velocity = Vector3.Zero; |
2929 | AbsolutePosition = m_moveToPositionTarget; | ||
2930 | if (Flying) | ||
2931 | { | ||
2932 | if (LandAtTarget) | ||
2933 | Flying = false; | ||
2934 | |||
2935 | // A horrible hack to stop the avatar dead in its tracks rather than having them overshoot | ||
2936 | // the target if flying. | ||
2937 | // We really need to be more subtle (slow the avatar as it approaches the target) or at | ||
2938 | // least be able to set collision status once, rather than 5 times to give it enough | ||
2939 | // weighting so that that PhysicsActor thinks it really is colliding. | ||
2940 | for (int i = 0; i < 5; i++) | ||
2941 | IsColliding = true; | ||
2942 | } | ||
2376 | ResetMoveToTarget(); | 2943 | ResetMoveToTarget(); |
2377 | updated = true; | 2944 | return false; |
2378 | } | 2945 | } |
2379 | else | 2946 | |
2947 | if(m_moveToSpeed > 0 && distanceToTarget <= m_moveToSpeed * Scene.FrameTime) | ||
2948 | m_moveToSpeed = distanceToTarget / Scene.FrameTime; | ||
2949 | |||
2950 | try | ||
2380 | { | 2951 | { |
2381 | try | 2952 | // move avatar in 3D towards target, in avatar coordinate frame. |
2382 | { | 2953 | // This movement vector gets added to the velocity through AddNewMovement(). |
2383 | // move avatar in 3D at one meter/second towards target, in avatar coordinate frame. | 2954 | // Theoretically we might need a more complex PID approach here if other |
2384 | // This movement vector gets added to the velocity through AddNewMovement(). | 2955 | // unknown forces are acting on the avatar and we need to adaptively respond |
2385 | // Theoretically we might need a more complex PID approach here if other | 2956 | // to such forces, but the following simple approach seems to works fine. |
2386 | // unknown forces are acting on the avatar and we need to adaptively respond | ||
2387 | // to such forces, but the following simple approach seems to works fine. | ||
2388 | Vector3 LocalVectorToTarget3D = | ||
2389 | (MoveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords | ||
2390 | * Matrix4.CreateFromQuaternion(Quaternion.Inverse(Rotation)); // change to avatar coords | ||
2391 | // Ignore z component of vector | ||
2392 | // Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); | ||
2393 | LocalVectorToTarget3D.Normalize(); | ||
2394 | |||
2395 | // update avatar movement flags. the avatar coordinate system is as follows: | ||
2396 | // | ||
2397 | // +X (forward) | ||
2398 | // | ||
2399 | // ^ | ||
2400 | // | | ||
2401 | // | | ||
2402 | // | | ||
2403 | // | | ||
2404 | // (left) +Y <--------o--------> -Y | ||
2405 | // avatar | ||
2406 | // | | ||
2407 | // | | ||
2408 | // | | ||
2409 | // | | ||
2410 | // v | ||
2411 | // -X | ||
2412 | // | ||
2413 | 2957 | ||
2414 | // based on the above avatar coordinate system, classify the movement into | 2958 | float angle = 0.5f * (float)Math.Atan2(LocalVectorToTarget3D.Y, LocalVectorToTarget3D.X); |
2415 | // one of left/right/back/forward. | 2959 | Quaternion rot = new Quaternion(0,0, (float)Math.Sin(angle),(float)Math.Cos(angle)); |
2416 | if (LocalVectorToTarget3D.X < 0) //MoveBack | 2960 | Rotation = rot; |
2417 | { | 2961 | LocalVectorToTarget3D = LocalVectorToTarget3D * Quaternion.Inverse(rot); // change to avatar coords |
2418 | MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; | 2962 | LocalVectorToTarget3D.Normalize(); |
2419 | AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; | ||
2420 | updated = true; | ||
2421 | } | ||
2422 | else if (LocalVectorToTarget3D.X > 0) //Move Forward | ||
2423 | { | ||
2424 | MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; | ||
2425 | AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; | ||
2426 | updated = true; | ||
2427 | } | ||
2428 | 2963 | ||
2429 | if (LocalVectorToTarget3D.Y > 0) //MoveLeft | 2964 | // update avatar movement flags. the avatar coordinate system is as follows: |
2430 | { | 2965 | // |
2431 | MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; | 2966 | // +X (forward) |
2432 | AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; | 2967 | // |
2433 | updated = true; | 2968 | // ^ |
2434 | } | 2969 | // | |
2435 | else if (LocalVectorToTarget3D.Y < 0) //MoveRight | 2970 | // | |
2436 | { | 2971 | // | |
2437 | MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; | 2972 | // | |
2438 | AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; | 2973 | // (left) +Y <--------o--------> -Y |
2439 | updated = true; | 2974 | // avatar |
2440 | } | 2975 | // | |
2976 | // | | ||
2977 | // | | ||
2978 | // | | ||
2979 | // v | ||
2980 | // -X | ||
2981 | // | ||
2441 | 2982 | ||
2442 | if (LocalVectorToTarget3D.Z > 0) //Up | 2983 | // based on the above avatar coordinate system, classify the movement into |
2443 | { | 2984 | // one of left/right/back/forward. |
2444 | // Don't set these flags for up or down - doing so will make the avatar crouch or | 2985 | |
2445 | // keep trying to jump even if walking along level ground | 2986 | const uint noMovFlagsMask = (uint)(~(Dir_ControlFlags.DIR_CONTROL_FLAG_BACK | |
2446 | //MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_UP; | 2987 | Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD | Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT | |
2447 | //AgentControlFlags | 2988 | Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT | Dir_ControlFlags.DIR_CONTROL_FLAG_UP | |
2448 | //AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_UP; | 2989 | Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN)); |
2449 | updated = true; | 2990 | |
2450 | } | 2991 | MovementFlag &= noMovFlagsMask; |
2451 | else if (LocalVectorToTarget3D.Z < 0) //Down | 2992 | uint tmpAgentControlFlags = (uint)m_AgentControlFlags; |
2452 | { | 2993 | tmpAgentControlFlags &= noMovFlagsMask; |
2453 | //MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN; | ||
2454 | //AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN; | ||
2455 | updated = true; | ||
2456 | } | ||
2457 | 2994 | ||
2995 | if (LocalVectorToTarget3D.X < 0) //MoveBack | ||
2996 | { | ||
2997 | MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; | ||
2998 | tmpAgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; | ||
2999 | updated = true; | ||
3000 | } | ||
3001 | else if (LocalVectorToTarget3D.X > 0) //Move Forward | ||
3002 | { | ||
3003 | MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; | ||
3004 | tmpAgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; | ||
3005 | updated = true; | ||
3006 | } | ||
3007 | |||
3008 | if (LocalVectorToTarget3D.Y > 0) //MoveLeft | ||
3009 | { | ||
3010 | MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; | ||
3011 | tmpAgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; | ||
3012 | updated = true; | ||
3013 | } | ||
3014 | else if (LocalVectorToTarget3D.Y < 0) //MoveRight | ||
3015 | { | ||
3016 | MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; | ||
3017 | tmpAgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; | ||
3018 | updated = true; | ||
3019 | } | ||
3020 | |||
3021 | if (LocalVectorToTarget3D.Z > 0) //Up | ||
3022 | updated = true; | ||
3023 | |||
3024 | else if (LocalVectorToTarget3D.Z < 0) //Down | ||
3025 | updated = true; | ||
3026 | |||
2458 | // m_log.DebugFormat( | 3027 | // m_log.DebugFormat( |
2459 | // "[SCENE PRESENCE]: HandleMoveToTargetUpdate adding {0} to move vector {1} for {2}", | 3028 | // "[SCENE PRESENCE]: HandleMoveToTargetUpdate adding {0} to move vector {1} for {2}", |
2460 | // LocalVectorToTarget3D, agent_control_v3, Name); | 3029 | // LocalVectorToTarget3D, agent_control_v3, Name); |
2461 | 3030 | ||
3031 | m_AgentControlFlags = (AgentManager.ControlFlags) tmpAgentControlFlags; | ||
3032 | if(updated) | ||
2462 | agent_control_v3 += LocalVectorToTarget3D; | 3033 | agent_control_v3 += LocalVectorToTarget3D; |
2463 | } | 3034 | } |
2464 | catch (Exception e) | 3035 | catch (Exception e) |
2465 | { | 3036 | { |
2466 | //Avoid system crash, can be slower but... | 3037 | //Avoid system crash, can be slower but... |
2467 | m_log.DebugFormat("Crash! {0}", e.ToString()); | 3038 | m_log.DebugFormat("Crash! {0}", e.ToString()); |
2468 | } | ||
2469 | } | 3039 | } |
2470 | 3040 | ||
2471 | return updated; | 3041 | return updated; |
3042 | // AddNewMovement(agent_control_v3); | ||
2472 | } | 3043 | } |
2473 | 3044 | ||
3045 | public void MoveToTargetHandle(Vector3 pos, bool noFly, bool landAtTarget) | ||
3046 | { | ||
3047 | MoveToTarget(pos, noFly, landAtTarget); | ||
3048 | } | ||
2474 | /// <summary> | 3049 | /// <summary> |
2475 | /// Move to the given target over time. | 3050 | /// Move to the given target over time. |
2476 | /// </summary> | 3051 | /// </summary> |
@@ -2483,8 +3058,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
2483 | /// <param name="landAtTarget"> | 3058 | /// <param name="landAtTarget"> |
2484 | /// If true and the avatar starts flying during the move then land at the target. | 3059 | /// If true and the avatar starts flying during the move then land at the target. |
2485 | /// </param> | 3060 | /// </param> |
2486 | public void MoveToTarget(Vector3 pos, bool noFly, bool landAtTarget) | 3061 | public void MoveToTarget(Vector3 pos, bool noFly, bool landAtTarget, float tau = -1f) |
2487 | { | 3062 | { |
3063 | m_delayedStop = -1; | ||
3064 | |||
2488 | if (SitGround) | 3065 | if (SitGround) |
2489 | StandUp(); | 3066 | StandUp(); |
2490 | 3067 | ||
@@ -2494,89 +3071,61 @@ namespace OpenSim.Region.Framework.Scenes | |||
2494 | 3071 | ||
2495 | // Allow move to another sub-region within a megaregion | 3072 | // Allow move to another sub-region within a megaregion |
2496 | Vector2 regionSize; | 3073 | Vector2 regionSize; |
2497 | IRegionCombinerModule regionCombinerModule = m_scene.RequestModuleInterface<IRegionCombinerModule>(); | 3074 | regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY); |
2498 | if (regionCombinerModule != null) | ||
2499 | regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); | ||
2500 | else | ||
2501 | regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY); | ||
2502 | 3075 | ||
2503 | if (pos.X < 0 || pos.X >= regionSize.X | 3076 | if (pos.X < 0 || pos.X >= regionSize.X |
2504 | || pos.Y < 0 || pos.Y >= regionSize.Y | 3077 | || pos.Y < 0 || pos.Y >= regionSize.Y |
2505 | || pos.Z < 0) | 3078 | || pos.Z < 0) |
2506 | return; | 3079 | return; |
2507 | 3080 | ||
3081 | float terrainHeight; | ||
2508 | Scene targetScene = m_scene; | 3082 | Scene targetScene = m_scene; |
3083 | terrainHeight = m_scene.GetGroundHeight(pos.X, pos.Y); | ||
2509 | 3084 | ||
2510 | // Vector3 heightAdjust = new Vector3(0, 0, Appearance.AvatarHeight / 2); | 3085 | // dont try to land underground |
2511 | // pos += heightAdjust; | 3086 | terrainHeight += Appearance.AvatarHeight * 0.5f + 0.2f; |
2512 | // | ||
2513 | // // Anti duck-walking measure | ||
2514 | // if (Math.Abs(pos.Z - AbsolutePosition.Z) < 0.2f) | ||
2515 | // { | ||
2516 | //// m_log.DebugFormat("[SCENE PRESENCE]: Adjusting MoveToPosition from {0} to {1}", pos, AbsolutePosition); | ||
2517 | // pos.Z = AbsolutePosition.Z; | ||
2518 | // } | ||
2519 | 3087 | ||
2520 | // Get terrain height for sub-region in a megaregion if necessary | 3088 | if(terrainHeight > pos.Z) |
2521 | |||
2522 | //COMMENT: If its only nessesary in a megaregion, why do it on normal region's too? | ||
2523 | |||
2524 | if (regionCombinerModule != null) | ||
2525 | { | ||
2526 | int x = (int)((m_scene.RegionInfo.WorldLocX) + pos.X); | ||
2527 | int y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y); | ||
2528 | GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, x, y); | ||
2529 | |||
2530 | // If X and Y is NaN, target_region will be null | ||
2531 | if (target_region == null) | ||
2532 | return; | ||
2533 | |||
2534 | SceneManager.Instance.TryGetScene(target_region.RegionID, out targetScene); | ||
2535 | } | ||
2536 | |||
2537 | float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)]; | ||
2538 | pos.Z = Math.Max(terrainHeight, pos.Z); | ||
2539 | |||
2540 | // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is | ||
2541 | // always slightly higher than the actual terrain height. | ||
2542 | // FIXME: This constrains NPC movements as well, so should be somewhere else. | ||
2543 | if (pos.Z - terrainHeight < 0.2) | ||
2544 | pos.Z = terrainHeight; | 3089 | pos.Z = terrainHeight; |
2545 | 3090 | ||
2546 | if (noFly) | ||
2547 | Flying = false; | ||
2548 | else if (pos.Z > terrainHeight) | ||
2549 | Flying = true; | ||
2550 | |||
2551 | // m_log.DebugFormat( | 3091 | // m_log.DebugFormat( |
2552 | // "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", | 3092 | // "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", |
2553 | // Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); | 3093 | // Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); |
2554 | 3094 | ||
2555 | if (noFly) | 3095 | terrainHeight += Appearance.AvatarHeight; // so 1.5 * AvatarHeight above ground at target |
2556 | Flying = false; | 3096 | bool shouldfly = Flying; |
2557 | 3097 | if (noFly) | |
2558 | LandAtTarget = landAtTarget; | 3098 | shouldfly = false; |
2559 | MovingToTarget = true; | 3099 | else if (pos.Z > terrainHeight || Flying) |
2560 | MoveToPositionTarget = pos; | 3100 | shouldfly = true; |
2561 | 3101 | ||
2562 | // Rotate presence around the z-axis to point in same direction as movement. | ||
2563 | // Ignore z component of vector | ||
2564 | Vector3 localVectorToTarget3D = pos - AbsolutePosition; | 3102 | Vector3 localVectorToTarget3D = pos - AbsolutePosition; |
2565 | Vector3 localVectorToTarget2D = new Vector3((float)(localVectorToTarget3D.X), (float)(localVectorToTarget3D.Y), 0f); | ||
2566 | 3103 | ||
2567 | // m_log.DebugFormat("[SCENE PRESENCE]: Local vector to target is {0}", localVectorToTarget2D); | 3104 | // m_log.DebugFormat("[SCENE PRESENCE]: Local vector to target is {0},[1}", localVectorToTarget3D.X,localVectorToTarget3D.Y); |
3105 | |||
3106 | m_movingToTarget = true; | ||
3107 | LandAtTarget = landAtTarget; | ||
3108 | m_moveToPositionTarget = pos; | ||
3109 | if(tau > 0) | ||
3110 | { | ||
3111 | if(tau < Scene.FrameTime) | ||
3112 | tau = Scene.FrameTime; | ||
3113 | m_moveToSpeed = localVectorToTarget3D.Length() / tau; | ||
3114 | if(m_moveToSpeed < 0.5f) //to tune | ||
3115 | m_moveToSpeed = 0.5f; | ||
3116 | else if(m_moveToSpeed > 50f) | ||
3117 | m_moveToSpeed = 50f; | ||
2568 | 3118 | ||
2569 | // Calculate the yaw. | 3119 | SetAlwaysRun = false; |
2570 | Vector3 angle = new Vector3(0, 0, (float)(Math.Atan2(localVectorToTarget2D.Y, localVectorToTarget2D.X))); | 3120 | } |
3121 | else | ||
3122 | m_moveToSpeed = 4.096f * m_speedModifier; | ||
2571 | 3123 | ||
2572 | // m_log.DebugFormat("[SCENE PRESENCE]: Angle is {0}", angle); | 3124 | Flying = shouldfly; |
2573 | 3125 | ||
2574 | Rotation = Quaternion.CreateFromEulers(angle); | 3126 | Vector3 control = Vector3.Zero; |
2575 | // m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, Rotation); | 3127 | if(HandleMoveToTargetUpdate(1f, ref control)) |
2576 | 3128 | AddNewMovement(control); | |
2577 | Vector3 agent_control_v3 = new Vector3(); | ||
2578 | HandleMoveToTargetUpdate(1, ref agent_control_v3); | ||
2579 | AddNewMovement(agent_control_v3); | ||
2580 | } | 3129 | } |
2581 | 3130 | ||
2582 | /// <summary> | 3131 | /// <summary> |
@@ -2586,9 +3135,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
2586 | { | 3135 | { |
2587 | // m_log.DebugFormat("[SCENE PRESENCE]: Resetting move to target for {0}", Name); | 3136 | // m_log.DebugFormat("[SCENE PRESENCE]: Resetting move to target for {0}", Name); |
2588 | 3137 | ||
2589 | MovingToTarget = false; | 3138 | m_movingToTarget = false; |
3139 | m_moveToSpeed = -1f; | ||
2590 | // MoveToPositionTarget = Vector3.Zero; | 3140 | // MoveToPositionTarget = Vector3.Zero; |
2591 | m_forceToApply = null; // cancel possible last action | 3141 | // lock(m_forceToApplyLock) |
3142 | // m_forceToApplyValid = false; // cancel possible last action | ||
2592 | 3143 | ||
2593 | // We need to reset the control flag as the ScenePresenceAnimator uses this to determine the correct | 3144 | // We need to reset the control flag as the ScenePresenceAnimator uses this to determine the correct |
2594 | // resting animation (e.g. hover or stand). NPCs don't have a client that will quickly reset this flag. | 3145 | // resting animation (e.g. hover or stand). NPCs don't have a client that will quickly reset this flag. |
@@ -2629,69 +3180,65 @@ namespace OpenSim.Region.Framework.Scenes | |||
2629 | } | 3180 | } |
2630 | } | 3181 | } |
2631 | 3182 | ||
3183 | // part.ParentGroup.DeleteAvatar(UUID); | ||
3184 | |||
3185 | Quaternion standRotation = part.ParentGroup.RootPart.RotationOffset; | ||
3186 | Vector3 sitPartWorldPosition = part.ParentGroup.AbsolutePosition + m_pos * standRotation; | ||
2632 | ControllingClient.SendClearFollowCamProperties(part.ParentUUID); | 3187 | ControllingClient.SendClearFollowCamProperties(part.ParentUUID); |
2633 | 3188 | ||
2634 | ParentID = 0; | 3189 | ParentID = 0; |
2635 | ParentPart = null; | 3190 | ParentPart = null; |
2636 | 3191 | ||
2637 | Quaternion standRotation; | ||
2638 | |||
2639 | if (part.SitTargetAvatar == UUID) | 3192 | if (part.SitTargetAvatar == UUID) |
2640 | { | 3193 | standRotation = standRotation * part.SitTargetOrientation; |
2641 | standRotation = part.GetWorldRotation(); | 3194 | else |
3195 | standRotation = standRotation * m_bodyRot; | ||
2642 | 3196 | ||
2643 | if (!part.IsRoot) | 3197 | m_bodyRot = standRotation; |
2644 | standRotation = standRotation * part.SitTargetOrientation; | 3198 | |
2645 | // standRotation = part.RotationOffset * part.SitTargetOrientation; | 3199 | Quaternion standRotationZ = new Quaternion(0,0,standRotation.Z,standRotation.W); |
2646 | // else | ||
2647 | // standRotation = part.SitTargetOrientation; | ||
2648 | 3200 | ||
3201 | float t = standRotationZ.W * standRotationZ.W + standRotationZ.Z * standRotationZ.Z; | ||
3202 | if (t > 0) | ||
3203 | { | ||
3204 | t = 1.0f / (float)Math.Sqrt(t); | ||
3205 | standRotationZ.W *= t; | ||
3206 | standRotationZ.Z *= t; | ||
2649 | } | 3207 | } |
2650 | else | 3208 | else |
2651 | { | 3209 | { |
2652 | standRotation = Rotation; | 3210 | standRotationZ.W = 1.0f; |
3211 | standRotationZ.Z = 0f; | ||
2653 | } | 3212 | } |
2654 | 3213 | ||
2655 | //Vector3 standPos = ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); | 3214 | Vector3 adjustmentForSitPose = new Vector3(0.75f, 0, m_sitAvatarHeight + .3f) * standRotationZ; |
2656 | //Vector3 standPos = ParentPosition; | ||
2657 | |||
2658 | // Vector3 standPositionAdjustment | ||
2659 | // = part.SitTargetPosition + new Vector3(0.5f, 0f, m_sitAvatarHeight / 2f); | ||
2660 | Vector3 adjustmentForSitPosition = OffsetPosition * part.ParentGroup.GroupRotation - SIT_TARGET_ADJUSTMENT * part.GetWorldRotation(); | ||
2661 | 3215 | ||
2662 | // XXX: This is based on the physics capsule sizes. Need to find a better way to read this rather than | 3216 | Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose; |
2663 | // hardcoding here. | 3217 | m_pos = standPos; |
2664 | Vector3 adjustmentForSitPose = new Vector3(0.74f, 0f, 0f) * standRotation; | ||
2665 | 3218 | ||
2666 | Vector3 standPos = part.ParentGroup.AbsolutePosition + adjustmentForSitPosition + adjustmentForSitPose; | ||
2667 | |||
2668 | // m_log.DebugFormat( | ||
2669 | // "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}", | ||
2670 | // standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name); | ||
2671 | |||
2672 | Rotation = standRotation; | ||
2673 | AbsolutePosition = standPos; | ||
2674 | } | 3219 | } |
2675 | 3220 | ||
2676 | // We need to wait until we have calculated proper stand positions before sitting up the physical | 3221 | // We need to wait until we have calculated proper stand positions before sitting up the physical |
2677 | // avatar to avoid race conditions. | 3222 | // avatar to avoid race conditions. |
2678 | if (PhysicsActor == null) | 3223 | if (PhysicsActor == null) |
2679 | AddToPhysicalScene(false); | 3224 | AddToPhysicalScene(false); |
2680 | 3225 | ||
2681 | if (satOnObject) | 3226 | if (satOnObject) |
2682 | { | 3227 | { |
2683 | SendAvatarDataToAllClients(); | ||
2684 | m_requestedSitTargetID = 0; | 3228 | m_requestedSitTargetID = 0; |
2685 | |||
2686 | part.RemoveSittingAvatar(this); | 3229 | part.RemoveSittingAvatar(this); |
2687 | |||
2688 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); | 3230 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); |
3231 | |||
3232 | SendAvatarDataToAllAgents(); | ||
3233 | m_scene.EventManager.TriggerParcelPrimCountTainted(); // update select/ sat on | ||
2689 | } | 3234 | } |
2690 | 3235 | ||
2691 | else if (PhysicsActor == null) | 3236 | // reset to default sitAnimation |
2692 | AddToPhysicalScene(false); | 3237 | sitAnimation = "SIT"; |
3238 | |||
3239 | // Animator.TrySetMovementAnimation("STAND"); | ||
3240 | Animator.SetMovementAnimations("STAND"); | ||
2693 | 3241 | ||
2694 | Animator.TrySetMovementAnimation("STAND"); | ||
2695 | TriggerScenePresenceUpdated(); | 3242 | TriggerScenePresenceUpdated(); |
2696 | } | 3243 | } |
2697 | 3244 | ||
@@ -2746,28 +3293,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
2746 | 3293 | ||
2747 | if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) | 3294 | if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) |
2748 | { | 3295 | { |
2749 | // m_log.DebugFormat( | ||
2750 | // "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied", | ||
2751 | // Name, part.Name, part.LocalId); | ||
2752 | |||
2753 | offset = part.SitTargetPosition; | 3296 | offset = part.SitTargetPosition; |
2754 | sitOrientation = part.SitTargetOrientation; | 3297 | sitOrientation = part.SitTargetOrientation; |
2755 | 3298 | ||
2756 | if (!part.IsRoot) | ||
2757 | { | ||
2758 | // m_log.DebugFormat("Old sit orient {0}", sitOrientation); | ||
2759 | sitOrientation = part.RotationOffset * sitOrientation; | ||
2760 | // m_log.DebugFormat("New sit orient {0}", sitOrientation); | ||
2761 | // m_log.DebugFormat("Old sit offset {0}", offset); | ||
2762 | offset = offset * part.RotationOffset; | ||
2763 | // m_log.DebugFormat("New sit offset {0}", offset); | ||
2764 | } | ||
2765 | |||
2766 | canSit = true; | 3299 | canSit = true; |
2767 | } | 3300 | } |
2768 | else | 3301 | else |
2769 | { | 3302 | { |
2770 | if (PhysicsSit(part,offset)) // physics engine | 3303 | if (PhysicsSit(part,offset)) // physics engine |
2771 | return; | 3304 | return; |
2772 | 3305 | ||
2773 | Vector3 pos = part.AbsolutePosition + offset; | 3306 | Vector3 pos = part.AbsolutePosition + offset; |
@@ -2781,55 +3314,45 @@ namespace OpenSim.Region.Framework.Scenes | |||
2781 | 3314 | ||
2782 | if (canSit) | 3315 | if (canSit) |
2783 | { | 3316 | { |
2784 | |||
2785 | if (PhysicsActor != null) | 3317 | if (PhysicsActor != null) |
2786 | { | 3318 | { |
2787 | // We can remove the physicsActor until they stand up. | 3319 | // We can remove the physicsActor until they stand up. |
2788 | RemoveFromPhysicalScene(); | 3320 | RemoveFromPhysicalScene(); |
2789 | } | 3321 | } |
2790 | 3322 | ||
2791 | if (MovingToTarget) | 3323 | if (m_movingToTarget) |
2792 | ResetMoveToTarget(); | 3324 | ResetMoveToTarget(); |
2793 | 3325 | ||
2794 | Velocity = Vector3.Zero; | 3326 | Velocity = Vector3.Zero; |
3327 | m_AngularVelocity = Vector3.Zero; | ||
2795 | 3328 | ||
2796 | part.AddSittingAvatar(this); | 3329 | part.AddSittingAvatar(this); |
2797 | 3330 | ||
2798 | cameraAtOffset = part.GetCameraAtOffset(); | 3331 | cameraAtOffset = part.GetCameraAtOffset(); |
2799 | |||
2800 | if (!part.IsRoot && cameraAtOffset == Vector3.Zero) | ||
2801 | cameraAtOffset = part.ParentGroup.RootPart.GetCameraAtOffset(); | ||
2802 | |||
2803 | bool cameraEyeOffsetFromRootForChild = false; | ||
2804 | cameraEyeOffset = part.GetCameraEyeOffset(); | 3332 | cameraEyeOffset = part.GetCameraEyeOffset(); |
2805 | 3333 | ||
2806 | if (!part.IsRoot && cameraEyeOffset == Vector3.Zero) | 3334 | forceMouselook = part.GetForceMouselook(); |
2807 | { | ||
2808 | cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset(); | ||
2809 | cameraEyeOffsetFromRootForChild = true; | ||
2810 | } | ||
2811 | 3335 | ||
2812 | if ((cameraEyeOffset != Vector3.Zero && !cameraEyeOffsetFromRootForChild) || cameraAtOffset != Vector3.Zero) | 3336 | if (!part.IsRoot) |
2813 | { | 3337 | { |
2814 | if (!part.IsRoot) | 3338 | sitOrientation = part.RotationOffset * sitOrientation; |
3339 | offset = offset * part.RotationOffset; | ||
3340 | offset += part.OffsetPosition; | ||
3341 | |||
3342 | if (cameraAtOffset == Vector3.Zero && cameraEyeOffset == Vector3.Zero) | ||
2815 | { | 3343 | { |
2816 | cameraEyeOffset = cameraEyeOffset * part.RotationOffset; | 3344 | cameraAtOffset = part.ParentGroup.RootPart.GetCameraAtOffset(); |
3345 | cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset(); | ||
3346 | } | ||
3347 | else | ||
3348 | { | ||
3349 | cameraAtOffset = cameraAtOffset * part.RotationOffset; | ||
2817 | cameraAtOffset += part.OffsetPosition; | 3350 | cameraAtOffset += part.OffsetPosition; |
3351 | cameraEyeOffset = cameraEyeOffset * part.RotationOffset; | ||
3352 | cameraEyeOffset += part.OffsetPosition; | ||
2818 | } | 3353 | } |
2819 | |||
2820 | cameraEyeOffset += part.OffsetPosition; | ||
2821 | } | 3354 | } |
2822 | 3355 | ||
2823 | // m_log.DebugFormat( | ||
2824 | // "[SCENE PRESENCE]: Using cameraAtOffset {0}, cameraEyeOffset {1} for sit on {2} by {3} in {4}", | ||
2825 | // cameraAtOffset, cameraEyeOffset, part.Name, Name, Scene.Name); | ||
2826 | |||
2827 | forceMouselook = part.GetForceMouselook(); | ||
2828 | |||
2829 | // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is | ||
2830 | // being sat upon. | ||
2831 | offset += part.OffsetPosition; | ||
2832 | |||
2833 | ControllingClient.SendSitResponse( | 3356 | ControllingClient.SendSitResponse( |
2834 | part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); | 3357 | part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); |
2835 | 3358 | ||
@@ -2840,6 +3363,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2840 | // Moved here to avoid a race with default sit anim | 3363 | // Moved here to avoid a race with default sit anim |
2841 | // The script event needs to be raised after the default sit anim is set. | 3364 | // The script event needs to be raised after the default sit anim is set. |
2842 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); | 3365 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); |
3366 | m_scene.EventManager.TriggerParcelPrimCountTainted(); // update select/ sat on | ||
2843 | } | 3367 | } |
2844 | } | 3368 | } |
2845 | 3369 | ||
@@ -2862,7 +3386,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2862 | { | 3386 | { |
2863 | m_requestedSitTargetID = part.LocalId; | 3387 | m_requestedSitTargetID = part.LocalId; |
2864 | m_requestedSitTargetUUID = part.UUID; | 3388 | m_requestedSitTargetUUID = part.UUID; |
2865 | |||
2866 | } | 3389 | } |
2867 | else | 3390 | else |
2868 | { | 3391 | { |
@@ -2875,13 +3398,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2875 | // returns false if does not suport so older sit can be tried | 3398 | // returns false if does not suport so older sit can be tried |
2876 | public bool PhysicsSit(SceneObjectPart part, Vector3 offset) | 3399 | public bool PhysicsSit(SceneObjectPart part, Vector3 offset) |
2877 | { | 3400 | { |
2878 | // TODO: Pull in these bits | ||
2879 | return false; | ||
2880 | /* | ||
2881 | if (part == null || part.ParentGroup.IsAttachment) | 3401 | if (part == null || part.ParentGroup.IsAttachment) |
2882 | { | ||
2883 | return true; | 3402 | return true; |
2884 | } | ||
2885 | 3403 | ||
2886 | if ( m_scene.PhysicsScene == null) | 3404 | if ( m_scene.PhysicsScene == null) |
2887 | return false; | 3405 | return false; |
@@ -2893,24 +3411,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
2893 | ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot."); | 3411 | ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot."); |
2894 | else | 3412 | else |
2895 | { // non physical phantom TODO | 3413 | { // non physical phantom TODO |
2896 | ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot."); | 3414 | // ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot."); |
2897 | return false; | 3415 | return false; |
2898 | } | 3416 | } |
2899 | return true; | 3417 | return true; |
2900 | } | 3418 | } |
2901 | 3419 | ||
2902 | |||
2903 | // not doing autopilot | ||
2904 | m_requestedSitTargetID = 0; | ||
2905 | |||
2906 | if (m_scene.PhysicsScene.SitAvatar(part.PhysActor, AbsolutePosition, CameraPosition, offset, new Vector3(0.35f, 0, 0.65f), PhysicsSitResponse) != 0) | 3420 | if (m_scene.PhysicsScene.SitAvatar(part.PhysActor, AbsolutePosition, CameraPosition, offset, new Vector3(0.35f, 0, 0.65f), PhysicsSitResponse) != 0) |
3421 | { | ||
2907 | return true; | 3422 | return true; |
3423 | } | ||
2908 | 3424 | ||
2909 | return false; | 3425 | return false; |
2910 | */ | ||
2911 | } | 3426 | } |
2912 | 3427 | ||
2913 | |||
2914 | private bool CanEnterLandPosition(Vector3 testPos) | 3428 | private bool CanEnterLandPosition(Vector3 testPos) |
2915 | { | 3429 | { |
2916 | ILandObject land = m_scene.LandChannel.GetLandObject(testPos.X, testPos.Y); | 3430 | ILandObject land = m_scene.LandChannel.GetLandObject(testPos.X, testPos.Y); |
@@ -2939,7 +3453,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2939 | if (part == null) | 3453 | if (part == null) |
2940 | return; | 3454 | return; |
2941 | 3455 | ||
2942 | Vector3 targetPos = part.GetWorldPosition() + offset * part.GetWorldRotation(); | 3456 | Vector3 targetPos = part.GetWorldPosition() + offset * part.GetWorldRotation(); |
2943 | if(!CanEnterLandPosition(targetPos)) | 3457 | if(!CanEnterLandPosition(targetPos)) |
2944 | { | 3458 | { |
2945 | ControllingClient.SendAlertMessage(" Sit position on restricted land, try another spot"); | 3459 | ControllingClient.SendAlertMessage(" Sit position on restricted land, try another spot"); |
@@ -2948,36 +3462,58 @@ namespace OpenSim.Region.Framework.Scenes | |||
2948 | 3462 | ||
2949 | RemoveFromPhysicalScene(); | 3463 | RemoveFromPhysicalScene(); |
2950 | 3464 | ||
2951 | if (MovingToTarget) | 3465 | if (m_movingToTarget) |
2952 | ResetMoveToTarget(); | 3466 | ResetMoveToTarget(); |
2953 | 3467 | ||
2954 | Velocity = Vector3.Zero; | 3468 | Velocity = Vector3.Zero; |
3469 | m_AngularVelocity = Vector3.Zero; | ||
2955 | 3470 | ||
3471 | m_requestedSitTargetID = 0; | ||
2956 | part.AddSittingAvatar(this); | 3472 | part.AddSittingAvatar(this); |
2957 | 3473 | ||
3474 | ParentPart = part; | ||
3475 | ParentID = part.LocalId; | ||
3476 | |||
2958 | Vector3 cameraAtOffset = part.GetCameraAtOffset(); | 3477 | Vector3 cameraAtOffset = part.GetCameraAtOffset(); |
2959 | Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); | 3478 | Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); |
2960 | bool forceMouselook = part.GetForceMouselook(); | 3479 | bool forceMouselook = part.GetForceMouselook(); |
2961 | 3480 | ||
2962 | ControllingClient.SendSitResponse( | 3481 | if (!part.IsRoot) |
2963 | part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); | 3482 | { |
3483 | Orientation = part.RotationOffset * Orientation; | ||
3484 | offset = offset * part.RotationOffset; | ||
3485 | offset += part.OffsetPosition; | ||
2964 | 3486 | ||
2965 | // not using autopilot | 3487 | if (cameraAtOffset == Vector3.Zero && cameraEyeOffset == Vector3.Zero) |
3488 | { | ||
3489 | cameraAtOffset = part.ParentGroup.RootPart.GetCameraAtOffset(); | ||
3490 | cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset(); | ||
3491 | } | ||
3492 | else | ||
3493 | { | ||
3494 | cameraAtOffset = cameraAtOffset * part.RotationOffset; | ||
3495 | cameraAtOffset += part.OffsetPosition; | ||
3496 | cameraEyeOffset = cameraEyeOffset * part.RotationOffset; | ||
3497 | cameraEyeOffset += part.OffsetPosition; | ||
3498 | } | ||
3499 | } | ||
2966 | 3500 | ||
2967 | Rotation = Orientation; | 3501 | m_bodyRot = Orientation; |
2968 | m_pos = offset; | 3502 | m_pos = offset; |
2969 | 3503 | ||
2970 | m_requestedSitTargetID = 0; | 3504 | ControllingClient.SendSitResponse( |
3505 | part.ParentGroup.UUID, offset, Orientation, true, cameraAtOffset, cameraEyeOffset, forceMouselook); | ||
2971 | 3506 | ||
2972 | ParentPart = part; | 3507 | SendAvatarDataToAllAgents(); |
2973 | ParentID = part.LocalId; | 3508 | |
2974 | if(status == 3) | 3509 | if (status == 3) |
2975 | Animator.TrySetMovementAnimation("SIT_GROUND"); | 3510 | sitAnimation = "SIT_GROUND"; |
2976 | else | 3511 | else |
2977 | Animator.TrySetMovementAnimation("SIT"); | 3512 | sitAnimation = "SIT"; |
2978 | SendAvatarDataToAllClients(); | ||
2979 | 3513 | ||
3514 | Animator.SetMovementAnimations("SIT"); | ||
2980 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); | 3515 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); |
3516 | m_scene.EventManager.TriggerParcelPrimCountTainted(); // update select/ sat on | ||
2981 | } | 3517 | } |
2982 | 3518 | ||
2983 | public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) | 3519 | public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) |
@@ -2985,7 +3521,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2985 | if (IsChildAgent) | 3521 | if (IsChildAgent) |
2986 | return; | 3522 | return; |
2987 | 3523 | ||
2988 | SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); | 3524 | SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); |
2989 | 3525 | ||
2990 | if (part != null) | 3526 | if (part != null) |
2991 | { | 3527 | { |
@@ -3007,45 +3543,77 @@ namespace OpenSim.Region.Framework.Scenes | |||
3007 | // "[SCENE PRESENCE]: Sitting {0} at sit target {1}, {2} on {3} {4}", | 3543 | // "[SCENE PRESENCE]: Sitting {0} at sit target {1}, {2} on {3} {4}", |
3008 | // Name, sitTargetPos, sitTargetOrient, part.Name, part.LocalId); | 3544 | // Name, sitTargetPos, sitTargetOrient, part.Name, part.LocalId); |
3009 | 3545 | ||
3010 | //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0); | 3546 | double x, y, z, m; |
3011 | //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w); | 3547 | Vector3 sitOffset; |
3012 | 3548 | Quaternion r = sitTargetOrient; | |
3013 | //Quaternion result = (sitTargetOrient * vq) * nq; | ||
3014 | 3549 | ||
3015 | double x, y, z, m1, m2; | 3550 | Vector3 newPos; |
3016 | 3551 | ||
3017 | Quaternion r = sitTargetOrient; | 3552 | if (LegacySitOffsets) |
3018 | m1 = r.X * r.X + r.Y * r.Y; | ||
3019 | m2 = r.Z * r.Z + r.W * r.W; | ||
3020 | |||
3021 | // Rotate the vector <0, 0, 1> | ||
3022 | x = 2 * (r.X * r.Z + r.Y * r.W); | ||
3023 | y = 2 * (-r.X * r.W + r.Y * r.Z); | ||
3024 | z = m2 - m1; | ||
3025 | |||
3026 | // Set m to be the square of the norm of r. | ||
3027 | double m = m1 + m2; | ||
3028 | |||
3029 | // This constant is emperically determined to be what is used in SL. | ||
3030 | // See also http://opensimulator.org/mantis/view.php?id=7096 | ||
3031 | double offset = 0.05; | ||
3032 | |||
3033 | // Normally m will be ~ 1, but if someone passed a handcrafted quaternion | ||
3034 | // to llSitTarget with values so small that squaring them is rounded off | ||
3035 | // to zero, then m could be zero. The result of this floating point | ||
3036 | // round off error (causing us to skip this impossible normalization) | ||
3037 | // is only 5 cm. | ||
3038 | if (m > 0.000001) | ||
3039 | { | 3553 | { |
3040 | offset /= m; | 3554 | double m1,m2; |
3555 | |||
3556 | m1 = r.X * r.X + r.Y * r.Y; | ||
3557 | m2 = r.Z * r.Z + r.W * r.W; | ||
3558 | |||
3559 | // Rotate the vector <0, 0, 1> | ||
3560 | x = 2 * (r.X * r.Z + r.Y * r.W); | ||
3561 | y = 2 * (-r.X * r.W + r.Y * r.Z); | ||
3562 | z = m2 - m1; | ||
3563 | |||
3564 | // Set m to be the square of the norm of r. | ||
3565 | m = m1 + m2; | ||
3566 | |||
3567 | // This constant is emperically determined to be what is used in SL. | ||
3568 | // See also http://opensimulator.org/mantis/view.php?id=7096 | ||
3569 | double offset = 0.05; | ||
3570 | |||
3571 | // Normally m will be ~ 1, but if someone passed a handcrafted quaternion | ||
3572 | // to llSitTarget with values so small that squaring them is rounded off | ||
3573 | // to zero, then m could be zero. The result of this floating point | ||
3574 | // round off error (causing us to skip this impossible normalization) | ||
3575 | // is only 5 cm. | ||
3576 | if (m > 0.000001) | ||
3577 | { | ||
3578 | offset /= m; | ||
3579 | } | ||
3580 | |||
3581 | Vector3 up = new Vector3((float)x, (float)y, (float)z); | ||
3582 | sitOffset = up * (float)offset; | ||
3583 | newPos = sitTargetPos - sitOffset + SIT_TARGET_ADJUSTMENT; | ||
3041 | } | 3584 | } |
3585 | else | ||
3586 | { | ||
3587 | m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W; | ||
3588 | |||
3589 | if (Math.Abs(1.0 - m) > 0.000001) | ||
3590 | { | ||
3591 | if(m != 0) | ||
3592 | { | ||
3593 | m = 1.0 / Math.Sqrt(m); | ||
3594 | r.X *= (float)m; | ||
3595 | r.Y *= (float)m; | ||
3596 | r.Z *= (float)m; | ||
3597 | r.W *= (float)m; | ||
3598 | } | ||
3599 | else | ||
3600 | { | ||
3601 | r.X = 0.0f; | ||
3602 | r.Y = 0.0f; | ||
3603 | r.Z = 0.0f; | ||
3604 | r.W = 1.0f; | ||
3605 | m = 1.0f; | ||
3606 | } | ||
3607 | } | ||
3042 | 3608 | ||
3043 | Vector3 up = new Vector3((float)x, (float)y, (float)z); | 3609 | x = 2 * (r.X * r.Z + r.Y * r.W); |
3044 | Vector3 sitOffset = up * (float)offset; | 3610 | y = 2 * (-r.X * r.W + r.Y * r.Z); |
3611 | z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W; | ||
3612 | Vector3 up = new Vector3((float)x, (float)y, (float)z); | ||
3613 | sitOffset = up * Appearance.AvatarHeight * 0.02638f; | ||
3614 | newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; | ||
3615 | } | ||
3045 | 3616 | ||
3046 | // sitOffset is in Avatar Center coordinates: from origin to 'sitTargetPos + SIT_TARGET_ADJUSTMENT'. | ||
3047 | // So, we need to _substract_ it to get to the origin of the Avatar Center. | ||
3048 | Vector3 newPos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset; | ||
3049 | Quaternion newRot; | 3617 | Quaternion newRot; |
3050 | 3618 | ||
3051 | if (part.IsRoot) | 3619 | if (part.IsRoot) |
@@ -3078,19 +3646,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
3078 | // Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); | 3646 | // Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); |
3079 | } | 3647 | } |
3080 | 3648 | ||
3649 | part.AddSittingAvatar(this); | ||
3081 | ParentPart = part; | 3650 | ParentPart = part; |
3082 | ParentID = m_requestedSitTargetID; | 3651 | ParentID = m_requestedSitTargetID; |
3652 | |||
3653 | RemoveFromPhysicalScene(); | ||
3083 | m_AngularVelocity = Vector3.Zero; | 3654 | m_AngularVelocity = Vector3.Zero; |
3084 | Velocity = Vector3.Zero; | 3655 | Velocity = Vector3.Zero; |
3085 | RemoveFromPhysicalScene(); | ||
3086 | 3656 | ||
3087 | String sitAnimation = "SIT"; | 3657 | m_requestedSitTargetID = 0; |
3658 | |||
3659 | SendAvatarDataToAllAgents(); | ||
3660 | |||
3661 | sitAnimation = "SIT"; | ||
3088 | if (!String.IsNullOrEmpty(part.SitAnimation)) | 3662 | if (!String.IsNullOrEmpty(part.SitAnimation)) |
3089 | { | 3663 | { |
3090 | sitAnimation = part.SitAnimation; | 3664 | sitAnimation = part.SitAnimation; |
3091 | } | 3665 | } |
3092 | Animator.TrySetMovementAnimation(sitAnimation); | 3666 | // Animator.TrySetMovementAnimation(sitAnimation); |
3093 | SendAvatarDataToAllClients(); | 3667 | Animator.SetMovementAnimations("SIT"); |
3094 | TriggerScenePresenceUpdated(); | 3668 | TriggerScenePresenceUpdated(); |
3095 | } | 3669 | } |
3096 | } | 3670 | } |
@@ -3101,11 +3675,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
3101 | return; | 3675 | return; |
3102 | 3676 | ||
3103 | // m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. | 3677 | // m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. |
3104 | m_AngularVelocity = Vector3.Zero; | 3678 | sitAnimation = "SIT_GROUND_CONSTRAINED"; |
3105 | Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); | 3679 | // Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); |
3106 | TriggerScenePresenceUpdated(); | 3680 | // TriggerScenePresenceUpdated(); |
3107 | SitGround = true; | 3681 | SitGround = true; |
3108 | RemoveFromPhysicalScene(); | 3682 | RemoveFromPhysicalScene(); |
3683 | |||
3684 | m_AngularVelocity = Vector3.Zero; | ||
3685 | Velocity = Vector3.Zero; | ||
3686 | |||
3687 | Animator.SetMovementAnimations("SITGROUND"); | ||
3688 | TriggerScenePresenceUpdated(); | ||
3109 | } | 3689 | } |
3110 | 3690 | ||
3111 | /// <summary> | 3691 | /// <summary> |
@@ -3129,86 +3709,84 @@ namespace OpenSim.Region.Framework.Scenes | |||
3129 | TriggerScenePresenceUpdated(); | 3709 | TriggerScenePresenceUpdated(); |
3130 | } | 3710 | } |
3131 | 3711 | ||
3712 | public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) | ||
3713 | { | ||
3714 | Animator.avnChangeAnim(animID, addRemove, sendPack); | ||
3715 | } | ||
3716 | |||
3132 | /// <summary> | 3717 | /// <summary> |
3133 | /// Rotate the avatar to the given rotation and apply a movement in the given relative vector | 3718 | /// Rotate the avatar to the given rotation and apply a movement in the given relative vector |
3134 | /// </summary> | 3719 | /// </summary> |
3135 | /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> | 3720 | /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> |
3136 | /// <param name="thisAddSpeedModifier"> | 3721 | /// <param name="thisAddSpeedModifier"> |
3137 | /// Optional additional speed modifier for this particular add. Default is 1</param> | 3722 | /// Optional additional speed modifier for this particular add. Default is 1</param> |
3138 | public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1) | 3723 | public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1, bool breaking = false) |
3139 | { | 3724 | { |
3140 | // m_log.DebugFormat( | 3725 | // m_log.DebugFormat( |
3141 | // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}", | 3726 | // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}", |
3142 | // vec, Rotation, thisAddSpeedModifier, Name); | 3727 | // vec, Rotation, thisAddSpeedModifier, Name); |
3143 | 3728 | m_delayedStop = -1; | |
3729 | // rotate from avatar coord space to world | ||
3144 | Quaternion rot = Rotation; | 3730 | Quaternion rot = Rotation; |
3145 | if (!Flying && PresenceType != PresenceType.Npc) | 3731 | if (!Flying && PresenceType != PresenceType.Npc) |
3146 | { | 3732 | { |
3147 | // The only situation in which we care about X and Y is avatar flying. The rest of the time | 3733 | // force rotation to be around Z only, if not flying |
3148 | // these parameters are not relevant for determining avatar movement direction and cause issues such | 3734 | // needed for mouselook |
3149 | // as wrong walk speed if the camera is rotated. | ||
3150 | rot.X = 0; | 3735 | rot.X = 0; |
3151 | rot.Y = 0; | 3736 | rot.Y = 0; |
3152 | rot.Normalize(); | ||
3153 | } | 3737 | } |
3154 | 3738 | ||
3155 | Vector3 direc = vec * rot; | 3739 | Vector3 direc = vec * rot; |
3156 | direc.Normalize(); | 3740 | direc.Normalize(); |
3157 | 3741 | ||
3158 | if (Flying != FlyingOld) // add for fly velocity control | ||
3159 | { | ||
3160 | FlyingOld = Flying; // add for fly velocity control | ||
3161 | if (!Flying) | ||
3162 | WasFlying = true; // add for fly velocity control | ||
3163 | } | ||
3164 | |||
3165 | if (IsColliding) | ||
3166 | WasFlying = false; // add for fly velocity control | ||
3167 | |||
3168 | if ((vec.Z == 0f) && !Flying) | 3742 | if ((vec.Z == 0f) && !Flying) |
3169 | direc.Z = 0f; // Prevent camera WASD up. | 3743 | direc.Z = 0f; // Prevent camera WASD up. |
3170 | 3744 | ||
3171 | direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier; | 3745 | bool notmvtrgt = !m_movingToTarget || m_moveToSpeed <= 0; |
3746 | // odd rescalings | ||
3747 | if(notmvtrgt) | ||
3748 | direc *= 4.096f * SpeedModifier * thisAddSpeedModifier; | ||
3749 | else | ||
3750 | direc *= m_moveToSpeed; | ||
3172 | 3751 | ||
3173 | // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); | 3752 | // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); |
3174 | 3753 | ||
3175 | if (PhysicsActor != null) | 3754 | if (Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling |
3755 | && (PhysicsActor == null || !PhysicsActor.PIDHoverActive)) | ||
3176 | { | 3756 | { |
3177 | if (Flying) | 3757 | if (breaking) |
3178 | { | 3758 | direc.Z = -9999f; //hack to tell physics to stop on Z |
3759 | else | ||
3760 | direc = Vector3.Zero; | ||
3761 | } | ||
3762 | else if (Flying) | ||
3763 | { | ||
3764 | if (IsColliding && direc.Z < 0) | ||
3765 | // landing situation, prevent avatar moving or it may fail to land | ||
3766 | // animator will handle this condition and do the land | ||
3767 | direc = Vector3.Zero; | ||
3768 | else if(notmvtrgt) | ||
3179 | direc *= 4.0f; | 3769 | direc *= 4.0f; |
3180 | //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); | 3770 | } |
3181 | //if (controlland) | 3771 | else if (IsColliding) |
3182 | // m_log.Info("[AGENT]: landCommand"); | 3772 | { |
3183 | //if (IsColliding) | 3773 | if (direc.Z > 2.0f && notmvtrgt) // reinforce jumps |
3184 | // m_log.Info("[AGENT]: colliding"); | ||
3185 | //if (Flying && IsColliding && controlland) | ||
3186 | //{ | ||
3187 | // StopFlying(); | ||
3188 | // m_log.Info("[AGENT]: Stop Flying"); | ||
3189 | //} | ||
3190 | } | ||
3191 | if (Animator.Falling && WasFlying) // if falling from flying, disable motion add | ||
3192 | { | ||
3193 | direc *= 0.0f; | ||
3194 | } | ||
3195 | else if (!Flying && IsColliding) | ||
3196 | { | 3774 | { |
3197 | if (direc.Z > 2.0f) | 3775 | direc.Z *= 2.6f; |
3198 | { | ||
3199 | direc.Z *= 2.6f; | ||
3200 | |||
3201 | // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. | ||
3202 | // Animator.TrySetMovementAnimation("PREJUMP"); | ||
3203 | // Animator.TrySetMovementAnimation("JUMP"); | ||
3204 | } | ||
3205 | } | 3776 | } |
3777 | else if (direc.Z < 0) // on a surface moving down (pg down) only changes animation | ||
3778 | direc.Z = 0; | ||
3206 | } | 3779 | } |
3207 | 3780 | ||
3208 | // m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name); | 3781 | // m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name); |
3209 | 3782 | /* | |
3210 | // TODO: Add the force instead of only setting it to support multiple forces per frame? | 3783 | lock(m_forceToApplyLock) |
3211 | m_forceToApply = direc; | 3784 | { |
3785 | m_forceToApply = direc; | ||
3786 | m_forceToApplyValid = true; | ||
3787 | } | ||
3788 | */ | ||
3789 | TargetVelocity = direc; | ||
3212 | Animator.UpdateMovementAnimations(); | 3790 | Animator.UpdateMovementAnimations(); |
3213 | } | 3791 | } |
3214 | 3792 | ||
@@ -3216,51 +3794,116 @@ namespace OpenSim.Region.Framework.Scenes | |||
3216 | 3794 | ||
3217 | #region Overridden Methods | 3795 | #region Overridden Methods |
3218 | 3796 | ||
3797 | const float ROTATION_TOLERANCE = 0.01f; | ||
3798 | const float VELOCITY_TOLERANCE = 0.1f; | ||
3799 | const float LOWVELOCITYSQ = 0.1f; | ||
3800 | const float POSITION_LARGETOLERANCE = 5f; | ||
3801 | const float POSITION_SMALLTOLERANCE = 0.05f; | ||
3802 | |||
3219 | public override void Update() | 3803 | public override void Update() |
3220 | { | 3804 | { |
3221 | if (IsChildAgent == false) | 3805 | if(IsChildAgent || IsDeleted) |
3222 | { | 3806 | return; |
3223 | // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to | 3807 | |
3224 | // grab the latest PhysicsActor velocity, whereas m_velocity is often | 3808 | CheckForBorderCrossing(); |
3225 | // storing a requested force instead of an actual traveling velocity | ||
3226 | if (Appearance.AvatarSize != m_lastSize && !IsLoggingIn) | ||
3227 | SendAvatarDataToAllClients(); | ||
3228 | 3809 | ||
3229 | // Allow any updates for sitting avatars to that llSetPrimitiveLinkParams() can work for very | 3810 | if (IsInTransit || IsLoggingIn) |
3230 | // small increments (e.g. sit position adjusters). An alternative may be to eliminate the tolerance | 3811 | return; |
3231 | // checks on all updates but the ramifications of this would need careful consideration. | ||
3232 | bool updateClients | ||
3233 | = IsSatOnObject && (Rotation != m_lastRotation || Velocity != m_lastVelocity || m_pos != m_lastPosition); | ||
3234 | |||
3235 | if (!updateClients) | ||
3236 | updateClients | ||
3237 | = !Rotation.ApproxEquals(m_lastRotation, Scene.RootRotationUpdateTolerance) | ||
3238 | || !Velocity.ApproxEquals(m_lastVelocity, Scene.RootVelocityUpdateTolerance) | ||
3239 | || !m_pos.ApproxEquals(m_lastPosition, Scene.RootPositionUpdateTolerance); | ||
3240 | 3812 | ||
3241 | if (updateClients) | 3813 | if(m_movingToTarget) |
3814 | { | ||
3815 | m_delayedStop = -1; | ||
3816 | Vector3 control = Vector3.Zero; | ||
3817 | if(HandleMoveToTargetUpdate(1f, ref control)) | ||
3818 | AddNewMovement(control); | ||
3819 | } | ||
3820 | else if(m_delayedStop > 0) | ||
3821 | { | ||
3822 | if(IsSatOnObject) | ||
3823 | m_delayedStop = -1; | ||
3824 | else | ||
3825 | if(Util.GetTimeStampMS() > m_delayedStop) | ||
3826 | AddNewMovement(Vector3.Zero); | ||
3827 | } | ||
3828 | |||
3829 | if (Appearance.AvatarSize != m_lastSize) | ||
3830 | SendAvatarDataToAllAgents(); | ||
3831 | |||
3832 | // Send terse position update if not sitting and position, velocity, or rotation | ||
3833 | // has changed significantly from last sent update | ||
3834 | if (!IsSatOnObject) | ||
3835 | { | ||
3836 | // this does need to be more complex later | ||
3837 | Vector3 vel = Velocity; | ||
3838 | Vector3 dpos = m_pos - m_lastPosition; | ||
3839 | if( State != m_lastState || | ||
3840 | Math.Abs(vel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE || | ||
3841 | Math.Abs(vel.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE || | ||
3842 | Math.Abs(vel.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE || | ||
3843 | |||
3844 | Math.Abs(m_bodyRot.X - m_lastRotation.X) > ROTATION_TOLERANCE || | ||
3845 | Math.Abs(m_bodyRot.Y - m_lastRotation.Y) > ROTATION_TOLERANCE || | ||
3846 | Math.Abs(m_bodyRot.Z - m_lastRotation.Z) > ROTATION_TOLERANCE || | ||
3847 | |||
3848 | (vel == Vector3.Zero && m_lastVelocity != Vector3.Zero) || | ||
3849 | |||
3850 | Math.Abs(dpos.X) > POSITION_LARGETOLERANCE || | ||
3851 | Math.Abs(dpos.Y) > POSITION_LARGETOLERANCE || | ||
3852 | Math.Abs(dpos.Z) > POSITION_LARGETOLERANCE || | ||
3853 | |||
3854 | ( (Math.Abs(dpos.X) > POSITION_SMALLTOLERANCE || | ||
3855 | Math.Abs(dpos.Y) > POSITION_SMALLTOLERANCE || | ||
3856 | Math.Abs(dpos.Z) > POSITION_SMALLTOLERANCE) | ||
3857 | && vel.LengthSquared() < LOWVELOCITYSQ | ||
3858 | ) || | ||
3859 | |||
3860 | Math.Abs(CollisionPlane.X - m_lastCollisionPlane.X) > POSITION_SMALLTOLERANCE || | ||
3861 | Math.Abs(CollisionPlane.Y - m_lastCollisionPlane.Y) > POSITION_SMALLTOLERANCE || | ||
3862 | Math.Abs(CollisionPlane.W - m_lastCollisionPlane.W) > POSITION_SMALLTOLERANCE | ||
3863 | ) | ||
3242 | { | 3864 | { |
3243 | SendTerseUpdateToAllClients(); | 3865 | SendTerseUpdateToAllClients(); |
3244 | |||
3245 | // Update the "last" values | ||
3246 | m_lastPosition = m_pos; | ||
3247 | m_lastRotation = Rotation; | ||
3248 | m_lastVelocity = Velocity; | ||
3249 | } | 3866 | } |
3250 | |||
3251 | if (Scene.AllowAvatarCrossing) | ||
3252 | CheckForBorderCrossing(); | ||
3253 | |||
3254 | CheckForSignificantMovement(); // sends update to the modules. | ||
3255 | } | 3867 | } |
3868 | CheckForSignificantMovement(); | ||
3256 | } | 3869 | } |
3257 | 3870 | ||
3258 | #endregion | 3871 | #endregion |
3259 | 3872 | ||
3260 | #region Update Client(s) | 3873 | #region Update Client(s) |
3261 | 3874 | ||
3875 | public void SendUpdateToAgent(ScenePresence p) | ||
3876 | { | ||
3877 | IClientAPI remoteClient = p.ControllingClient; | ||
3878 | |||
3879 | if (remoteClient.IsActive) | ||
3880 | { | ||
3881 | //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); | ||
3882 | remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate); | ||
3883 | m_scene.StatsReporter.AddAgentUpdates(1); | ||
3884 | } | ||
3885 | } | ||
3886 | |||
3887 | public void SendFullUpdateToClient(IClientAPI remoteClient) | ||
3888 | { | ||
3889 | if (remoteClient.IsActive) | ||
3890 | { | ||
3891 | //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); | ||
3892 | remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate); | ||
3893 | m_scene.StatsReporter.AddAgentUpdates(1); | ||
3894 | } | ||
3895 | } | ||
3896 | |||
3897 | // this is diferente from SendTerseUpdateToClient | ||
3898 | // this sends bypassing entities updates | ||
3899 | public void SendAgentTerseUpdate(ISceneEntity p) | ||
3900 | { | ||
3901 | ControllingClient.SendAgentTerseUpdate(p); | ||
3902 | } | ||
3903 | |||
3262 | /// <summary> | 3904 | /// <summary> |
3263 | /// Sends a location update to the client connected to this scenePresence | 3905 | /// Sends a location update to the client connected to this scenePresence |
3906 | /// via entity updates | ||
3264 | /// </summary> | 3907 | /// </summary> |
3265 | /// <param name="remoteClient"></param> | 3908 | /// <param name="remoteClient"></param> |
3266 | public void SendTerseUpdateToClient(IClientAPI remoteClient) | 3909 | public void SendTerseUpdateToClient(IClientAPI remoteClient) |
@@ -3269,31 +3912,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3269 | // server. | 3912 | // server. |
3270 | if (remoteClient.IsActive) | 3913 | if (remoteClient.IsActive) |
3271 | { | 3914 | { |
3272 | if (Scene.RootTerseUpdatePeriod > 1) | ||
3273 | { | ||
3274 | // Console.WriteLine( | ||
3275 | // "{0} {1} {2} {3} {4} {5} for {6} to {7}", | ||
3276 | // remoteClient.AgentId, UUID, remoteClient.SceneAgent.IsChildAgent, m_terseUpdateCount, Scene.RootTerseUpdatePeriod, Velocity.ApproxEquals(Vector3.Zero, 0.001f), Name, remoteClient.Name); | ||
3277 | if (remoteClient.AgentId != UUID | ||
3278 | && !remoteClient.SceneAgent.IsChildAgent | ||
3279 | && m_terseUpdateCount % Scene.RootTerseUpdatePeriod != 0 | ||
3280 | && !Velocity.ApproxEquals(Vector3.Zero, 0.001f)) | ||
3281 | { | ||
3282 | // m_log.DebugFormat("[SCENE PRESENCE]: Discarded update from {0} to {1}, args {2} {3} {4} {5} {6} {7}", | ||
3283 | // Name, remoteClient.Name, remoteClient.AgentId, UUID, remoteClient.SceneAgent.IsChildAgent, m_terseUpdateCount, Scene.RootTerseUpdatePeriod, Velocity.ApproxEquals(Vector3.Zero, 0.001f)); | ||
3284 | |||
3285 | return; | ||
3286 | } | ||
3287 | } | ||
3288 | |||
3289 | if (Scene.ChildTerseUpdatePeriod > 1 | ||
3290 | && remoteClient.SceneAgent.IsChildAgent | ||
3291 | && m_terseUpdateCount % Scene.ChildTerseUpdatePeriod != 0 | ||
3292 | && !Velocity.ApproxEquals(Vector3.Zero, 0.001f)) | ||
3293 | return; | ||
3294 | |||
3295 | //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); | 3915 | //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); |
3296 | |||
3297 | remoteClient.SendEntityUpdate( | 3916 | remoteClient.SendEntityUpdate( |
3298 | this, | 3917 | this, |
3299 | PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | 3918 | PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity |
@@ -3303,59 +3922,51 @@ namespace OpenSim.Region.Framework.Scenes | |||
3303 | } | 3922 | } |
3304 | } | 3923 | } |
3305 | 3924 | ||
3306 | 3925 | public void SendTerseUpdateToAgent(ScenePresence p) | |
3307 | // vars to support reduced update frequency when velocity is unchanged | ||
3308 | private Vector3 lastVelocitySentToAllClients = Vector3.Zero; | ||
3309 | private Vector3 lastPositionSentToAllClients = Vector3.Zero; | ||
3310 | private int lastTerseUpdateToAllClientsTick = Util.EnvironmentTickCount(); | ||
3311 | |||
3312 | /// <summary> | ||
3313 | /// Send a location/velocity/accelleration update to all agents in scene | ||
3314 | /// </summary> | ||
3315 | public void SendTerseUpdateToAllClients() | ||
3316 | { | 3926 | { |
3317 | int currentTick = Util.EnvironmentTickCount(); | 3927 | IClientAPI remoteClient = p.ControllingClient; |
3318 | |||
3319 | // Decrease update frequency when avatar is moving but velocity is | ||
3320 | // not changing. | ||
3321 | // If there is a mismatch between distance travelled and expected | ||
3322 | // distance based on last velocity sent and velocity hasnt changed, | ||
3323 | // then send a new terse update | ||
3324 | |||
3325 | float timeSinceLastUpdate = (currentTick - lastTerseUpdateToAllClientsTick) * 0.001f; | ||
3326 | |||
3327 | Vector3 expectedPosition = lastPositionSentToAllClients + lastVelocitySentToAllClients * timeSinceLastUpdate; | ||
3328 | 3928 | ||
3329 | float distanceError = Vector3.Distance(OffsetPosition, expectedPosition); | 3929 | if (!remoteClient.IsActive) |
3930 | return; | ||
3330 | 3931 | ||
3331 | float speed = Velocity.Length(); | 3932 | if (ParcelHideThisAvatar && p.currentParcelUUID != currentParcelUUID && !p.IsViewerUIGod) |
3332 | float velocityDiff = Vector3.Distance(lastVelocitySentToAllClients, Velocity); | 3933 | return; |
3333 | 3934 | ||
3334 | // m_log.DebugFormat( | 3935 | //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); |
3335 | // "[SCENE PRESENCE]: Delta-v {0}, lastVelocity {1}, Velocity {2} for {3} in {4}", | 3936 | remoteClient.SendEntityUpdate( |
3336 | // velocidyDiff, lastVelocitySentToAllClients, Velocity, Name, Scene.Name); | 3937 | this, |
3938 | PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | ||
3939 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); | ||
3337 | 3940 | ||
3338 | // assuming 5 ms. worst case precision for timer, use 2x that | 3941 | m_scene.StatsReporter.AddAgentUpdates(1); |
3339 | // for distance error threshold | 3942 | } |
3340 | float distanceErrorThreshold = speed * 0.01f; | ||
3341 | 3943 | ||
3342 | if (speed < 0.01f // allow rotation updates if avatar position is unchanged | 3944 | public void SendTerseUpdateToAgentNF(ScenePresence p) |
3343 | || Math.Abs(distanceError) > distanceErrorThreshold | 3945 | { |
3344 | || velocityDiff > 0.01f) // did velocity change from last update? | 3946 | IClientAPI remoteClient = p.ControllingClient; |
3947 | if (remoteClient.IsActive) | ||
3345 | { | 3948 | { |
3346 | // m_log.DebugFormat( | 3949 | //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); |
3347 | // "[SCENE PRESENCE]: Update triggered with speed {0}, distanceError {1}, distanceThreshold {2}, delta-v {3} for {4} in {5}", | 3950 | remoteClient.SendEntityUpdate(this, |
3348 | // speed, distanceError, distanceErrorThreshold, velocidyDiff, Name, Scene.Name); | 3951 | PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity |
3349 | 3952 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); | |
3350 | lastVelocitySentToAllClients = Velocity; | 3953 | m_scene.StatsReporter.AddAgentUpdates(1); |
3351 | lastTerseUpdateToAllClientsTick = currentTick; | 3954 | } |
3352 | lastPositionSentToAllClients = OffsetPosition; | 3955 | } |
3353 | 3956 | ||
3354 | m_terseUpdateCount++; | 3957 | /// <summary> |
3958 | /// Send a location/velocity/accelleration update to all agents in scene | ||
3959 | /// </summary> | ||
3960 | public void SendTerseUpdateToAllClients() | ||
3961 | { | ||
3962 | m_lastState = State; | ||
3963 | m_lastPosition = m_pos; | ||
3964 | m_lastRotation = m_bodyRot; | ||
3965 | m_lastVelocity = Velocity; | ||
3966 | m_lastCollisionPlane = CollisionPlane; | ||
3355 | 3967 | ||
3356 | // Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name); | 3968 | m_scene.ForEachScenePresence(SendTerseUpdateToAgent); |
3357 | m_scene.ForEachClient(SendTerseUpdateToClient); | 3969 | // Update the "last" values |
3358 | } | ||
3359 | TriggerScenePresenceUpdated(); | 3970 | TriggerScenePresenceUpdated(); |
3360 | } | 3971 | } |
3361 | 3972 | ||
@@ -3379,89 +3990,75 @@ namespace OpenSim.Region.Framework.Scenes | |||
3379 | ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); | 3990 | ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); |
3380 | } | 3991 | } |
3381 | 3992 | ||
3382 | public void SendInitialDataToClient() | 3993 | public void SendInitialDataToMe() |
3383 | { | 3994 | { |
3384 | SentInitialDataToClient = true; | ||
3385 | |||
3386 | // Send all scene object to the new client | 3995 | // Send all scene object to the new client |
3387 | WorkManager.RunJob("SendInitialDataToClient", delegate | 3996 | SentInitialData = true; |
3997 | Util.FireAndForget(delegate | ||
3388 | { | 3998 | { |
3389 | // m_log.DebugFormat( | ||
3390 | // "[SCENE PRESENCE]: Sending initial data to {0} agent {1} in {2}, tp flags {3}", | ||
3391 | // IsChildAgent ? "child" : "root", Name, Scene.Name, m_teleportFlags); | ||
3392 | |||
3393 | // we created a new ScenePresence (a new child agent) in a fresh region. | 3999 | // we created a new ScenePresence (a new child agent) in a fresh region. |
3394 | // Request info about all the (root) agents in this region | 4000 | // Request info about all the (root) agents in this region |
3395 | // Note: This won't send data *to* other clients in that region (children don't send) | 4001 | // Note: This won't send data *to* other clients in that region (children don't send) |
3396 | SendOtherAgentsAvatarDataToClient(); | 4002 | if (m_teleportFlags <= 0) |
3397 | SendOtherAgentsAppearanceToClient(); | 4003 | { |
4004 | Scene.SendLayerData(ControllingClient); | ||
3398 | 4005 | ||
4006 | ILandChannel landch = m_scene.LandChannel; | ||
4007 | if (landch != null) | ||
4008 | { | ||
4009 | landch.sendClientInitialLandInfo(ControllingClient); | ||
4010 | } | ||
4011 | } | ||
4012 | |||
4013 | SendOtherAgentsAvatarFullToMe(); | ||
3399 | EntityBase[] entities = Scene.Entities.GetEntities(); | 4014 | EntityBase[] entities = Scene.Entities.GetEntities(); |
3400 | foreach (EntityBase e in entities) | 4015 | foreach (EntityBase e in entities) |
3401 | { | 4016 | { |
3402 | if (e != null && e is SceneObjectGroup) | 4017 | if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment) |
3403 | ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); | 4018 | ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); |
3404 | } | 4019 | } |
3405 | }, null, string.Format("SendInitialDataToClient ({0} in {1})", Name, Scene.Name), false, true); | 4020 | |
4021 | m_reprioritizationLastPosition = AbsolutePosition; | ||
4022 | m_reprioritizationLastDrawDistance = DrawDistance; | ||
4023 | m_reprioritizationLastTime = Util.EnvironmentTickCount() + 15000; // delay it | ||
4024 | m_reprioritizationBusy = false; | ||
4025 | |||
4026 | }); | ||
3406 | } | 4027 | } |
3407 | 4028 | ||
3408 | /// <summary> | 4029 | /// <summary> |
3409 | /// Do everything required once a client completes its movement into a region and becomes | 4030 | /// Send avatar full data appearance and animations for all other root agents to this agent, this agent |
3410 | /// a root agent. | 4031 | /// can be either a child or root |
3411 | /// </summary> | 4032 | /// </summary> |
3412 | private void ValidateAndSendAppearanceAndAgentData() | 4033 | public void SendOtherAgentsAvatarFullToMe() |
3413 | { | 4034 | { |
3414 | //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID); | 4035 | int count = 0; |
3415 | // Moved this into CompleteMovement to ensure that Appearance is initialized before | 4036 | m_scene.ForEachRootScenePresence(delegate(ScenePresence p) |
3416 | // the inventory arrives | ||
3417 | // m_scene.GetAvatarAppearance(ControllingClient, out Appearance); | ||
3418 | |||
3419 | bool cachedappearance = false; | ||
3420 | |||
3421 | // We have an appearance but we may not have the baked textures. Check the asset cache | ||
3422 | // to see if all the baked textures are already here. | ||
3423 | if (m_scene.AvatarFactory != null) | ||
3424 | cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this); | ||
3425 | |||
3426 | // If we aren't using a cached appearance, then clear out the baked textures | ||
3427 | if (!cachedappearance) | ||
3428 | { | 4037 | { |
3429 | Appearance.ResetAppearance(); | 4038 | // only send information about other root agents |
3430 | if (m_scene.AvatarFactory != null) | 4039 | if (p.UUID == UUID) |
3431 | m_scene.AvatarFactory.QueueAppearanceSave(UUID); | 4040 | return; |
3432 | } | ||
3433 | |||
3434 | // This agent just became root. We are going to tell everyone about it. The process of | ||
3435 | // getting other avatars information was initiated elsewhere immediately after the child circuit connected... don't do it | ||
3436 | // again here... this comes after the cached appearance check because the avatars | ||
3437 | // appearance goes into the avatar update packet | ||
3438 | SendAvatarDataToAllClients(); | ||
3439 | 4041 | ||
3440 | // This invocation always shows up in the viewer logs as an error. Is it needed? | 4042 | // get the avatar, then a kill if can't see it |
3441 | SendAppearanceToClient(this); | 4043 | p.SendInitialAvatarDataToAgent(this); |
3442 | 4044 | ||
3443 | // If we are using the the cached appearance then send it out to everyone | 4045 | if (p.ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !IsViewerUIGod) |
3444 | if (cachedappearance) | 4046 | return; |
3445 | { | ||
3446 | m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name); | ||
3447 | 4047 | ||
3448 | // If the avatars baked textures are all in the cache, then we have a | 4048 | p.SendAppearanceToAgentNF(this); |
3449 | // complete appearance... send it out, if not, then we'll send it when | 4049 | p.SendAnimPackToAgentNF(this); |
3450 | // the avatar finishes updating its appearance | 4050 | p.SendAttachmentsToAgentNF(this); |
3451 | SendAppearanceToAllOtherClients(); | 4051 | count++; |
3452 | } | 4052 | }); |
3453 | } | ||
3454 | 4053 | ||
3455 | public void SendAvatarDataToAllClients() | 4054 | m_scene.StatsReporter.AddAgentUpdates(count); |
3456 | { | ||
3457 | SendAvatarDataToAllClients(true); | ||
3458 | } | 4055 | } |
3459 | 4056 | ||
3460 | /// <summary> | 4057 | /// <summary> |
3461 | /// Send this agent's avatar data to all other root and child agents in the scene | 4058 | /// Send this agent's avatar data to all other root and child agents in the scene |
3462 | /// This agent must be root. This avatar will receive its own update. | 4059 | /// This agent must be root. This avatar will receive its own update. |
3463 | /// </summary> | 4060 | /// </summary> |
3464 | public void SendAvatarDataToAllClients(bool full) | 4061 | public void SendAvatarDataToAllAgents() |
3465 | { | 4062 | { |
3466 | //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID); | 4063 | //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID); |
3467 | // only send update from root agents to other clients; children are only "listening posts" | 4064 | // only send update from root agents to other clients; children are only "listening posts" |
@@ -3470,64 +4067,73 @@ namespace OpenSim.Region.Framework.Scenes | |||
3470 | m_log.WarnFormat( | 4067 | m_log.WarnFormat( |
3471 | "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}", | 4068 | "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}", |
3472 | Name, Scene.RegionInfo.RegionName); | 4069 | Name, Scene.RegionInfo.RegionName); |
3473 | |||
3474 | return; | 4070 | return; |
3475 | } | 4071 | } |
3476 | 4072 | ||
3477 | m_lastSize = Appearance.AvatarSize; | 4073 | m_lastSize = Appearance.AvatarSize; |
3478 | |||
3479 | int count = 0; | 4074 | int count = 0; |
4075 | |||
3480 | m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) | 4076 | m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) |
3481 | { | 4077 | { |
3482 | if (full) | 4078 | SendAvatarDataToAgent(scenePresence); |
3483 | SendAvatarDataToClient(scenePresence); | ||
3484 | else | ||
3485 | scenePresence.ControllingClient.SendAvatarDataImmediate(this); | ||
3486 | count++; | 4079 | count++; |
3487 | }); | 4080 | }); |
3488 | 4081 | ||
3489 | m_scene.StatsReporter.AddAgentUpdates(count); | 4082 | m_scene.StatsReporter.AddAgentUpdates(count); |
3490 | } | 4083 | } |
3491 | 4084 | // sends avatar object to all clients so they cross it into region | |
3492 | /// <summary> | 4085 | // then sends kills to hide |
3493 | /// Send avatar data for all other root agents to this agent, this agent | 4086 | public void SendInitialAvatarDataToAllAgents(List<ScenePresence> presences) |
3494 | /// can be either a child or root | ||
3495 | /// </summary> | ||
3496 | public void SendOtherAgentsAvatarDataToClient() | ||
3497 | { | 4087 | { |
4088 | m_lastSize = Appearance.AvatarSize; | ||
3498 | int count = 0; | 4089 | int count = 0; |
3499 | m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) | 4090 | foreach (ScenePresence p in presences) |
3500 | { | 4091 | { |
3501 | // only send information about other root agents | 4092 | p.ControllingClient.SendEntityFullUpdateImmediate(this); |
3502 | if (scenePresence.UUID == UUID) | 4093 | if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) |
3503 | return; | 4094 | // either just kill the object |
3504 | 4095 | // p.ControllingClient.SendKillObject(new List<uint> {LocalId}); | |
3505 | scenePresence.SendAvatarDataToClient(this); | 4096 | // or also attachments viewer may still know about |
3506 | count++; | 4097 | SendKillTo(p); |
3507 | }); | 4098 | count++; |
3508 | 4099 | } | |
3509 | m_scene.StatsReporter.AddAgentUpdates(count); | 4100 | m_scene.StatsReporter.AddAgentUpdates(count); |
3510 | } | 4101 | } |
3511 | 4102 | ||
4103 | public void SendInitialAvatarDataToAgent(ScenePresence p) | ||
4104 | { | ||
4105 | p.ControllingClient.SendEntityFullUpdateImmediate(this); | ||
4106 | if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) | ||
4107 | // either just kill the object | ||
4108 | // p.ControllingClient.SendKillObject(new List<uint> {LocalId}); | ||
4109 | // or also attachments viewer may still know about | ||
4110 | SendKillTo(p); | ||
4111 | } | ||
4112 | |||
3512 | /// <summary> | 4113 | /// <summary> |
3513 | /// Send avatar data to an agent. | 4114 | /// Send avatar data to an agent. |
3514 | /// </summary> | 4115 | /// </summary> |
3515 | /// <param name="avatar"></param> | 4116 | /// <param name="avatar"></param> |
3516 | public void SendAvatarDataToClient(ScenePresence avatar) | 4117 | public void SendAvatarDataToAgent(ScenePresence avatar) |
3517 | { | 4118 | { |
3518 | //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToClient from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); | 4119 | //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); |
4120 | if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && !avatar.IsViewerUIGod) | ||
4121 | return; | ||
4122 | avatar.ControllingClient.SendEntityFullUpdateImmediate(this); | ||
4123 | } | ||
3519 | 4124 | ||
3520 | avatar.ControllingClient.SendAvatarDataImmediate(this); | 4125 | public void SendAvatarDataToAgentNF(ScenePresence avatar) |
3521 | Animator.SendAnimPackToClient(avatar.ControllingClient); | 4126 | { |
4127 | avatar.ControllingClient.SendEntityFullUpdateImmediate(this); | ||
3522 | } | 4128 | } |
3523 | 4129 | ||
3524 | /// <summary> | 4130 | /// <summary> |
3525 | /// Send this agent's appearance to all other root and child agents in the scene | 4131 | /// Send this agent's appearance to all other root and child agents in the scene |
3526 | /// This agent must be root. | 4132 | /// This agent must be root. |
3527 | /// </summary> | 4133 | /// </summary> |
3528 | public void SendAppearanceToAllOtherClients() | 4134 | public void SendAppearanceToAllOtherAgents() |
3529 | { | 4135 | { |
3530 | // m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherClients: {0} {1}", Name, UUID); | 4136 | // m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID); |
3531 | 4137 | ||
3532 | // only send update from root agents to other clients; children are only "listening posts" | 4138 | // only send update from root agents to other clients; children are only "listening posts" |
3533 | if (IsChildAgent) | 4139 | if (IsChildAgent) |
@@ -3538,109 +4144,217 @@ namespace OpenSim.Region.Framework.Scenes | |||
3538 | 4144 | ||
3539 | return; | 4145 | return; |
3540 | } | 4146 | } |
3541 | 4147 | ||
3542 | int count = 0; | 4148 | int count = 0; |
3543 | m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) | 4149 | m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) |
3544 | { | 4150 | { |
3545 | // only send information to other root agents | 4151 | // only send information to other root agents |
3546 | if (scenePresence.UUID == UUID) | 4152 | if (scenePresence.UUID == UUID) |
3547 | return; | 4153 | return; |
3548 | |||
3549 | SendAppearanceToClient(scenePresence); | ||
3550 | count++; | ||
3551 | }); | ||
3552 | 4154 | ||
4155 | SendAppearanceToAgent(scenePresence); | ||
4156 | count++; | ||
4157 | }); | ||
3553 | m_scene.StatsReporter.AddAgentUpdates(count); | 4158 | m_scene.StatsReporter.AddAgentUpdates(count); |
3554 | } | 4159 | } |
3555 | 4160 | ||
3556 | /// <summary> | 4161 | public void SendAppearanceToAgent(ScenePresence avatar) |
3557 | /// Send appearance from all other root agents to this agent. this agent | ||
3558 | /// can be either root or child | ||
3559 | /// </summary> | ||
3560 | public void SendOtherAgentsAppearanceToClient() | ||
3561 | { | 4162 | { |
3562 | // m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToClient {0} {1}", Name, UUID); | 4163 | // m_log.DebugFormat( |
4164 | // "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID); | ||
4165 | if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && !avatar.IsViewerUIGod) | ||
4166 | return; | ||
4167 | SendAppearanceToAgentNF(avatar); | ||
4168 | } | ||
3563 | 4169 | ||
3564 | int count = 0; | 4170 | public void SendAppearanceToAgentNF(ScenePresence avatar) |
3565 | m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) | 4171 | { |
3566 | { | 4172 | avatar.ControllingClient.SendAppearance( |
3567 | // only send information about other root agents | 4173 | UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); |
3568 | if (scenePresence.UUID == UUID) | 4174 | } |
3569 | return; | ||
3570 | |||
3571 | scenePresence.SendAppearanceToClient(this); | ||
3572 | count++; | ||
3573 | }); | ||
3574 | 4175 | ||
3575 | m_scene.StatsReporter.AddAgentUpdates(count); | 4176 | public void SendAnimPackToAgent(ScenePresence p) |
4177 | { | ||
4178 | if (IsChildAgent || Animator == null) | ||
4179 | return; | ||
4180 | |||
4181 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) | ||
4182 | return; | ||
4183 | |||
4184 | Animator.SendAnimPackToClient(p.ControllingClient); | ||
3576 | } | 4185 | } |
3577 | 4186 | ||
3578 | /// <summary> | 4187 | public void SendAnimPackToAgent(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs) |
3579 | /// Send appearance data to an agent. | ||
3580 | /// </summary> | ||
3581 | /// <param name="avatar"></param> | ||
3582 | public void SendAppearanceToClient(ScenePresence avatar) | ||
3583 | { | 4188 | { |
3584 | // m_log.DebugFormat( | 4189 | if (IsChildAgent) |
3585 | // "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID); | 4190 | return; |
3586 | 4191 | ||
3587 | avatar.ControllingClient.SendAppearance( | 4192 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) |
3588 | UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); | 4193 | return; |
4194 | |||
4195 | p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs); | ||
4196 | } | ||
4197 | |||
4198 | public void SendAnimPackToAgentNF(ScenePresence p) | ||
4199 | { | ||
4200 | if (IsChildAgent || Animator == null) | ||
4201 | return; | ||
4202 | Animator.SendAnimPackToClient(p.ControllingClient); | ||
4203 | } | ||
4204 | |||
4205 | public void SendAnimPackToAgentNF(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs) | ||
4206 | { | ||
4207 | p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs); | ||
4208 | } | ||
4209 | |||
4210 | public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs) | ||
4211 | { | ||
4212 | if (IsChildAgent) | ||
4213 | return; | ||
3589 | 4214 | ||
3590 | 4215 | m_scene.ForEachScenePresence(delegate(ScenePresence p) | |
4216 | { | ||
4217 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) | ||
4218 | return; | ||
4219 | p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs); | ||
4220 | }); | ||
3591 | } | 4221 | } |
3592 | 4222 | ||
3593 | #endregion | 4223 | #endregion |
3594 | 4224 | ||
3595 | #region Significant Movement Method | 4225 | #region Significant Movement Method |
3596 | 4226 | ||
4227 | private void checkRePrioritization() | ||
4228 | { | ||
4229 | if(IsDeleted || !ControllingClient.IsActive) | ||
4230 | return; | ||
4231 | |||
4232 | if(!SentInitialData) | ||
4233 | { | ||
4234 | SendInitialDataToMe(); | ||
4235 | return; | ||
4236 | } | ||
4237 | |||
4238 | if(m_reprioritizationBusy) | ||
4239 | return; | ||
4240 | |||
4241 | float limit = Scene.ReprioritizationDistance; | ||
4242 | bool byDrawdistance = Scene.ObjectsCullingByDistance; | ||
4243 | if(byDrawdistance) | ||
4244 | { | ||
4245 | float minregionSize = (float)Scene.RegionInfo.RegionSizeX; | ||
4246 | if(minregionSize > (float)Scene.RegionInfo.RegionSizeY) | ||
4247 | minregionSize = (float)Scene.RegionInfo.RegionSizeY; | ||
4248 | minregionSize *= 0.5f; | ||
4249 | if(DrawDistance > minregionSize && m_reprioritizationLastDrawDistance > minregionSize) | ||
4250 | byDrawdistance = false; | ||
4251 | else | ||
4252 | byDrawdistance = (Math.Abs(DrawDistance - m_reprioritizationLastDrawDistance) > 0.5f * limit); | ||
4253 | } | ||
4254 | |||
4255 | int tdiff = Util.EnvironmentTickCountSubtract(m_reprioritizationLastTime); | ||
4256 | if(!byDrawdistance && tdiff < Scene.ReprioritizationInterval) | ||
4257 | return; | ||
4258 | // priority uses avatar position | ||
4259 | Vector3 pos = AbsolutePosition; | ||
4260 | Vector3 diff = pos - m_reprioritizationLastPosition; | ||
4261 | limit *= limit; | ||
4262 | if (!byDrawdistance && diff.LengthSquared() < limit) | ||
4263 | return; | ||
4264 | |||
4265 | m_reprioritizationBusy = true; | ||
4266 | m_reprioritizationLastPosition = pos; | ||
4267 | m_reprioritizationLastDrawDistance = DrawDistance; | ||
4268 | |||
4269 | Util.FireAndForget( | ||
4270 | o => | ||
4271 | { | ||
4272 | ControllingClient.ReprioritizeUpdates(); | ||
4273 | m_reprioritizationLastTime = Util.EnvironmentTickCount(); | ||
4274 | m_reprioritizationBusy = false; | ||
4275 | }, null, "ScenePresence.Reprioritization"); | ||
4276 | } | ||
3597 | /// <summary> | 4277 | /// <summary> |
3598 | /// This checks for a significant movement and sends a coarselocationchange update | 4278 | /// This checks for a significant movement and sends a coarselocationchange update |
3599 | /// </summary> | 4279 | /// </summary> |
3600 | protected void CheckForSignificantMovement() | 4280 | protected void CheckForSignificantMovement() |
3601 | { | 4281 | { |
3602 | if (Util.GetDistanceTo(AbsolutePosition, posLastSignificantMove) > SIGNIFICANT_MOVEMENT) | 4282 | Vector3 pos = AbsolutePosition; |
4283 | |||
4284 | Vector3 diff = pos - posLastMove; | ||
4285 | if (diff.LengthSquared() > MOVEMENT) | ||
3603 | { | 4286 | { |
3604 | posLastSignificantMove = AbsolutePosition; | 4287 | posLastMove = pos; |
3605 | m_scene.EventManager.TriggerSignificantClientMovement(this); | 4288 | m_scene.EventManager.TriggerOnClientMovement(this); |
3606 | } | 4289 | } |
3607 | 4290 | ||
3608 | // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m | 4291 | diff = pos - posLastSignificantMove; |
3609 | if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance) | 4292 | if (diff.LengthSquared() > SIGNIFICANT_MOVEMENT) |
3610 | { | 4293 | { |
3611 | m_lastChildAgentUpdatePosition = AbsolutePosition; | 4294 | posLastSignificantMove = pos; |
3612 | // m_lastChildAgentUpdateCamPosition = CameraPosition; | 4295 | m_scene.EventManager.TriggerSignificantClientMovement(this); |
4296 | } | ||
3613 | 4297 | ||
3614 | ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); | 4298 | // updates priority recalc |
3615 | cadu.ActiveGroupID = UUID.Zero.Guid; | 4299 | checkRePrioritization(); |
3616 | cadu.AgentID = UUID.Guid; | ||
3617 | cadu.alwaysrun = SetAlwaysRun; | ||
3618 | cadu.AVHeight = Appearance.AvatarHeight; | ||
3619 | cadu.cameraPosition = CameraPosition; | ||
3620 | cadu.drawdistance = DrawDistance; | ||
3621 | cadu.GroupAccess = 0; | ||
3622 | cadu.Position = AbsolutePosition; | ||
3623 | cadu.regionHandle = RegionHandle; | ||
3624 | 4300 | ||
3625 | // Throttles | 4301 | if(m_childUpdatesBusy) |
3626 | float multiplier = 1; | 4302 | return; |
3627 | int childRegions = KnownRegionCount; | ||
3628 | if (childRegions != 0) | ||
3629 | multiplier = 1f / childRegions; | ||
3630 | 4303 | ||
3631 | // Minimum throttle for a child region is 1/4 of the root region throttle | 4304 | //possible KnownRegionHandles always contains current region and this check is not needed |
3632 | if (multiplier <= 0.25f) | 4305 | int minhandles = 0; |
3633 | multiplier = 0.25f; | 4306 | if(KnownRegionHandles.Contains(RegionHandle)) |
4307 | minhandles++; | ||
3634 | 4308 | ||
3635 | cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); | 4309 | if(KnownRegionHandles.Count > minhandles) |
3636 | cadu.Velocity = Velocity; | 4310 | { |
4311 | int tdiff = Util.EnvironmentTickCountSubtract(m_lastChildUpdatesTime); | ||
4312 | if(tdiff < CHILDUPDATES_TIME) | ||
4313 | return; | ||
3637 | 4314 | ||
3638 | AgentPosition agentpos = new AgentPosition(); | 4315 | bool doUpdate = false; |
3639 | agentpos.CopyFrom(cadu, ControllingClient.SessionId); | 4316 | if(m_lastChildAgentUpdateGodLevel != GodController.ViwerUIGodLevel) |
4317 | doUpdate = true; | ||
4318 | |||
4319 | if(!doUpdate && Math.Abs(DrawDistance - m_lastChildAgentUpdateDrawDistance) > 32.0f) | ||
4320 | doUpdate = true; | ||
4321 | |||
4322 | if(!doUpdate) | ||
4323 | { | ||
4324 | diff = pos - m_lastChildAgentUpdatePosition; | ||
4325 | if (diff.LengthSquared() > CHILDUPDATES_MOVEMENT) | ||
4326 | doUpdate = true; | ||
4327 | } | ||
3640 | 4328 | ||
3641 | // Let's get this out of the update loop | 4329 | if(doUpdate) |
3642 | Util.FireAndForget( | 4330 | { |
3643 | o => m_scene.SendOutChildAgentUpdates(agentpos, this), null, "ScenePresence.SendOutChildAgentUpdates"); | 4331 | m_childUpdatesBusy = true; |
4332 | m_lastChildAgentUpdatePosition = pos; | ||
4333 | m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; | ||
4334 | m_lastChildAgentUpdateDrawDistance = DrawDistance; | ||
4335 | // m_lastChildAgentUpdateCamPosition = CameraPosition; | ||
4336 | |||
4337 | AgentPosition agentpos = new AgentPosition(); | ||
4338 | agentpos.AgentID = new UUID(UUID.Guid); | ||
4339 | agentpos.SessionID = ControllingClient.SessionId; | ||
4340 | agentpos.Size = Appearance.AvatarSize; | ||
4341 | agentpos.Center = CameraPosition; | ||
4342 | agentpos.Far = DrawDistance; | ||
4343 | agentpos.Position = AbsolutePosition; | ||
4344 | agentpos.Velocity = Velocity; | ||
4345 | agentpos.RegionHandle = RegionHandle; | ||
4346 | agentpos.GodData = GodController.State(); | ||
4347 | agentpos.Throttles = ControllingClient.GetThrottlesPacked(1); | ||
4348 | |||
4349 | // Let's get this out of the update loop | ||
4350 | Util.FireAndForget( | ||
4351 | o => | ||
4352 | { | ||
4353 | m_scene.SendOutChildAgentUpdates(agentpos, this); | ||
4354 | m_lastChildUpdatesTime = Util.EnvironmentTickCount(); | ||
4355 | m_childUpdatesBusy = false; | ||
4356 | }, null, "ScenePresence.SendOutChildAgentUpdates"); | ||
4357 | } | ||
3644 | } | 4358 | } |
3645 | } | 4359 | } |
3646 | 4360 | ||
@@ -3657,7 +4371,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3657 | protected void CheckForBorderCrossing() | 4371 | protected void CheckForBorderCrossing() |
3658 | { | 4372 | { |
3659 | // Check that we we are not a child | 4373 | // Check that we we are not a child |
3660 | if (IsChildAgent) | 4374 | if (IsChildAgent || IsInTransit) |
3661 | return; | 4375 | return; |
3662 | 4376 | ||
3663 | // If we don't have a PhysActor, we can't cross anyway | 4377 | // If we don't have a PhysActor, we can't cross anyway |
@@ -3667,79 +4381,71 @@ namespace OpenSim.Region.Framework.Scenes | |||
3667 | if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) | 4381 | if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) |
3668 | return; | 4382 | return; |
3669 | 4383 | ||
3670 | if (IsInTransit) | ||
3671 | return; | ||
3672 | |||
3673 | Vector3 pos2 = AbsolutePosition; | 4384 | Vector3 pos2 = AbsolutePosition; |
3674 | Vector3 origPosition = pos2; | ||
3675 | Vector3 vel = Velocity; | 4385 | Vector3 vel = Velocity; |
3676 | 4386 | ||
3677 | // Compute the future avatar position. | 4387 | float timeStep = 0.1f; |
3678 | // If the avatar will be crossing, we force the crossing to happen now | 4388 | pos2.X += vel.X * timeStep; |
3679 | // in the hope that this will make the avatar movement smoother when crossing. | 4389 | pos2.Y += vel.Y * timeStep; |
3680 | pos2 += vel * 0.05f; | 4390 | pos2.Z += vel.Z * timeStep; |
3681 | |||
3682 | if (m_scene.PositionIsInCurrentRegion(pos2)) | ||
3683 | return; | ||
3684 | |||
3685 | m_log.DebugFormat("{0} CheckForBorderCrossing: position outside region. {1} in {2} at pos {3}", | ||
3686 | LogHeader, Name, Scene.Name, pos2); | ||
3687 | 4391 | ||
3688 | // Disconnect from the current region | 4392 | // m_log.DebugFormat( |
3689 | bool isFlying = Flying; | 4393 | // "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}", |
3690 | RemoveFromPhysicalScene(); | 4394 | // pos2, Name, Scene.Name); |
3691 | 4395 | ||
3692 | // pos2 is the forcasted position so make that the 'current' position so the crossing | 4396 | if (Scene.PositionIsInCurrentRegion(pos2)) |
3693 | // code will move us into the newly addressed region. | 4397 | return; |
3694 | m_pos = pos2; | ||
3695 | 4398 | ||
3696 | if (CrossToNewRegion()) | 4399 | if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero) |
3697 | { | ||
3698 | AddToPhysicalScene(isFlying); | ||
3699 | } | ||
3700 | else | ||
3701 | { | 4400 | { |
3702 | // Tried to make crossing happen but it failed. | 4401 | // we don't have entity transfer module |
3703 | if (m_requestedSitTargetUUID == UUID.Zero) | 4402 | Vector3 pos = AbsolutePosition; |
3704 | { | 4403 | vel = Velocity; |
3705 | m_log.DebugFormat("{0} CheckForBorderCrossing: Crossing failed. Restoring old position.", LogHeader); | 4404 | float px = pos.X; |
3706 | 4405 | if (px < 0) | |
3707 | Velocity = Vector3.Zero; | 4406 | pos.X += vel.X * 2; |
3708 | AbsolutePosition = EnforceSanityOnPosition(origPosition); | 4407 | else if (px > m_scene.RegionInfo.RegionSizeX) |
4408 | pos.X -= vel.X * 2; | ||
4409 | |||
4410 | float py = pos.Y; | ||
4411 | if (py < 0) | ||
4412 | pos.Y += vel.Y * 2; | ||
4413 | else if (py > m_scene.RegionInfo.RegionSizeY) | ||
4414 | pos.Y -= vel.Y * 2; | ||
3709 | 4415 | ||
3710 | AddToPhysicalScene(isFlying); | 4416 | Velocity = Vector3.Zero; |
3711 | } | 4417 | m_AngularVelocity = Vector3.Zero; |
4418 | AbsolutePosition = pos; | ||
3712 | } | 4419 | } |
3713 | } | 4420 | } |
3714 | 4421 | ||
3715 | // Given a position, make sure it is within the current region. | 4422 | public void CrossToNewRegionFail() |
3716 | // If just outside some border, the returned position will be just inside the border on that side. | ||
3717 | private Vector3 EnforceSanityOnPosition(Vector3 origPosition) | ||
3718 | { | 4423 | { |
3719 | const float borderFudge = 0.1f; | 4424 | if (m_requestedSitTargetUUID == UUID.Zero) |
3720 | Vector3 ret = origPosition; | ||
3721 | |||
3722 | // Sanity checking on the position to make sure it is in the region we couldn't cross from | ||
3723 | float extentX = (float)m_scene.RegionInfo.RegionSizeX; | ||
3724 | float extentY = (float)m_scene.RegionInfo.RegionSizeY; | ||
3725 | IRegionCombinerModule combiner = m_scene.RequestModuleInterface<IRegionCombinerModule>(); | ||
3726 | if (combiner != null) | ||
3727 | { | 4425 | { |
3728 | // If a mega-region, the size could be much bigger | 4426 | bool isFlying = Flying; |
3729 | Vector2 megaExtent = combiner.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); | 4427 | RemoveFromPhysicalScene(); |
3730 | extentX = megaExtent.X; | 4428 | |
3731 | extentY = megaExtent.Y; | 4429 | Vector3 pos = AbsolutePosition; |
3732 | } | 4430 | Vector3 vel = Velocity; |
3733 | if (ret.X < 0) | 4431 | float px = pos.X; |
3734 | ret.X = borderFudge; | 4432 | if (px < 0) |
3735 | else if (ret.X >= extentX) | 4433 | pos.X += vel.X * 2; |
3736 | ret.X = extentX - borderFudge; | 4434 | else if (px > m_scene.RegionInfo.RegionSizeX) |
3737 | if (ret.Y < 0) | 4435 | pos.X -= vel.X * 2; |
3738 | ret.Y = borderFudge; | 4436 | |
3739 | else if (ret.Y >= extentY) | 4437 | float py = pos.Y; |
3740 | ret.Y = extentY - borderFudge; | 4438 | if (py < 0) |
4439 | pos.Y += vel.Y * 2; | ||
4440 | else if (py > m_scene.RegionInfo.RegionSizeY) | ||
4441 | pos.Y -= vel.Y * 2; | ||
4442 | |||
4443 | Velocity = Vector3.Zero; | ||
4444 | m_AngularVelocity = Vector3.Zero; | ||
4445 | AbsolutePosition = pos; | ||
3741 | 4446 | ||
3742 | return ret; | 4447 | AddToPhysicalScene(isFlying); |
4448 | } | ||
3743 | } | 4449 | } |
3744 | 4450 | ||
3745 | /// <summary> | 4451 | /// <summary> |
@@ -3750,62 +4456,93 @@ namespace OpenSim.Region.Framework.Scenes | |||
3750 | /// </summary> | 4456 | /// </summary> |
3751 | protected bool CrossToNewRegion() | 4457 | protected bool CrossToNewRegion() |
3752 | { | 4458 | { |
4459 | bool result = false; | ||
4460 | // parcelRegionCross(false); | ||
3753 | try | 4461 | try |
3754 | { | 4462 | { |
3755 | return m_scene.CrossAgentToNewRegion(this, Flying); | 4463 | result = m_scene.CrossAgentToNewRegion(this, Flying); |
3756 | } | 4464 | } |
3757 | catch | 4465 | catch |
3758 | { | 4466 | { |
3759 | return m_scene.CrossAgentToNewRegion(this, false); | 4467 | // result = m_scene.CrossAgentToNewRegion(this, false); |
4468 | return false; | ||
3760 | } | 4469 | } |
3761 | } | 4470 | // if(!result) |
4471 | // parcelRegionCross(true); | ||
3762 | 4472 | ||
3763 | public void Reset() | 4473 | return result; |
3764 | { | ||
3765 | // m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); | ||
3766 | |||
3767 | // Put the child agent back at the center | ||
3768 | AbsolutePosition | ||
3769 | = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70); | ||
3770 | 4474 | ||
3771 | Animator.ResetAnimations(); | ||
3772 | } | 4475 | } |
3773 | 4476 | ||
3774 | /// <summary> | 4477 | /// <summary> |
3775 | /// Computes which child agents to close when the scene presence moves to another region. | 4478 | /// Computes which child agents to close when the scene presence moves to another region. |
3776 | /// Removes those regions from m_knownRegions. | 4479 | /// Removes those regions from m_knownRegions. |
3777 | /// </summary> | 4480 | /// </summary> |
3778 | /// <param name="newRegionX">The new region's x on the map</param> | 4481 | /// <param name="newRegionHandle">The new region's handle</param> |
3779 | /// <param name="newRegionY">The new region's y on the map</param> | 4482 | /// <param name="newRegionSizeX">The new region's size x</param> |
4483 | /// <param name="newRegionSizeY">The new region's size y</param> | ||
3780 | /// <returns></returns> | 4484 | /// <returns></returns> |
3781 | public void CloseChildAgents(uint newRegionX, uint newRegionY) | 4485 | public List<ulong> GetChildAgentsToClose(ulong newRegionHandle, int newRegionSizeX, int newRegionSizeY) |
3782 | { | 4486 | { |
4487 | ulong curRegionHandle = m_scene.RegionInfo.RegionHandle; | ||
3783 | List<ulong> byebyeRegions = new List<ulong>(); | 4488 | List<ulong> byebyeRegions = new List<ulong>(); |
4489 | |||
4490 | if(newRegionHandle == curRegionHandle) //?? | ||
4491 | return byebyeRegions; | ||
4492 | |||
4493 | uint newRegionX, newRegionY; | ||
3784 | List<ulong> knownRegions = KnownRegionHandles; | 4494 | List<ulong> knownRegions = KnownRegionHandles; |
3785 | m_log.DebugFormat( | 4495 | m_log.DebugFormat( |
3786 | "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}", | 4496 | "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}", |
3787 | knownRegions.Count, Scene.RegionInfo.RegionName); | 4497 | knownRegions.Count, Scene.RegionInfo.RegionName); |
3788 | //DumpKnownRegions(); | 4498 | |
4499 | Util.RegionHandleToRegionLoc(newRegionHandle, out newRegionX, out newRegionY); | ||
4500 | uint x, y; | ||
4501 | spRegionSizeInfo regInfo; | ||
3789 | 4502 | ||
3790 | foreach (ulong handle in knownRegions) | 4503 | foreach (ulong handle in knownRegions) |
3791 | { | 4504 | { |
3792 | // Don't close the agent on this region yet | 4505 | if(newRegionY == 0) // HG |
3793 | if (handle != Scene.RegionInfo.RegionHandle) | 4506 | byebyeRegions.Add(handle); |
4507 | else if(handle == curRegionHandle) | ||
3794 | { | 4508 | { |
3795 | uint x, y; | 4509 | RegionInfo curreg = m_scene.RegionInfo; |
3796 | Util.RegionHandleToRegionLoc(handle, out x, out y); | 4510 | if (Util.IsOutsideView(255, curreg.RegionLocX, newRegionX, curreg.RegionLocY, newRegionY, |
3797 | 4511 | (int)curreg.RegionSizeX, (int)curreg.RegionSizeX, newRegionSizeX, newRegionSizeY)) | |
3798 | // m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); | ||
3799 | // m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); | ||
3800 | float dist = (float)Math.Max(Scene.DefaultDrawDistance, | ||
3801 | (float)Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY)); | ||
3802 | if (Util.IsOutsideView(dist, x, newRegionX, y, newRegionY)) | ||
3803 | { | 4512 | { |
3804 | byebyeRegions.Add(handle); | 4513 | byebyeRegions.Add(handle); |
3805 | } | 4514 | } |
3806 | } | 4515 | } |
4516 | else | ||
4517 | { | ||
4518 | Util.RegionHandleToRegionLoc(handle, out x, out y); | ||
4519 | if (m_knownChildRegionsSizeInfo.TryGetValue(handle, out regInfo)) | ||
4520 | { | ||
4521 | // if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY, | ||
4522 | // for now need to close all but first order bc RegionViewDistance it the target value not ours | ||
4523 | if (Util.IsOutsideView(255, x, newRegionX, y, newRegionY, | ||
4524 | regInfo.sizeX, regInfo.sizeY, newRegionSizeX, newRegionSizeY)) | ||
4525 | { | ||
4526 | byebyeRegions.Add(handle); | ||
4527 | } | ||
4528 | } | ||
4529 | else | ||
4530 | { | ||
4531 | // if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY, | ||
4532 | if (Util.IsOutsideView(255, x, newRegionX, y, newRegionY, | ||
4533 | (int)Constants.RegionSize, (int)Constants.RegionSize, newRegionSizeX, newRegionSizeY)) | ||
4534 | { | ||
4535 | byebyeRegions.Add(handle); | ||
4536 | } | ||
4537 | } | ||
4538 | } | ||
3807 | } | 4539 | } |
3808 | 4540 | return byebyeRegions; | |
4541 | } | ||
4542 | |||
4543 | public void CloseChildAgents(List<ulong> byebyeRegions) | ||
4544 | { | ||
4545 | byebyeRegions.Remove(Scene.RegionInfo.RegionHandle); | ||
3809 | if (byebyeRegions.Count > 0) | 4546 | if (byebyeRegions.Count > 0) |
3810 | { | 4547 | { |
3811 | m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); | 4548 | m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); |
@@ -3814,43 +4551,56 @@ namespace OpenSim.Region.Framework.Scenes | |||
3814 | string auth = string.Empty; | 4551 | string auth = string.Empty; |
3815 | if (acd != null) | 4552 | if (acd != null) |
3816 | auth = acd.SessionID.ToString(); | 4553 | auth = acd.SessionID.ToString(); |
3817 | m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions); | 4554 | m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions); |
3818 | } | 4555 | } |
3819 | 4556 | ||
3820 | foreach (ulong handle in byebyeRegions) | 4557 | foreach (ulong handle in byebyeRegions) |
3821 | { | 4558 | { |
3822 | RemoveNeighbourRegion(handle); | 4559 | RemoveNeighbourRegion(handle); |
4560 | Scene.CapsModule.DropChildSeed(UUID, handle); | ||
3823 | } | 4561 | } |
3824 | } | 4562 | } |
3825 | 4563 | ||
3826 | #endregion | 4564 | public void closeAllChildAgents() |
3827 | |||
3828 | /// <summary> | ||
3829 | /// This allows the Sim owner the abiility to kick users from their sim currently. | ||
3830 | /// It tells the client that the agent has permission to do so. | ||
3831 | /// </summary> | ||
3832 | public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus) | ||
3833 | { | 4565 | { |
3834 | if (godStatus) | 4566 | List<ulong> byebyeRegions = new List<ulong>(); |
4567 | List<ulong> knownRegions = KnownRegionHandles; | ||
4568 | foreach (ulong handle in knownRegions) | ||
3835 | { | 4569 | { |
3836 | // For now, assign god level 200 to anyone | 4570 | if (handle != Scene.RegionInfo.RegionHandle) |
3837 | // who is granted god powers, but has no god level set. | ||
3838 | // | ||
3839 | UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, agentID); | ||
3840 | if (account != null) | ||
3841 | { | 4571 | { |
3842 | if (account.UserLevel > 0) | 4572 | byebyeRegions.Add(handle); |
3843 | GodLevel = account.UserLevel; | 4573 | RemoveNeighbourRegion(handle); |
3844 | else | 4574 | Scene.CapsModule.DropChildSeed(UUID, handle); |
3845 | GodLevel = 200; | ||
3846 | } | 4575 | } |
3847 | } | 4576 | } |
3848 | else | 4577 | |
4578 | if (byebyeRegions.Count > 0) | ||
3849 | { | 4579 | { |
3850 | GodLevel = 0; | 4580 | m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); |
4581 | |||
4582 | AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID); | ||
4583 | string auth = string.Empty; | ||
4584 | if (acd != null) | ||
4585 | auth = acd.SessionID.ToString(); | ||
4586 | m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions); | ||
3851 | } | 4587 | } |
4588 | } | ||
4589 | |||
4590 | #endregion | ||
3852 | 4591 | ||
3853 | ControllingClient.SendAdminResponse(token, (uint)GodLevel); | 4592 | /// <summary> |
4593 | /// handle god level requests. | ||
4594 | /// </summary> | ||
4595 | public void GrantGodlikePowers(UUID token, bool godStatus) | ||
4596 | { | ||
4597 | if (IsNPC) | ||
4598 | return; | ||
4599 | |||
4600 | bool wasgod = IsViewerUIGod; | ||
4601 | GodController.RequestGodMode(godStatus); | ||
4602 | if (wasgod != IsViewerUIGod) | ||
4603 | parcelGodCheck(m_currentParcelUUID); | ||
3854 | } | 4604 | } |
3855 | 4605 | ||
3856 | #region Child Agent Updates | 4606 | #region Child Agent Updates |
@@ -3862,12 +4612,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
3862 | return; | 4612 | return; |
3863 | 4613 | ||
3864 | CopyFrom(cAgentData); | 4614 | CopyFrom(cAgentData); |
3865 | |||
3866 | m_updateAgentReceivedAfterTransferEvent.Set(); | 4615 | m_updateAgentReceivedAfterTransferEvent.Set(); |
3867 | } | 4616 | } |
3868 | 4617 | ||
3869 | private static Vector3 marker = new Vector3(-1f, -1f, -1f); | 4618 | private static Vector3 marker = new Vector3(-1f, -1f, -1f); |
3870 | 4619 | ||
4620 | private void RaiseUpdateThrottles() | ||
4621 | { | ||
4622 | m_scene.EventManager.TriggerThrottleUpdate(this); | ||
4623 | } | ||
4624 | |||
3871 | /// <summary> | 4625 | /// <summary> |
3872 | /// This updates important decision making data about a child agent | 4626 | /// This updates important decision making data about a child agent |
3873 | /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region | 4627 | /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region |
@@ -3877,44 +4631,59 @@ namespace OpenSim.Region.Framework.Scenes | |||
3877 | if (!IsChildAgent) | 4631 | if (!IsChildAgent) |
3878 | return; | 4632 | return; |
3879 | 4633 | ||
3880 | // m_log.DebugFormat( | 4634 | GodController.SetState(cAgentData.GodData); |
3881 | // "[SCENE PRESENCE]: ChildAgentPositionUpdate for {0} in {1}, tRegion {2},{3}, rRegion {4},{5}, pos {6}", | 4635 | |
3882 | // Name, Scene.Name, tRegionX, tRegionY, rRegionX, rRegionY, cAgentData.Position); | 4636 | RegionHandle = cAgentData.RegionHandle; |
3883 | 4637 | ||
3884 | // Find the distance (in meters) between the two regions | 4638 | //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); |
3885 | // XXX: We cannot use Util.RegionLocToHandle() here because a negative value will silently overflow the | 4639 | int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; |
3886 | // uint | 4640 | int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; |
3887 | int shiftx = (int)(((int)rRegionX - (int)tRegionX) * Constants.RegionSize); | ||
3888 | int shifty = (int)(((int)rRegionY - (int)tRegionY) * Constants.RegionSize); | ||
3889 | 4641 | ||
3890 | Vector3 offset = new Vector3(shiftx, shifty, 0f); | 4642 | Vector3 offset = new Vector3(shiftx, shifty, 0f); |
3891 | 4643 | ||
3892 | // When we get to the point of re-computing neighbors everytime this | ||
3893 | // changes, then start using the agent's drawdistance rather than the | ||
3894 | // region's draw distance. | ||
3895 | DrawDistance = cAgentData.Far; | 4644 | DrawDistance = cAgentData.Far; |
3896 | // DrawDistance = Scene.DefaultDrawDistance; | ||
3897 | 4645 | ||
3898 | if (cAgentData.Position != marker) // UGH!! | 4646 | if (cAgentData.Position != marker) // UGH!! |
3899 | m_pos = cAgentData.Position + offset; | 4647 | m_pos = cAgentData.Position + offset; |
3900 | 4648 | ||
3901 | if (Vector3.Distance(AbsolutePosition, posLastSignificantMove) >= Scene.ChildReprioritizationDistance) | 4649 | CameraPosition = cAgentData.Center + offset; |
4650 | |||
4651 | if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0) | ||
3902 | { | 4652 | { |
3903 | posLastSignificantMove = AbsolutePosition; | 4653 | // some scaling factor |
3904 | ReprioritizeUpdates(); | 4654 | float x = m_pos.X; |
4655 | if (x > m_scene.RegionInfo.RegionSizeX) | ||
4656 | x -= m_scene.RegionInfo.RegionSizeX; | ||
4657 | float y = m_pos.Y; | ||
4658 | if (y > m_scene.RegionInfo.RegionSizeY) | ||
4659 | y -= m_scene.RegionInfo.RegionSizeY; | ||
4660 | |||
4661 | x = x * x + y * y; | ||
4662 | |||
4663 | const float distScale = 0.4f / Constants.RegionSize / Constants.RegionSize; | ||
4664 | float factor = 1.0f - distScale * x; | ||
4665 | if (factor < 0.2f) | ||
4666 | factor = 0.2f; | ||
4667 | |||
4668 | ControllingClient.SetChildAgentThrottle(cAgentData.Throttles,factor); | ||
3905 | } | 4669 | } |
3906 | 4670 | ||
3907 | CameraPosition = cAgentData.Center + offset; | 4671 | if(cAgentData.ChildrenCapSeeds != null && cAgentData.ChildrenCapSeeds.Count >0) |
4672 | { | ||
4673 | if (Scene.CapsModule != null) | ||
4674 | { | ||
4675 | Scene.CapsModule.SetChildrenSeed(UUID, cAgentData.ChildrenCapSeeds); | ||
4676 | } | ||
3908 | 4677 | ||
3909 | if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0) | 4678 | KnownRegions = cAgentData.ChildrenCapSeeds; |
3910 | ControllingClient.SetChildAgentThrottle(cAgentData.Throttles); | 4679 | } |
3911 | 4680 | ||
3912 | //cAgentData.AVHeight; | 4681 | //cAgentData.AVHeight; |
3913 | RegionHandle = cAgentData.RegionHandle; | ||
3914 | //m_velocity = cAgentData.Velocity; | 4682 | //m_velocity = cAgentData.Velocity; |
4683 | checkRePrioritization(); | ||
3915 | } | 4684 | } |
3916 | 4685 | ||
3917 | public void CopyTo(AgentData cAgent) | 4686 | public void CopyTo(AgentData cAgent, bool isCrossUpdate) |
3918 | { | 4687 | { |
3919 | cAgent.CallbackURI = m_callbackURI; | 4688 | cAgent.CallbackURI = m_callbackURI; |
3920 | 4689 | ||
@@ -3930,35 +4699,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
3930 | cAgent.UpAxis = CameraUpAxis; | 4699 | cAgent.UpAxis = CameraUpAxis; |
3931 | 4700 | ||
3932 | cAgent.Far = DrawDistance; | 4701 | cAgent.Far = DrawDistance; |
4702 | cAgent.GodData = GodController.State(); | ||
3933 | 4703 | ||
3934 | // Throttles | 4704 | // Throttles |
3935 | float multiplier = 1; | 4705 | cAgent.Throttles = ControllingClient.GetThrottlesPacked(1); |
3936 | int childRegions = KnownRegionCount; | ||
3937 | if (childRegions != 0) | ||
3938 | multiplier = 1f / childRegions; | ||
3939 | |||
3940 | // Minimum throttle for a child region is 1/4 of the root region throttle | ||
3941 | if (multiplier <= 0.25f) | ||
3942 | multiplier = 0.25f; | ||
3943 | |||
3944 | cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier); | ||
3945 | 4706 | ||
3946 | cAgent.HeadRotation = m_headrotation; | 4707 | cAgent.HeadRotation = m_headrotation; |
3947 | cAgent.BodyRotation = Rotation; | 4708 | cAgent.BodyRotation = Rotation; |
3948 | cAgent.ControlFlags = (uint)m_AgentControlFlags; | 4709 | cAgent.ControlFlags = (uint)m_AgentControlFlags; |
3949 | 4710 | ||
3950 | if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) | ||
3951 | cAgent.GodLevel = (byte)GodLevel; | ||
3952 | else | ||
3953 | cAgent.GodLevel = (byte) 0; | ||
3954 | |||
3955 | cAgent.AlwaysRun = SetAlwaysRun; | 4711 | cAgent.AlwaysRun = SetAlwaysRun; |
3956 | 4712 | ||
3957 | cAgent.Appearance = new AvatarAppearance(Appearance); | 4713 | // make clear we want the all thing |
4714 | cAgent.Appearance = new AvatarAppearance(Appearance,true,true); | ||
3958 | 4715 | ||
3959 | cAgent.ParentPart = ParentUUID; | 4716 | cAgent.ParentPart = ParentUUID; |
3960 | cAgent.SitOffset = PrevSitOffset; | 4717 | cAgent.SitOffset = PrevSitOffset; |
3961 | 4718 | ||
3962 | lock (scriptedcontrols) | 4719 | lock (scriptedcontrols) |
3963 | { | 4720 | { |
3964 | ControllerData[] controls = new ControllerData[scriptedcontrols.Count]; | 4721 | ControllerData[] controls = new ControllerData[scriptedcontrols.Count]; |
@@ -3980,8 +4737,36 @@ namespace OpenSim.Region.Framework.Scenes | |||
3980 | cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; | 4737 | cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; |
3981 | cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation; | 4738 | cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation; |
3982 | 4739 | ||
4740 | cAgent.MovementAnimationOverRides = Overrides.CloneAOPairs(); | ||
4741 | |||
4742 | cAgent.MotionState = (byte)Animator.currentControlState; | ||
4743 | |||
3983 | if (Scene.AttachmentsModule != null) | 4744 | if (Scene.AttachmentsModule != null) |
3984 | Scene.AttachmentsModule.CopyAttachments(this, cAgent); | 4745 | Scene.AttachmentsModule.CopyAttachments(this, cAgent); |
4746 | |||
4747 | if(isCrossUpdate) | ||
4748 | { | ||
4749 | cAgent.CrossingFlags = crossingFlags; | ||
4750 | cAgent.CrossingFlags |= 1; | ||
4751 | cAgent.CrossExtraFlags = 0; | ||
4752 | if((LastCommands & ScriptControlled.CONTROL_LBUTTON) != 0) | ||
4753 | cAgent.CrossExtraFlags |= 1; | ||
4754 | if((LastCommands & ScriptControlled.CONTROL_ML_LBUTTON) != 0) | ||
4755 | cAgent.CrossExtraFlags |= 2; | ||
4756 | } | ||
4757 | else | ||
4758 | cAgent.CrossingFlags = 0; | ||
4759 | |||
4760 | if(isCrossUpdate) | ||
4761 | { | ||
4762 | cAgent.agentCOF = COF; | ||
4763 | cAgent.ActiveGroupID = ControllingClient.ActiveGroupId; | ||
4764 | cAgent.ActiveGroupName = ControllingClient.ActiveGroupName; | ||
4765 | if(Grouptitle == null) | ||
4766 | cAgent.ActiveGroupTitle = String.Empty; | ||
4767 | else | ||
4768 | cAgent.ActiveGroupTitle = Grouptitle; | ||
4769 | } | ||
3985 | } | 4770 | } |
3986 | 4771 | ||
3987 | private void CopyFrom(AgentData cAgent) | 4772 | private void CopyFrom(AgentData cAgent) |
@@ -3991,40 +4776,59 @@ namespace OpenSim.Region.Framework.Scenes | |||
3991 | // "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()", | 4776 | // "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()", |
3992 | // Name, m_scene.RegionInfo.RegionName, m_callbackURI); | 4777 | // Name, m_scene.RegionInfo.RegionName, m_callbackURI); |
3993 | 4778 | ||
4779 | GodController.SetState(cAgent.GodData); | ||
4780 | |||
3994 | m_pos = cAgent.Position; | 4781 | m_pos = cAgent.Position; |
3995 | m_velocity = cAgent.Velocity; | 4782 | m_velocity = cAgent.Velocity; |
3996 | CameraPosition = cAgent.Center; | 4783 | CameraPosition = cAgent.Center; |
3997 | CameraAtAxis = cAgent.AtAxis; | 4784 | CameraAtAxis = cAgent.AtAxis; |
3998 | CameraLeftAxis = cAgent.LeftAxis; | 4785 | CameraLeftAxis = cAgent.LeftAxis; |
3999 | CameraUpAxis = cAgent.UpAxis; | 4786 | CameraUpAxis = cAgent.UpAxis; |
4787 | |||
4788 | Quaternion camRot = Util.Axes2Rot(CameraAtAxis, CameraLeftAxis, CameraUpAxis); | ||
4789 | CameraRotation = camRot; | ||
4790 | |||
4000 | ParentUUID = cAgent.ParentPart; | 4791 | ParentUUID = cAgent.ParentPart; |
4001 | PrevSitOffset = cAgent.SitOffset; | 4792 | PrevSitOffset = cAgent.SitOffset; |
4002 | 4793 | ||
4003 | // When we get to the point of re-computing neighbors everytime this | 4794 | // When we get to the point of re-computing neighbors everytime this |
4004 | // changes, then start using the agent's drawdistance rather than the | 4795 | // changes, then start using the agent's drawdistance rather than the |
4005 | // region's draw distance. | 4796 | // region's draw distance. |
4006 | DrawDistance = cAgent.Far; | 4797 | DrawDistance = cAgent.Far; |
4007 | // DrawDistance = Scene.DefaultDrawDistance; | 4798 | //DrawDistance = Scene.DefaultDrawDistance; |
4799 | |||
4800 | if (cAgent.ChildrenCapSeeds != null && cAgent.ChildrenCapSeeds.Count > 0) | ||
4801 | { | ||
4802 | if (Scene.CapsModule != null) | ||
4803 | { | ||
4804 | Scene.CapsModule.SetChildrenSeed(UUID, cAgent.ChildrenCapSeeds); | ||
4805 | } | ||
4806 | KnownRegions = cAgent.ChildrenCapSeeds; | ||
4807 | } | ||
4008 | 4808 | ||
4009 | if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) | 4809 | if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) |
4010 | ControllingClient.SetChildAgentThrottle(cAgent.Throttles); | 4810 | ControllingClient.SetChildAgentThrottle(cAgent.Throttles); |
4011 | 4811 | ||
4012 | m_headrotation = cAgent.HeadRotation; | 4812 | m_headrotation = cAgent.HeadRotation; |
4013 | Rotation = cAgent.BodyRotation; | 4813 | Rotation = cAgent.BodyRotation; |
4014 | m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; | 4814 | m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; |
4015 | 4815 | ||
4016 | if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) | ||
4017 | GodLevel = cAgent.GodLevel; | ||
4018 | SetAlwaysRun = cAgent.AlwaysRun; | 4816 | SetAlwaysRun = cAgent.AlwaysRun; |
4019 | 4817 | ||
4020 | Appearance = new AvatarAppearance(cAgent.Appearance); | 4818 | Appearance = new AvatarAppearance(cAgent.Appearance); |
4819 | /* | ||
4820 | bool isFlying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); | ||
4821 | |||
4021 | if (PhysicsActor != null) | 4822 | if (PhysicsActor != null) |
4022 | { | 4823 | { |
4023 | bool isFlying = Flying; | ||
4024 | RemoveFromPhysicalScene(); | 4824 | RemoveFromPhysicalScene(); |
4025 | AddToPhysicalScene(isFlying); | 4825 | AddToPhysicalScene(isFlying); |
4026 | } | 4826 | } |
4027 | 4827 | */ | |
4828 | |||
4829 | if (Scene.AttachmentsModule != null) | ||
4830 | Scene.AttachmentsModule.CopyAttachments(cAgent, this); | ||
4831 | |||
4028 | try | 4832 | try |
4029 | { | 4833 | { |
4030 | lock (scriptedcontrols) | 4834 | lock (scriptedcontrols) |
@@ -4032,6 +4836,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4032 | if (cAgent.Controllers != null) | 4836 | if (cAgent.Controllers != null) |
4033 | { | 4837 | { |
4034 | scriptedcontrols.Clear(); | 4838 | scriptedcontrols.Clear(); |
4839 | IgnoredControls = ScriptControlled.CONTROL_ZERO; | ||
4035 | 4840 | ||
4036 | foreach (ControllerData c in cAgent.Controllers) | 4841 | foreach (ControllerData c in cAgent.Controllers) |
4037 | { | 4842 | { |
@@ -4042,40 +4847,63 @@ namespace OpenSim.Region.Framework.Scenes | |||
4042 | sc.eventControls = (ScriptControlled)c.EventControls; | 4847 | sc.eventControls = (ScriptControlled)c.EventControls; |
4043 | 4848 | ||
4044 | scriptedcontrols[sc.itemID] = sc; | 4849 | scriptedcontrols[sc.itemID] = sc; |
4850 | IgnoredControls |= sc.ignoreControls; // this is not correct, aparently only last applied should count | ||
4045 | } | 4851 | } |
4046 | } | 4852 | } |
4047 | } | 4853 | } |
4048 | } | 4854 | } |
4049 | catch { } | 4855 | catch { } |
4050 | 4856 | ||
4857 | Animator.ResetAnimations(); | ||
4858 | |||
4859 | Overrides.CopyAOPairsFrom(cAgent.MovementAnimationOverRides); | ||
4860 | |||
4051 | // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? | 4861 | // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? |
4052 | if (cAgent.Anims != null) | ||
4053 | Animator.Animations.FromArray(cAgent.Anims); | ||
4054 | if (cAgent.DefaultAnim != null) | 4862 | if (cAgent.DefaultAnim != null) |
4055 | Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); | 4863 | Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); |
4056 | if (cAgent.AnimState != null) | 4864 | if (cAgent.AnimState != null) |
4057 | Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); | 4865 | Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); |
4866 | if (cAgent.Anims != null) | ||
4867 | Animator.Animations.FromArray(cAgent.Anims); | ||
4868 | if (cAgent.MotionState != 0) | ||
4869 | Animator.currentControlState = (ScenePresenceAnimator.motionControlStates) cAgent.MotionState; | ||
4058 | 4870 | ||
4059 | if (Scene.AttachmentsModule != null) | 4871 | |
4872 | crossingFlags = cAgent.CrossingFlags; | ||
4873 | gotCrossUpdate = (crossingFlags != 0); | ||
4874 | if(gotCrossUpdate) | ||
4875 | { | ||
4876 | LastCommands &= ~(ScriptControlled.CONTROL_LBUTTON | ScriptControlled.CONTROL_ML_LBUTTON); | ||
4877 | if((cAgent.CrossExtraFlags & 1) != 0) | ||
4878 | LastCommands |= ScriptControlled.CONTROL_LBUTTON; | ||
4879 | if((cAgent.CrossExtraFlags & 2) != 0) | ||
4880 | LastCommands |= ScriptControlled.CONTROL_ML_LBUTTON; | ||
4881 | MouseDown = (cAgent.CrossExtraFlags & 3) != 0; | ||
4882 | } | ||
4883 | |||
4884 | haveGroupInformation = false; | ||
4885 | // using this as protocol detection don't want to mess with the numbers for now | ||
4886 | if(cAgent.ActiveGroupTitle != null) | ||
4060 | { | 4887 | { |
4061 | // If the JobEngine is running we can schedule this job now and continue rather than waiting for all | 4888 | haveGroupInformation = true; |
4062 | // attachments to copy, which might take a long time in the Hypergrid case as the entire inventory | 4889 | COF = cAgent.agentCOF; |
4063 | // graph is inspected for each attachments and assets possibly fetched. | 4890 | if(ControllingClient.IsGroupMember(cAgent.ActiveGroupID)) |
4064 | // | 4891 | { |
4065 | // We don't need to worry about a race condition as the job to later start the scripts is also | 4892 | ControllingClient.ActiveGroupId = cAgent.ActiveGroupID; |
4066 | // JobEngine scheduled and so will always occur after this task. | 4893 | ControllingClient.ActiveGroupName = cAgent.ActiveGroupName; |
4067 | // XXX: This will not be true if JobEngine ever gets more than one thread. | 4894 | Grouptitle = cAgent.ActiveGroupTitle; |
4068 | WorkManager.RunJob( | 4895 | ControllingClient.ActiveGroupPowers = |
4069 | "CopyAttachments", | 4896 | ControllingClient.GetGroupPowers(cAgent.ActiveGroupID); |
4070 | o => Scene.AttachmentsModule.CopyAttachments(cAgent, this), | 4897 | } |
4071 | null, | 4898 | else |
4072 | string.Format("Copy attachments for {0} entering {1}", Name, Scene.Name), | 4899 | { |
4073 | true); | 4900 | // we got a unknown active group so get what groups thinks about us |
4074 | } | 4901 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); |
4075 | 4902 | if (gm != null) | |
4076 | // This must occur after attachments are copied or scheduled to be copied, as it releases the CompleteMovement() calling thread | 4903 | gm.SendAgentGroupDataUpdate(ControllingClient); |
4077 | // originating from the client completing a teleport. Otherwise, CompleteMovement() code to restart | 4904 | } |
4078 | // script attachments can outrace this thread. | 4905 | } |
4906 | |||
4079 | lock (m_originRegionIDAccessLock) | 4907 | lock (m_originRegionIDAccessLock) |
4080 | m_originRegionID = cAgent.RegionID; | 4908 | m_originRegionID = cAgent.RegionID; |
4081 | } | 4909 | } |
@@ -4083,7 +4911,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4083 | public bool CopyAgent(out IAgentData agent) | 4911 | public bool CopyAgent(out IAgentData agent) |
4084 | { | 4912 | { |
4085 | agent = new CompleteAgentData(); | 4913 | agent = new CompleteAgentData(); |
4086 | CopyTo((AgentData)agent); | 4914 | CopyTo((AgentData)agent, false); |
4087 | return true; | 4915 | return true; |
4088 | } | 4916 | } |
4089 | 4917 | ||
@@ -4094,15 +4922,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
4094 | /// </summary> | 4922 | /// </summary> |
4095 | public void UpdateMovement() | 4923 | public void UpdateMovement() |
4096 | { | 4924 | { |
4097 | if (m_forceToApply.HasValue) | 4925 | /* |
4098 | { | 4926 | if (IsInTransit) |
4099 | Vector3 force = m_forceToApply.Value; | 4927 | return; |
4100 | 4928 | ||
4101 | Velocity = force; | 4929 | lock(m_forceToApplyLock) |
4930 | { | ||
4931 | if (m_forceToApplyValid) | ||
4932 | { | ||
4933 | Velocity = m_forceToApply; | ||
4102 | 4934 | ||
4103 | m_forceToApply = null; | 4935 | m_forceToApplyValid = false; |
4104 | TriggerScenePresenceUpdated(); | 4936 | TriggerScenePresenceUpdated(); |
4937 | } | ||
4105 | } | 4938 | } |
4939 | */ | ||
4106 | } | 4940 | } |
4107 | 4941 | ||
4108 | /// <summary> | 4942 | /// <summary> |
@@ -4124,22 +4958,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
4124 | if (Appearance.AvatarHeight == 0) | 4958 | if (Appearance.AvatarHeight == 0) |
4125 | // Appearance.SetHeight(); | 4959 | // Appearance.SetHeight(); |
4126 | Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f)); | 4960 | Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f)); |
4127 | |||
4128 | /* | ||
4129 | PhysicsActor = scene.AddAvatar( | ||
4130 | LocalId, Firstname + "." + Lastname, pVec, | ||
4131 | new Vector3(0.45f, 0.6f, Appearance.AvatarHeight), isFlying); | ||
4132 | */ | ||
4133 | 4961 | ||
4134 | PhysicsActor = m_scene.PhysicsScene.AddAvatar( | 4962 | // lock(m_forceToApplyLock) |
4135 | LocalId, Firstname + "." + Lastname, AbsolutePosition, Velocity, | 4963 | // m_forceToApplyValid = false; |
4136 | Appearance.AvatarBoxSize, isFlying); | 4964 | |
4965 | PhysicsScene scene = m_scene.PhysicsScene; | ||
4966 | Vector3 pVec = AbsolutePosition; | ||
4137 | 4967 | ||
4968 | PhysicsActor = scene.AddAvatar( | ||
4969 | LocalId, Firstname + "." + Lastname, pVec, | ||
4970 | Appearance.AvatarBoxSize,Appearance.AvatarFeetOffset, isFlying); | ||
4971 | PhysicsActor.Orientation = m_bodyRot; | ||
4138 | //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; | 4972 | //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; |
4139 | PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; | 4973 | PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; |
4140 | PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong | 4974 | PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong |
4141 | PhysicsActor.SubscribeEvents(100); | 4975 | PhysicsActor.SubscribeEvents(100); |
4142 | PhysicsActor.LocalID = LocalId; | 4976 | PhysicsActor.LocalID = LocalId; |
4977 | PhysicsActor.SetAlwaysRun = m_setAlwaysRun; | ||
4143 | } | 4978 | } |
4144 | 4979 | ||
4145 | private void OutOfBoundsCall(Vector3 pos) | 4980 | private void OutOfBoundsCall(Vector3 pos) |
@@ -4152,7 +4987,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
4152 | ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true); | 4987 | ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true); |
4153 | } | 4988 | } |
4154 | 4989 | ||
4155 | |||
4156 | /// <summary> | 4990 | /// <summary> |
4157 | /// Event called by the physics plugin to tell the avatar about a collision. | 4991 | /// Event called by the physics plugin to tell the avatar about a collision. |
4158 | /// </summary> | 4992 | /// </summary> |
@@ -4166,24 +5000,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
4166 | /// <param name="e"></param> | 5000 | /// <param name="e"></param> |
4167 | public void PhysicsCollisionUpdate(EventArgs e) | 5001 | public void PhysicsCollisionUpdate(EventArgs e) |
4168 | { | 5002 | { |
4169 | if (IsChildAgent || Animator == null) | 5003 | if (IsChildAgent) |
4170 | return; | 5004 | return; |
4171 | 5005 | ||
5006 | if(IsInTransit) | ||
5007 | return; | ||
5008 | |||
4172 | //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) | 5009 | //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) |
4173 | // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents( | 5010 | // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents( |
4174 | // as of this comment the interval is set in AddToPhysicalScene | 5011 | // as of this comment the interval is set in AddToPhysicalScene |
4175 | 5012 | ||
4176 | // if (m_updateCount > 0) | 5013 | // if (m_updateCount > 0) |
4177 | // { | 5014 | // { |
4178 | if (Animator.UpdateMovementAnimations()) | 5015 | // if (Animator != null && Animator.UpdateMovementAnimations()) |
4179 | TriggerScenePresenceUpdated(); | 5016 | // TriggerScenePresenceUpdated(); |
4180 | // m_updateCount--; | 5017 | // m_updateCount--; |
4181 | // } | 5018 | // } |
4182 | 5019 | ||
4183 | CollisionEventUpdate collisionData = (CollisionEventUpdate)e; | 5020 | CollisionEventUpdate collisionData = (CollisionEventUpdate)e; |
4184 | Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; | 5021 | Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; |
4185 | 5022 | ||
4186 | |||
4187 | // // No collisions at all means we may be flying. Update always | 5023 | // // No collisions at all means we may be flying. Update always |
4188 | // // to make falling work | 5024 | // // to make falling work |
4189 | // if (m_lastColCount != coldata.Count || coldata.Count == 0) | 5025 | // if (m_lastColCount != coldata.Count || coldata.Count == 0) |
@@ -4192,81 +5028,98 @@ namespace OpenSim.Region.Framework.Scenes | |||
4192 | // m_lastColCount = coldata.Count; | 5028 | // m_lastColCount = coldata.Count; |
4193 | // } | 5029 | // } |
4194 | 5030 | ||
4195 | CollisionPlane = Vector4.UnitW; | 5031 | if (coldata.Count != 0) |
5032 | { | ||
5033 | ContactPoint lowest; | ||
5034 | lowest.SurfaceNormal = Vector3.Zero; | ||
5035 | lowest.Position = Vector3.Zero; | ||
5036 | lowest.Position.Z = float.MaxValue; | ||
5037 | |||
5038 | foreach (ContactPoint contact in coldata.Values) | ||
5039 | { | ||
5040 | if (contact.CharacterFeet && contact.Position.Z < lowest.Position.Z) | ||
5041 | lowest = contact; | ||
5042 | } | ||
5043 | |||
5044 | if (lowest.Position.Z != float.MaxValue) | ||
5045 | { | ||
5046 | lowest.SurfaceNormal = -lowest.SurfaceNormal; | ||
5047 | CollisionPlane = new Vector4(lowest.SurfaceNormal, Vector3.Dot(lowest.Position, lowest.SurfaceNormal)); | ||
5048 | } | ||
5049 | else | ||
5050 | CollisionPlane = Vector4.UnitW; | ||
5051 | } | ||
5052 | else | ||
5053 | CollisionPlane = Vector4.UnitW; | ||
5054 | |||
5055 | RaiseCollisionScriptEvents(coldata); | ||
4196 | 5056 | ||
4197 | // Gods do not take damage and Invulnerable is set depending on parcel/region flags | 5057 | // Gods do not take damage and Invulnerable is set depending on parcel/region flags |
4198 | if (Invulnerable || GodLevel > 0) | 5058 | if (Invulnerable || IsViewerUIGod) |
4199 | return; | 5059 | return; |
4200 | 5060 | ||
4201 | // The following may be better in the ICombatModule | 5061 | // The following may be better in the ICombatModule |
4202 | // probably tweaking of the values for ground and normal prim collisions will be needed | 5062 | // probably tweaking of the values for ground and normal prim collisions will be needed |
4203 | float starthealth = Health; | 5063 | float startHealth = Health; |
4204 | uint killerObj = 0; | 5064 | if(coldata.Count > 0) |
4205 | SceneObjectPart part = null; | ||
4206 | foreach (uint localid in coldata.Keys) | ||
4207 | { | 5065 | { |
4208 | if (localid == 0) | 5066 | uint killerObj = 0; |
4209 | { | 5067 | SceneObjectPart part = null; |
4210 | part = null; | 5068 | float rvel; // relative velocity, negative on approch |
4211 | } | 5069 | foreach (uint localid in coldata.Keys) |
4212 | else | ||
4213 | { | ||
4214 | part = Scene.GetSceneObjectPart(localid); | ||
4215 | } | ||
4216 | if (part != null) | ||
4217 | { | 5070 | { |
4218 | // Ignore if it has been deleted or volume detect | 5071 | if (localid == 0) |
4219 | if (!part.ParentGroup.IsDeleted && !part.ParentGroup.IsVolumeDetect) | 5072 | { |
5073 | // 0 is the ground | ||
5074 | rvel = coldata[0].RelativeSpeed; | ||
5075 | if(rvel < -5.0f) | ||
5076 | Health -= 0.01f * rvel * rvel; | ||
5077 | } | ||
5078 | else | ||
4220 | { | 5079 | { |
4221 | if (part.ParentGroup.Damage > 0.0f) | 5080 | part = Scene.GetSceneObjectPart(localid); |
5081 | |||
5082 | if(part != null && !part.ParentGroup.IsVolumeDetect) | ||
4222 | { | 5083 | { |
4223 | // Something with damage... | 5084 | if (part.ParentGroup.Damage > 0.0f) |
4224 | Health -= part.ParentGroup.Damage; | 5085 | { |
4225 | part.ParentGroup.Scene.DeleteSceneObject(part.ParentGroup, false); | 5086 | // Something with damage... |
5087 | Health -= part.ParentGroup.Damage; | ||
5088 | part.ParentGroup.Scene.DeleteSceneObject(part.ParentGroup, false); | ||
5089 | } | ||
5090 | else | ||
5091 | { | ||
5092 | // An ordinary prim | ||
5093 | rvel = coldata[localid].RelativeSpeed; | ||
5094 | if(rvel < -5.0f) | ||
5095 | { | ||
5096 | Health -= 0.005f * rvel * rvel; | ||
5097 | } | ||
5098 | } | ||
4226 | } | 5099 | } |
4227 | else | 5100 | else |
4228 | { | 5101 | { |
4229 | // An ordinary prim | 5102 | |
4230 | if (coldata[localid].PenetrationDepth >= 0.10f) | ||
4231 | Health -= coldata[localid].PenetrationDepth * 5.0f; | ||
4232 | } | 5103 | } |
4233 | } | 5104 | } |
4234 | } | ||
4235 | else | ||
4236 | { | ||
4237 | // 0 is the ground | ||
4238 | // what about collisions with other avatars? | ||
4239 | if (localid == 0 && coldata[localid].PenetrationDepth >= 0.10f) | ||
4240 | Health -= coldata[localid].PenetrationDepth * 5.0f; | ||
4241 | } | ||
4242 | |||
4243 | 5105 | ||
4244 | if (Health <= 0.0f) | 5106 | if (Health <= 0.0f) |
4245 | { | 5107 | { |
4246 | if (localid != 0) | 5108 | if (localid != 0) |
4247 | killerObj = localid; | 5109 | killerObj = localid; |
4248 | } | 5110 | } |
4249 | //m_log.Debug("[AVATAR]: Collision with localid: " + localid.ToString() + " at depth: " + coldata[localid].ToString()); | ||
4250 | } | ||
4251 | //Health = 100; | ||
4252 | if (!Invulnerable) | ||
4253 | { | ||
4254 | if (starthealth != Health) | ||
4255 | { | ||
4256 | ControllingClient.SendHealth(Health); | ||
4257 | } | 5111 | } |
5112 | |||
4258 | if (Health <= 0) | 5113 | if (Health <= 0) |
4259 | { | 5114 | { |
4260 | m_scene.EventManager.TriggerAvatarKill(killerObj, this); | ||
4261 | } | ||
4262 | if (starthealth == Health && Health < 100.0f) | ||
4263 | { | ||
4264 | Health += 0.03f; | ||
4265 | if (Health > 100.0f) | ||
4266 | Health = 100.0f; | ||
4267 | ControllingClient.SendHealth(Health); | 5115 | ControllingClient.SendHealth(Health); |
5116 | m_scene.EventManager.TriggerAvatarKill(killerObj, this); | ||
5117 | return; | ||
4268 | } | 5118 | } |
4269 | } | 5119 | } |
5120 | |||
5121 | if(Math.Abs(Health - startHealth) > 1.0) | ||
5122 | ControllingClient.SendHealth(Health); | ||
4270 | } | 5123 | } |
4271 | 5124 | ||
4272 | public void setHealthWithUpdate(float health) | 5125 | public void setHealthWithUpdate(float health) |
@@ -4280,25 +5133,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
4280 | // Clear known regions | 5133 | // Clear known regions |
4281 | KnownRegions = new Dictionary<ulong, string>(); | 5134 | KnownRegions = new Dictionary<ulong, string>(); |
4282 | 5135 | ||
4283 | lock (m_reprioritization_timer) | ||
4284 | { | ||
4285 | m_reprioritization_timer.Enabled = false; | ||
4286 | m_reprioritization_timer.Elapsed -= new ElapsedEventHandler(Reprioritize); | ||
4287 | } | ||
4288 | |||
4289 | // I don't get it but mono crashes when you try to dispose of this timer, | 5136 | // I don't get it but mono crashes when you try to dispose of this timer, |
4290 | // unsetting the elapsed callback should be enough to allow for cleanup however. | 5137 | // unsetting the elapsed callback should be enough to allow for cleanup however. |
4291 | // m_reprioritizationTimer.Dispose(); | 5138 | // m_reprioritizationTimer.Dispose(); |
4292 | 5139 | ||
4293 | RemoveFromPhysicalScene(); | 5140 | RemoveFromPhysicalScene(); |
4294 | 5141 | ||
4295 | m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; | 5142 | m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; |
5143 | RemoveClientEvents(); | ||
4296 | 5144 | ||
4297 | // if (Animator != null) | 5145 | // if (Animator != null) |
4298 | // Animator.Close(); | 5146 | // Animator.Close(); |
4299 | Animator = null; | 5147 | Animator = null; |
4300 | 5148 | ||
5149 | scriptedcontrols.Clear(); | ||
5150 | ControllingClient = null; | ||
4301 | LifecycleState = ScenePresenceState.Removed; | 5151 | LifecycleState = ScenePresenceState.Removed; |
5152 | IsDeleted = true; | ||
5153 | m_updateAgentReceivedAfterTransferEvent.Dispose(); | ||
5154 | m_updateAgentReceivedAfterTransferEvent = null; | ||
4302 | } | 5155 | } |
4303 | 5156 | ||
4304 | public void AddAttachment(SceneObjectGroup gobj) | 5157 | public void AddAttachment(SceneObjectGroup gobj) |
@@ -4311,6 +5164,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
4311 | 5164 | ||
4312 | m_attachments.Add(gobj); | 5165 | m_attachments.Add(gobj); |
4313 | } | 5166 | } |
5167 | |||
5168 | IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); | ||
5169 | if (bakedModule != null) | ||
5170 | bakedModule.UpdateMeshAvatar(m_uuid); | ||
4314 | } | 5171 | } |
4315 | 5172 | ||
4316 | /// <summary> | 5173 | /// <summary> |
@@ -4343,7 +5200,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4343 | } | 5200 | } |
4344 | } | 5201 | } |
4345 | } | 5202 | } |
4346 | 5203 | ||
4347 | return attachments; | 5204 | return attachments; |
4348 | } | 5205 | } |
4349 | 5206 | ||
@@ -4474,6 +5331,287 @@ namespace OpenSim.Region.Framework.Scenes | |||
4474 | return validated; | 5331 | return validated; |
4475 | } | 5332 | } |
4476 | 5333 | ||
5334 | public void SendAttachmentsToAllAgents() | ||
5335 | { | ||
5336 | lock (m_attachments) | ||
5337 | { | ||
5338 | foreach (SceneObjectGroup sog in m_attachments) | ||
5339 | { | ||
5340 | m_scene.ForEachScenePresence(delegate(ScenePresence p) | ||
5341 | { | ||
5342 | if (p != this && sog.HasPrivateAttachmentPoint) | ||
5343 | return; | ||
5344 | |||
5345 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) | ||
5346 | return; | ||
5347 | |||
5348 | SendTerseUpdateToAgentNF(p); | ||
5349 | SendAttachmentFullUpdateToAgentNF(sog, p); | ||
5350 | }); | ||
5351 | } | ||
5352 | } | ||
5353 | } | ||
5354 | |||
5355 | // send attachments to a client without filters except for huds | ||
5356 | // for now they are checked in several places down the line... | ||
5357 | public void SendAttachmentsToAgentNF(ScenePresence p) | ||
5358 | { | ||
5359 | SendTerseUpdateToAgentNF(p); | ||
5360 | // SendAvatarDataToAgentNF(this); | ||
5361 | lock (m_attachments) | ||
5362 | { | ||
5363 | foreach (SceneObjectGroup sog in m_attachments) | ||
5364 | { | ||
5365 | SendAttachmentFullUpdateToAgentNF(sog, p); | ||
5366 | } | ||
5367 | } | ||
5368 | } | ||
5369 | |||
5370 | public void SendAttachmentFullUpdateToAgentNF(SceneObjectGroup sog, ScenePresence p) | ||
5371 | { | ||
5372 | if (p != this && sog.HasPrivateAttachmentPoint) | ||
5373 | return; | ||
5374 | |||
5375 | SceneObjectPart[] parts = sog.Parts; | ||
5376 | SceneObjectPart rootpart = sog.RootPart; | ||
5377 | |||
5378 | p.ControllingClient.SendEntityUpdate(rootpart, PrimUpdateFlags.FullUpdate); | ||
5379 | |||
5380 | for (int i = 0; i < parts.Length; i++) | ||
5381 | { | ||
5382 | SceneObjectPart part = parts[i]; | ||
5383 | if (part == rootpart) | ||
5384 | continue; | ||
5385 | p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate); | ||
5386 | } | ||
5387 | } | ||
5388 | |||
5389 | public void SendAttachmentScheduleUpdate(SceneObjectGroup sog) | ||
5390 | { | ||
5391 | if (IsChildAgent || IsInTransit) | ||
5392 | return; | ||
5393 | |||
5394 | SceneObjectPart[] origparts = sog.Parts; | ||
5395 | SceneObjectPart[] parts = new SceneObjectPart[origparts.Length]; | ||
5396 | PrimUpdateFlags[] flags = new PrimUpdateFlags[origparts.Length]; | ||
5397 | |||
5398 | SceneObjectPart rootpart = sog.RootPart; | ||
5399 | UpdateRequired rootreq = sog.RootPart.UpdateFlag; | ||
5400 | |||
5401 | int j = 0; | ||
5402 | bool allterse = true; | ||
5403 | for (int i = 0; i < origparts.Length; i++) | ||
5404 | { | ||
5405 | if (origparts[i] != rootpart) | ||
5406 | { | ||
5407 | switch (origparts[i].UpdateFlag) | ||
5408 | { | ||
5409 | case UpdateRequired.NONE: | ||
5410 | break; | ||
5411 | |||
5412 | case UpdateRequired.TERSE: | ||
5413 | flags[j] = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | ||
5414 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; | ||
5415 | parts[j] = origparts[i]; | ||
5416 | j++; | ||
5417 | break; | ||
5418 | |||
5419 | case UpdateRequired.FULL: | ||
5420 | flags[j] = PrimUpdateFlags.FullUpdate; | ||
5421 | allterse = false; | ||
5422 | parts[j] = origparts[i]; | ||
5423 | j++; | ||
5424 | break; | ||
5425 | } | ||
5426 | } | ||
5427 | origparts[i].UpdateFlag = 0; | ||
5428 | } | ||
5429 | |||
5430 | if (j == 0 && rootreq == UpdateRequired.NONE) | ||
5431 | return; | ||
5432 | |||
5433 | PrimUpdateFlags rootflag = PrimUpdateFlags.FullUpdate; | ||
5434 | |||
5435 | if (rootreq != UpdateRequired.FULL && allterse) | ||
5436 | { | ||
5437 | rootflag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | ||
5438 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; | ||
5439 | } | ||
5440 | |||
5441 | int nparts = j; | ||
5442 | |||
5443 | ControllingClient.SendEntityUpdate(rootpart, rootflag); | ||
5444 | |||
5445 | for (int i = 0; i < nparts; i++) | ||
5446 | { | ||
5447 | ControllingClient.SendEntityUpdate(parts[i], flags[i]); | ||
5448 | } | ||
5449 | |||
5450 | if (sog.HasPrivateAttachmentPoint) | ||
5451 | return; | ||
5452 | |||
5453 | List<ScenePresence> allPresences = m_scene.GetScenePresences(); | ||
5454 | foreach (ScenePresence p in allPresences) | ||
5455 | { | ||
5456 | if (p == this) | ||
5457 | continue; | ||
5458 | |||
5459 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) | ||
5460 | continue; | ||
5461 | |||
5462 | p.ControllingClient.SendEntityUpdate(rootpart, rootflag); | ||
5463 | |||
5464 | for (int i = 0; i < nparts; i++) | ||
5465 | { | ||
5466 | p.ControllingClient.SendEntityUpdate(parts[i], flags[i]); | ||
5467 | } | ||
5468 | } | ||
5469 | } | ||
5470 | |||
5471 | public void SendAttachmentUpdate(SceneObjectGroup sog, UpdateRequired UpdateFlag) | ||
5472 | { | ||
5473 | if (IsChildAgent || IsInTransit) | ||
5474 | return; | ||
5475 | |||
5476 | PrimUpdateFlags flag; | ||
5477 | switch (UpdateFlag) | ||
5478 | { | ||
5479 | case UpdateRequired.TERSE: | ||
5480 | flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | ||
5481 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; | ||
5482 | break; | ||
5483 | |||
5484 | case UpdateRequired.FULL: | ||
5485 | flag = PrimUpdateFlags.FullUpdate; | ||
5486 | break; | ||
5487 | |||
5488 | default: | ||
5489 | return; | ||
5490 | } | ||
5491 | |||
5492 | SceneObjectPart[] parts = sog.Parts; | ||
5493 | SceneObjectPart rootpart = sog.RootPart; | ||
5494 | |||
5495 | // rootpart.UpdateFlag = 0; | ||
5496 | |||
5497 | ControllingClient.SendEntityUpdate(rootpart, flag); | ||
5498 | |||
5499 | for (int i = 0; i < parts.Length; i++) | ||
5500 | { | ||
5501 | SceneObjectPart part = parts[i]; | ||
5502 | if (part == rootpart) | ||
5503 | continue; | ||
5504 | ControllingClient.SendEntityUpdate(part, flag); | ||
5505 | // part.UpdateFlag = 0; | ||
5506 | } | ||
5507 | |||
5508 | if (sog.HasPrivateAttachmentPoint) | ||
5509 | return; | ||
5510 | |||
5511 | List<ScenePresence> allPresences = m_scene.GetScenePresences(); | ||
5512 | foreach (ScenePresence p in allPresences) | ||
5513 | { | ||
5514 | if (p == this) | ||
5515 | continue; | ||
5516 | |||
5517 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) | ||
5518 | continue; | ||
5519 | |||
5520 | p.ControllingClient.SendEntityUpdate(rootpart, flag); | ||
5521 | |||
5522 | for (int i = 0; i < parts.Length; i++) | ||
5523 | { | ||
5524 | SceneObjectPart part = parts[i]; | ||
5525 | if (part == rootpart) | ||
5526 | continue; | ||
5527 | p.ControllingClient.SendEntityUpdate(part, flag); | ||
5528 | } | ||
5529 | } | ||
5530 | } | ||
5531 | |||
5532 | public void SendAttachmentScheduleUpdate(SceneObjectPart part) | ||
5533 | { | ||
5534 | if (IsChildAgent || IsInTransit) | ||
5535 | return; | ||
5536 | |||
5537 | |||
5538 | PrimUpdateFlags flag; | ||
5539 | switch (part.UpdateFlag) | ||
5540 | { | ||
5541 | case UpdateRequired.TERSE: | ||
5542 | flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | ||
5543 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; | ||
5544 | break; | ||
5545 | |||
5546 | case UpdateRequired.FULL: | ||
5547 | flag = PrimUpdateFlags.FullUpdate; | ||
5548 | break; | ||
5549 | |||
5550 | default: | ||
5551 | return; | ||
5552 | } | ||
5553 | |||
5554 | part.UpdateFlag = 0; | ||
5555 | |||
5556 | ControllingClient.SendEntityUpdate(part, flag); | ||
5557 | |||
5558 | if (part.ParentGroup.HasPrivateAttachmentPoint) | ||
5559 | return; | ||
5560 | |||
5561 | List<ScenePresence> allPresences = m_scene.GetScenePresences(); | ||
5562 | foreach (ScenePresence p in allPresences) | ||
5563 | { | ||
5564 | if (p == this) | ||
5565 | continue; | ||
5566 | |||
5567 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) | ||
5568 | continue; | ||
5569 | |||
5570 | p.ControllingClient.SendEntityUpdate(part, flag); | ||
5571 | } | ||
5572 | } | ||
5573 | |||
5574 | |||
5575 | public void SendAttachmentUpdate(SceneObjectPart part, UpdateRequired UpdateFlag) | ||
5576 | { | ||
5577 | if (IsChildAgent || IsInTransit) | ||
5578 | return; | ||
5579 | |||
5580 | PrimUpdateFlags flag; | ||
5581 | switch (UpdateFlag) | ||
5582 | { | ||
5583 | case UpdateRequired.TERSE: | ||
5584 | flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | ||
5585 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; | ||
5586 | break; | ||
5587 | |||
5588 | case UpdateRequired.FULL: | ||
5589 | flag = PrimUpdateFlags.FullUpdate; | ||
5590 | break; | ||
5591 | |||
5592 | default: | ||
5593 | return; | ||
5594 | } | ||
5595 | |||
5596 | // part.UpdateFlag = 0; | ||
5597 | |||
5598 | ControllingClient.SendEntityUpdate(part, flag); | ||
5599 | |||
5600 | if (part.ParentGroup.HasPrivateAttachmentPoint) | ||
5601 | return; | ||
5602 | |||
5603 | List<ScenePresence> allPresences = m_scene.GetScenePresences(); | ||
5604 | foreach (ScenePresence p in allPresences) | ||
5605 | { | ||
5606 | if (p == this) | ||
5607 | continue; | ||
5608 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) | ||
5609 | continue; | ||
5610 | |||
5611 | p.ControllingClient.SendEntityUpdate(part, flag); | ||
5612 | } | ||
5613 | } | ||
5614 | |||
4477 | /// <summary> | 5615 | /// <summary> |
4478 | /// Send a script event to this scene presence's attachments | 5616 | /// Send a script event to this scene presence's attachments |
4479 | /// </summary> | 5617 | /// </summary> |
@@ -4530,10 +5668,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
4530 | } | 5668 | } |
4531 | } | 5669 | } |
4532 | 5670 | ||
5671 | CameraData physActor_OnPhysicsRequestingCameraData() | ||
5672 | { | ||
5673 | return new CameraData | ||
5674 | { | ||
5675 | Valid = true, | ||
5676 | MouseLook = this.m_mouseLook, | ||
5677 | CameraRotation = this.CameraRotation, | ||
5678 | CameraAtAxis = this.CameraAtAxis | ||
5679 | }; | ||
5680 | } | ||
5681 | |||
4533 | public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID) | 5682 | public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID) |
4534 | { | 5683 | { |
4535 | SceneObjectPart p = m_scene.GetSceneObjectPart(Obj_localID); | 5684 | SceneObjectPart part = m_scene.GetSceneObjectPart(Obj_localID); |
4536 | if (p == null) | 5685 | if (part == null) |
4537 | return; | 5686 | return; |
4538 | 5687 | ||
4539 | ControllingClient.SendTakeControls(controls, false, false); | 5688 | ControllingClient.SendTakeControls(controls, false, false); |
@@ -4543,7 +5692,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4543 | obj.ignoreControls = ScriptControlled.CONTROL_ZERO; | 5692 | obj.ignoreControls = ScriptControlled.CONTROL_ZERO; |
4544 | obj.eventControls = ScriptControlled.CONTROL_ZERO; | 5693 | obj.eventControls = ScriptControlled.CONTROL_ZERO; |
4545 | 5694 | ||
4546 | obj.objectID = p.ParentGroup.UUID; | 5695 | obj.objectID = part.ParentGroup.UUID; |
4547 | obj.itemID = Script_item_UUID; | 5696 | obj.itemID = Script_item_UUID; |
4548 | if (pass_on == 0 && accept == 0) | 5697 | if (pass_on == 0 && accept == 0) |
4549 | { | 5698 | { |
@@ -4562,7 +5711,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
4562 | { | 5711 | { |
4563 | IgnoredControls = ScriptControlled.CONTROL_ZERO; | 5712 | IgnoredControls = ScriptControlled.CONTROL_ZERO; |
4564 | obj.eventControls = (ScriptControlled)controls; | 5713 | obj.eventControls = (ScriptControlled)controls; |
4565 | obj.ignoreControls = ScriptControlled.CONTROL_ZERO; | ||
4566 | } | 5714 | } |
4567 | 5715 | ||
4568 | lock (scriptedcontrols) | 5716 | lock (scriptedcontrols) |
@@ -4571,19 +5719,52 @@ namespace OpenSim.Region.Framework.Scenes | |||
4571 | { | 5719 | { |
4572 | IgnoredControls &= ~(ScriptControlled)controls; | 5720 | IgnoredControls &= ~(ScriptControlled)controls; |
4573 | if (scriptedcontrols.ContainsKey(Script_item_UUID)) | 5721 | if (scriptedcontrols.ContainsKey(Script_item_UUID)) |
4574 | scriptedcontrols.Remove(Script_item_UUID); | 5722 | RemoveScriptFromControlNotifications(Script_item_UUID, part); |
4575 | } | 5723 | } |
4576 | else | 5724 | else |
4577 | { | 5725 | { |
4578 | scriptedcontrols[Script_item_UUID] = obj; | 5726 | AddScriptToControlNotifications(Script_item_UUID, part, ref obj); |
4579 | } | 5727 | } |
4580 | } | 5728 | } |
4581 | 5729 | ||
4582 | ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true); | 5730 | ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true); |
4583 | } | 5731 | } |
4584 | 5732 | ||
5733 | private void AddScriptToControlNotifications(OpenMetaverse.UUID Script_item_UUID, SceneObjectPart part, ref ScriptControllers obj) | ||
5734 | { | ||
5735 | scriptedcontrols[Script_item_UUID] = obj; | ||
5736 | |||
5737 | PhysicsActor physActor = part.ParentGroup.RootPart.PhysActor; | ||
5738 | if (physActor != null) | ||
5739 | { | ||
5740 | physActor.OnPhysicsRequestingCameraData -= physActor_OnPhysicsRequestingCameraData; | ||
5741 | physActor.OnPhysicsRequestingCameraData += physActor_OnPhysicsRequestingCameraData; | ||
5742 | } | ||
5743 | } | ||
5744 | |||
5745 | private void RemoveScriptFromControlNotifications(OpenMetaverse.UUID Script_item_UUID, SceneObjectPart part) | ||
5746 | { | ||
5747 | scriptedcontrols.Remove(Script_item_UUID); | ||
5748 | |||
5749 | if (part != null) | ||
5750 | { | ||
5751 | PhysicsActor physActor = part.ParentGroup.RootPart.PhysActor; | ||
5752 | if (physActor != null) | ||
5753 | { | ||
5754 | physActor.OnPhysicsRequestingCameraData -= physActor_OnPhysicsRequestingCameraData; | ||
5755 | } | ||
5756 | } | ||
5757 | } | ||
5758 | |||
4585 | public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID) | 5759 | public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID) |
4586 | { | 5760 | { |
5761 | foreach (ScriptControllers c in scriptedcontrols.Values) | ||
5762 | { | ||
5763 | SceneObjectGroup sog = m_scene.GetSceneObjectGroup(c.objectID); | ||
5764 | if(sog != null && !sog.IsDeleted && sog.RootPart.PhysActor != null) | ||
5765 | sog.RootPart.PhysActor.OnPhysicsRequestingCameraData -= physActor_OnPhysicsRequestingCameraData; | ||
5766 | } | ||
5767 | |||
4587 | IgnoredControls = ScriptControlled.CONTROL_ZERO; | 5768 | IgnoredControls = ScriptControlled.CONTROL_ZERO; |
4588 | lock (scriptedcontrols) | 5769 | lock (scriptedcontrols) |
4589 | { | 5770 | { |
@@ -4592,7 +5773,36 @@ namespace OpenSim.Region.Framework.Scenes | |||
4592 | ControllingClient.SendTakeControls(int.MaxValue, false, false); | 5773 | ControllingClient.SendTakeControls(int.MaxValue, false, false); |
4593 | } | 5774 | } |
4594 | 5775 | ||
4595 | private void UnRegisterSeatControls(UUID obj) | 5776 | public void HandleRevokePermissions(UUID objectID, uint permissions ) |
5777 | { | ||
5778 | |||
5779 | // still skeleton code | ||
5780 | if((permissions & (16 | 0x8000 )) == 0) //PERMISSION_TRIGGER_ANIMATION | PERMISSION_OVERRIDE_ANIMATIONS | ||
5781 | return; | ||
5782 | if(objectID == m_scene.RegionInfo.RegionID) // for all objects | ||
5783 | { | ||
5784 | |||
5785 | } | ||
5786 | else | ||
5787 | { | ||
5788 | SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); | ||
5789 | if(part != null) | ||
5790 | { | ||
5791 | |||
5792 | } | ||
5793 | } | ||
5794 | } | ||
5795 | |||
5796 | public void ClearControls() | ||
5797 | { | ||
5798 | IgnoredControls = ScriptControlled.CONTROL_ZERO; | ||
5799 | lock (scriptedcontrols) | ||
5800 | { | ||
5801 | scriptedcontrols.Clear(); | ||
5802 | } | ||
5803 | } | ||
5804 | |||
5805 | public void UnRegisterSeatControls(UUID obj) | ||
4596 | { | 5806 | { |
4597 | List<UUID> takers = new List<UUID>(); | 5807 | List<UUID> takers = new List<UUID>(); |
4598 | 5808 | ||
@@ -4610,17 +5820,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
4610 | public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) | 5820 | public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) |
4611 | { | 5821 | { |
4612 | ScriptControllers takecontrols; | 5822 | ScriptControllers takecontrols; |
5823 | SceneObjectPart part = m_scene.GetSceneObjectPart(Obj_localID); | ||
4613 | 5824 | ||
4614 | lock (scriptedcontrols) | 5825 | lock (scriptedcontrols) |
4615 | { | 5826 | { |
4616 | if (scriptedcontrols.TryGetValue(Script_item_UUID, out takecontrols)) | 5827 | if (scriptedcontrols.TryGetValue(Script_item_UUID, out takecontrols)) |
4617 | { | 5828 | { |
4618 | ScriptControlled sctc = takecontrols.eventControls; | 5829 | ScriptControlled sctc = takecontrols.eventControls; |
4619 | 5830 | ||
4620 | ControllingClient.SendTakeControls((int)sctc, false, false); | 5831 | ControllingClient.SendTakeControls((int)sctc, false, false); |
4621 | ControllingClient.SendTakeControls((int)sctc, true, false); | 5832 | ControllingClient.SendTakeControls((int)sctc, true, false); |
4622 | 5833 | ||
4623 | scriptedcontrols.Remove(Script_item_UUID); | 5834 | RemoveScriptFromControlNotifications(Script_item_UUID, part); |
4624 | IgnoredControls = ScriptControlled.CONTROL_ZERO; | 5835 | IgnoredControls = ScriptControlled.CONTROL_ZERO; |
4625 | foreach (ScriptControllers scData in scriptedcontrols.Values) | 5836 | foreach (ScriptControllers scData in scriptedcontrols.Values) |
4626 | { | 5837 | { |
@@ -4639,46 +5850,38 @@ namespace OpenSim.Region.Framework.Scenes | |||
4639 | if (scriptedcontrols.Count <= 0) | 5850 | if (scriptedcontrols.Count <= 0) |
4640 | return; | 5851 | return; |
4641 | 5852 | ||
4642 | ScriptControlled allflags = ScriptControlled.CONTROL_ZERO; | 5853 | ScriptControlled allflags; |
4643 | 5854 | // convert mouse from edge to level | |
4644 | if (MouseDown) | 5855 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || |
5856 | (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0) | ||
4645 | { | 5857 | { |
4646 | allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON); | 5858 | allflags = ScriptControlled.CONTROL_ZERO; |
4647 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0) | ||
4648 | { | ||
4649 | allflags = ScriptControlled.CONTROL_ZERO; | ||
4650 | MouseDown = true; | ||
4651 | } | ||
4652 | } | 5859 | } |
4653 | 5860 | else // recover last state of mouse | |
5861 | allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON); | ||
5862 | |||
4654 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0) | 5863 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0) |
4655 | { | ||
4656 | allflags |= ScriptControlled.CONTROL_ML_LBUTTON; | 5864 | allflags |= ScriptControlled.CONTROL_ML_LBUTTON; |
4657 | MouseDown = true; | 5865 | |
4658 | } | ||
4659 | |||
4660 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0) | 5866 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0) |
4661 | { | ||
4662 | allflags |= ScriptControlled.CONTROL_LBUTTON; | 5867 | allflags |= ScriptControlled.CONTROL_LBUTTON; |
4663 | MouseDown = true; | 5868 | |
4664 | } | ||
4665 | |||
4666 | // find all activated controls, whether the scripts are interested in them or not | 5869 | // find all activated controls, whether the scripts are interested in them or not |
4667 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0) | 5870 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0) |
4668 | { | 5871 | { |
4669 | allflags |= ScriptControlled.CONTROL_FWD; | 5872 | allflags |= ScriptControlled.CONTROL_FWD; |
4670 | } | 5873 | } |
4671 | 5874 | ||
4672 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0) | 5875 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0) |
4673 | { | 5876 | { |
4674 | allflags |= ScriptControlled.CONTROL_BACK; | 5877 | allflags |= ScriptControlled.CONTROL_BACK; |
4675 | } | 5878 | } |
4676 | 5879 | ||
4677 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0) | 5880 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0) |
4678 | { | 5881 | { |
4679 | allflags |= ScriptControlled.CONTROL_UP; | 5882 | allflags |= ScriptControlled.CONTROL_UP; |
4680 | } | 5883 | } |
4681 | 5884 | ||
4682 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0) | 5885 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0) |
4683 | { | 5886 | { |
4684 | allflags |= ScriptControlled.CONTROL_DOWN; | 5887 | allflags |= ScriptControlled.CONTROL_DOWN; |
@@ -4688,17 +5891,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
4688 | { | 5891 | { |
4689 | allflags |= ScriptControlled.CONTROL_LEFT; | 5892 | allflags |= ScriptControlled.CONTROL_LEFT; |
4690 | } | 5893 | } |
4691 | 5894 | ||
4692 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0) | 5895 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0) |
4693 | { | 5896 | { |
4694 | allflags |= ScriptControlled.CONTROL_RIGHT; | 5897 | allflags |= ScriptControlled.CONTROL_RIGHT; |
4695 | } | 5898 | } |
4696 | 5899 | ||
4697 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) | 5900 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) |
4698 | { | 5901 | { |
4699 | allflags |= ScriptControlled.CONTROL_ROT_RIGHT; | 5902 | allflags |= ScriptControlled.CONTROL_ROT_RIGHT; |
4700 | } | 5903 | } |
4701 | 5904 | ||
4702 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) | 5905 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) |
4703 | { | 5906 | { |
4704 | allflags |= ScriptControlled.CONTROL_ROT_LEFT; | 5907 | allflags |= ScriptControlled.CONTROL_ROT_LEFT; |
@@ -4711,7 +5914,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4711 | { | 5914 | { |
4712 | UUID scriptUUID = kvp.Key; | 5915 | UUID scriptUUID = kvp.Key; |
4713 | ScriptControllers scriptControlData = kvp.Value; | 5916 | ScriptControllers scriptControlData = kvp.Value; |
4714 | 5917 | ||
4715 | ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us | 5918 | ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us |
4716 | ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle | 5919 | ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle |
4717 | ScriptControlled localChange = localHeld ^ localLast; // the changed bits | 5920 | ScriptControlled localChange = localHeld ^ localLast; // the changed bits |
@@ -4723,8 +5926,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
4723 | } | 5926 | } |
4724 | } | 5927 | } |
4725 | } | 5928 | } |
4726 | 5929 | ||
4727 | LastCommands = allflags; | 5930 | LastCommands = allflags; |
5931 | MouseDown = (allflags & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON)) != 0; | ||
4728 | } | 5932 | } |
4729 | } | 5933 | } |
4730 | 5934 | ||
@@ -4765,191 +5969,252 @@ namespace OpenSim.Region.Framework.Scenes | |||
4765 | return flags; | 5969 | return flags; |
4766 | } | 5970 | } |
4767 | 5971 | ||
4768 | private void ReprioritizeUpdates() | 5972 | // returns true it local teleport allowed and sets the destiny position into pos |
5973 | |||
5974 | private bool CheckLocalTPLandingPoint(ref Vector3 pos) | ||
4769 | { | 5975 | { |
4770 | if (Scene.IsReprioritizationEnabled && Scene.UpdatePrioritizationScheme != UpdatePrioritizationSchemes.Time) | 5976 | // Never constrain lures |
5977 | if ((TeleportFlags & TeleportFlags.ViaLure) != 0) | ||
5978 | return true; | ||
5979 | |||
5980 | if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport) | ||
5981 | return true; | ||
5982 | |||
5983 | // do not constrain gods and estate managers | ||
5984 | if(m_scene.Permissions.IsGod(m_uuid) || | ||
5985 | m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) | ||
5986 | return true; | ||
5987 | |||
5988 | // will teleport to a telehub spawn point or landpoint if that results in getting closer to target | ||
5989 | // if not the local teleport fails. | ||
5990 | |||
5991 | float currDistanceSQ = Vector3.DistanceSquared(AbsolutePosition, pos); | ||
5992 | |||
5993 | // first check telehub | ||
5994 | |||
5995 | UUID TelehubObjectID = m_scene.RegionInfo.RegionSettings.TelehubObject; | ||
5996 | if ( TelehubObjectID != UUID.Zero) | ||
4771 | { | 5997 | { |
4772 | lock (m_reprioritization_timer) | 5998 | SceneObjectGroup telehubSOG = m_scene.GetSceneObjectGroup(TelehubObjectID); |
5999 | if(telehubSOG != null) | ||
4773 | { | 6000 | { |
4774 | if (!m_reprioritizing) | 6001 | Vector3 spawnPos; |
4775 | m_reprioritization_timer.Enabled = m_reprioritizing = true; | 6002 | float spawnDistSQ; |
6003 | |||
6004 | SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray(); | ||
6005 | if(spawnPoints.Length == 0) | ||
6006 | { | ||
6007 | spawnPos = new Vector3(128.0f, 128.0f, pos.Z); | ||
6008 | spawnDistSQ = Vector3.DistanceSquared(spawnPos, pos); | ||
6009 | } | ||
4776 | else | 6010 | else |
4777 | m_reprioritization_called = true; | 6011 | { |
4778 | } | 6012 | Vector3 hubPos = telehubSOG.AbsolutePosition; |
4779 | } | 6013 | Quaternion hubRot = telehubSOG.GroupRotation; |
4780 | } | ||
4781 | 6014 | ||
4782 | private void Reprioritize(object sender, ElapsedEventArgs e) | 6015 | spawnPos = spawnPoints[0].GetLocation(hubPos, hubRot); |
4783 | { | 6016 | spawnDistSQ = Vector3.DistanceSquared(spawnPos, pos); |
4784 | ControllingClient.ReprioritizeUpdates(); | ||
4785 | 6017 | ||
4786 | lock (m_reprioritization_timer) | 6018 | float testDistSQ; |
4787 | { | 6019 | Vector3 testSpawnPos; |
4788 | m_reprioritization_timer.Enabled = m_reprioritizing = m_reprioritization_called; | 6020 | for(int i = 1; i< spawnPoints.Length; i++) |
4789 | m_reprioritization_called = false; | 6021 | { |
6022 | testSpawnPos = spawnPoints[i].GetLocation(hubPos, hubRot); | ||
6023 | testDistSQ = Vector3.DistanceSquared(testSpawnPos, pos); | ||
6024 | |||
6025 | if(testDistSQ < spawnDistSQ) | ||
6026 | { | ||
6027 | spawnPos = testSpawnPos; | ||
6028 | spawnDistSQ = testDistSQ; | ||
6029 | } | ||
6030 | } | ||
6031 | } | ||
6032 | if (currDistanceSQ < spawnDistSQ) | ||
6033 | { | ||
6034 | // we are already close | ||
6035 | ControllingClient.SendAlertMessage("Can't teleport closer to destination"); | ||
6036 | return false; | ||
6037 | } | ||
6038 | else | ||
6039 | { | ||
6040 | pos = spawnPos; | ||
6041 | return true; | ||
6042 | } | ||
6043 | } | ||
4790 | } | 6044 | } |
4791 | } | ||
4792 | 6045 | ||
4793 | private void CheckLandingPoint(ref Vector3 pos) | 6046 | ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); |
4794 | { | ||
4795 | // Never constrain lures | ||
4796 | if ((TeleportFlags & TeleportFlags.ViaLure) != 0) | ||
4797 | return; | ||
4798 | 6047 | ||
4799 | if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport) | 6048 | if (land.LandData.LandingType != (byte)LandingType.LandingPoint |
4800 | return; | 6049 | || land.LandData.OwnerID == m_uuid) |
6050 | return true; | ||
4801 | 6051 | ||
4802 | ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); | 6052 | Vector3 landLocation = land.LandData.UserLocation; |
6053 | if(landLocation == Vector3.Zero) | ||
6054 | return true; | ||
4803 | 6055 | ||
4804 | if (land.LandData.LandingType == (byte)LandingType.LandingPoint && | 6056 | if (currDistanceSQ < Vector3.DistanceSquared(landLocation, pos)) |
4805 | land.LandData.UserLocation != Vector3.Zero && | ||
4806 | land.LandData.OwnerID != m_uuid && | ||
4807 | (!m_scene.Permissions.IsGod(m_uuid)) && | ||
4808 | (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid))) | ||
4809 | { | 6057 | { |
4810 | float curr = Vector3.Distance(AbsolutePosition, pos); | 6058 | ControllingClient.SendAlertMessage("Can't teleport closer to destination"); |
4811 | if (Vector3.Distance(land.LandData.UserLocation, pos) < curr) | 6059 | return false; |
4812 | pos = land.LandData.UserLocation; | ||
4813 | else | ||
4814 | ControllingClient.SendAlertMessage("Can't teleport closer to destination"); | ||
4815 | } | 6060 | } |
6061 | |||
6062 | pos = land.LandData.UserLocation; | ||
6063 | return true; | ||
4816 | } | 6064 | } |
4817 | 6065 | ||
4818 | private void CheckAndAdjustTelehub(SceneObjectGroup telehub, ref Vector3 pos) | 6066 | const TeleportFlags TeleHubTPFlags = TeleportFlags.ViaLogin |
6067 | | TeleportFlags.ViaHGLogin | TeleportFlags.ViaLocation; | ||
6068 | |||
6069 | private bool CheckAndAdjustTelehub(SceneObjectGroup telehub, ref Vector3 pos, ref bool positionChanged) | ||
4819 | { | 6070 | { |
4820 | if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == | 6071 | // forcing telehubs on any tp that reachs this |
4821 | (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) || | 6072 | if ((m_teleportFlags & TeleHubTPFlags) != 0 || |
4822 | (m_scene.TelehubAllowLandmarks == true ? false : ((m_teleportFlags & TeleportFlags.ViaLandmark) != 0 )) || | 6073 | (m_scene.TelehubAllowLandmarks == true ? false : ((m_teleportFlags & TeleportFlags.ViaLandmark) != 0 ))) |
4823 | (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || | ||
4824 | (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0) | ||
4825 | { | 6074 | { |
6075 | ILandObject land; | ||
6076 | Vector3 teleHubPosition = telehub.AbsolutePosition; | ||
4826 | 6077 | ||
4827 | if (GodLevel < 200 && | 6078 | SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray(); |
4828 | ((!m_scene.Permissions.IsGod(m_uuid) && | 6079 | if(spawnPoints.Length == 0) |
4829 | !m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) || | ||
4830 | (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || | ||
4831 | (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)) | ||
4832 | { | 6080 | { |
4833 | SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray(); | 6081 | land = m_scene.LandChannel.GetLandObject(teleHubPosition.X,teleHubPosition.Y); |
4834 | if (spawnPoints.Length == 0) | 6082 | if(land != null) |
4835 | { | 6083 | { |
4836 | if(m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) | 6084 | pos = teleHubPosition; |
4837 | { | 6085 | if(land.IsEitherBannedOrRestricted(UUID)) |
4838 | pos.X = 128.0f; | 6086 | return false; |
4839 | pos.Y = 128.0f; | 6087 | positionChanged = true; |
4840 | } | 6088 | return true; |
4841 | return; | ||
4842 | } | 6089 | } |
6090 | else | ||
6091 | return false; | ||
6092 | } | ||
4843 | 6093 | ||
4844 | int index; | 6094 | int index; |
4845 | bool selected = false; | 6095 | int tries; |
4846 | 6096 | bool selected = false; | |
4847 | switch (m_scene.SpawnPointRouting) | 6097 | bool validhub = false; |
4848 | { | 6098 | Vector3 spawnPosition; |
4849 | case "random": | ||
4850 | 6099 | ||
4851 | if (spawnPoints.Length == 0) | 6100 | Quaternion teleHubRotation = telehub.GroupRotation; |
4852 | return; | ||
4853 | do | ||
4854 | { | ||
4855 | index = Util.RandomClass.Next(spawnPoints.Length - 1); | ||
4856 | |||
4857 | Vector3 spawnPosition = spawnPoints[index].GetLocation( | ||
4858 | telehub.AbsolutePosition, | ||
4859 | telehub.GroupRotation | ||
4860 | ); | ||
4861 | // SpawnPoint sp = spawnPoints[index]; | ||
4862 | 6101 | ||
4863 | ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y); | 6102 | switch(m_scene.SpawnPointRouting) |
6103 | { | ||
6104 | case "random": | ||
6105 | tries = spawnPoints.Length; | ||
6106 | if(tries < 3) // no much sense in random with a few points when there same can have bans | ||
6107 | goto case "sequence"; | ||
6108 | do | ||
6109 | { | ||
6110 | index = Util.RandomClass.Next(spawnPoints.Length - 1); | ||
4864 | 6111 | ||
4865 | if (land == null || land.IsEitherBannedOrRestricted(UUID)) | 6112 | spawnPosition = spawnPoints[index].GetLocation(teleHubPosition, teleHubRotation); |
4866 | selected = false; | 6113 | land = m_scene.LandChannel.GetLandObject(spawnPosition.X,spawnPosition.Y); |
4867 | else | 6114 | if(land != null && !land.IsEitherBannedOrRestricted(UUID)) |
4868 | selected = true; | 6115 | selected = true; |
4869 | 6116 | ||
4870 | } while ( selected == false); | 6117 | } while(selected == false && --tries > 0 ); |
4871 | 6118 | ||
4872 | pos = spawnPoints[index].GetLocation( | 6119 | if(tries <= 0) |
4873 | telehub.AbsolutePosition, | 6120 | goto case "sequence"; |
4874 | telehub.GroupRotation | ||
4875 | ); | ||
4876 | return; | ||
4877 | 6121 | ||
4878 | case "sequence": | 6122 | pos = spawnPosition; |
6123 | return true; | ||
4879 | 6124 | ||
4880 | do | 6125 | case "sequence": |
6126 | tries = spawnPoints.Length; | ||
6127 | selected = false; | ||
6128 | validhub = false; | ||
6129 | do | ||
6130 | { | ||
6131 | index = m_scene.SpawnPoint(); | ||
6132 | spawnPosition = spawnPoints[index].GetLocation(teleHubPosition, teleHubRotation); | ||
6133 | land = m_scene.LandChannel.GetLandObject(spawnPosition.X,spawnPosition.Y); | ||
6134 | if(land != null) | ||
4881 | { | 6135 | { |
4882 | index = m_scene.SpawnPoint(); | 6136 | validhub = true; |
4883 | 6137 | if(land.IsEitherBannedOrRestricted(UUID)) | |
4884 | Vector3 spawnPosition = spawnPoints[index].GetLocation( | ||
4885 | telehub.AbsolutePosition, | ||
4886 | telehub.GroupRotation | ||
4887 | ); | ||
4888 | // SpawnPoint sp = spawnPoints[index]; | ||
4889 | |||
4890 | ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y); | ||
4891 | if (land == null || land.IsEitherBannedOrRestricted(UUID)) | ||
4892 | selected = false; | 6138 | selected = false; |
4893 | else | 6139 | else |
4894 | selected = true; | 6140 | selected = true; |
6141 | } | ||
4895 | 6142 | ||
4896 | } while (selected == false); | 6143 | } while(selected == false && --tries > 0); |
4897 | 6144 | ||
4898 | pos = spawnPoints[index].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); | 6145 | if(!validhub) |
4899 | ; | 6146 | return false; |
4900 | return; | ||
4901 | 6147 | ||
4902 | default: | 6148 | pos = spawnPosition; |
4903 | case "closest": | ||
4904 | 6149 | ||
4905 | float distance = 9999; | 6150 | if(!selected) |
4906 | int closest = -1; | 6151 | return false; |
4907 | 6152 | positionChanged = true; | |
4908 | for (int i = 0; i < spawnPoints.Length; i++) | 6153 | return true; |
4909 | { | ||
4910 | Vector3 spawnPosition = spawnPoints[i].GetLocation( | ||
4911 | telehub.AbsolutePosition, | ||
4912 | telehub.GroupRotation | ||
4913 | ); | ||
4914 | Vector3 offset = spawnPosition - pos; | ||
4915 | float d = Vector3.Mag(offset); | ||
4916 | if (d >= distance) | ||
4917 | continue; | ||
4918 | ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y); | ||
4919 | if (land == null) | ||
4920 | continue; | ||
4921 | if (land.IsEitherBannedOrRestricted(UUID)) | ||
4922 | continue; | ||
4923 | distance = d; | ||
4924 | closest = i; | ||
4925 | } | ||
4926 | if (closest == -1) | ||
4927 | return; | ||
4928 | |||
4929 | pos = spawnPoints[closest].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); | ||
4930 | return; | ||
4931 | 6154 | ||
4932 | } | 6155 | default: |
6156 | case "closest": | ||
6157 | float distancesq = float.MaxValue; | ||
6158 | int closest = -1; | ||
6159 | validhub = false; | ||
6160 | |||
6161 | for(int i = 0; i < spawnPoints.Length; i++) | ||
6162 | { | ||
6163 | spawnPosition = spawnPoints[i].GetLocation(teleHubPosition, teleHubRotation); | ||
6164 | Vector3 offset = spawnPosition - pos; | ||
6165 | float dsq = offset.LengthSquared(); | ||
6166 | land = m_scene.LandChannel.GetLandObject(spawnPosition.X,spawnPosition.Y); | ||
6167 | if(land == null) | ||
6168 | continue; | ||
6169 | |||
6170 | validhub = true; | ||
6171 | if(land.IsEitherBannedOrRestricted(UUID)) | ||
6172 | continue; | ||
6173 | |||
6174 | if(dsq >= distancesq) | ||
6175 | continue; | ||
6176 | distancesq = dsq; | ||
6177 | closest = i; | ||
6178 | } | ||
6179 | |||
6180 | if(!validhub) | ||
6181 | return false; | ||
6182 | |||
6183 | if(closest < 0) | ||
6184 | { | ||
6185 | pos = spawnPoints[0].GetLocation(teleHubPosition, teleHubRotation); | ||
6186 | positionChanged = true; | ||
6187 | return false; | ||
6188 | } | ||
6189 | |||
6190 | pos = spawnPoints[closest].GetLocation(teleHubPosition, teleHubRotation); | ||
6191 | positionChanged = true; | ||
6192 | return true; | ||
4933 | } | 6193 | } |
4934 | } | 6194 | } |
6195 | return false; | ||
4935 | } | 6196 | } |
4936 | 6197 | ||
6198 | const TeleportFlags adicionalLandPointFlags = TeleportFlags.ViaLandmark | | ||
6199 | TeleportFlags.ViaLocation | TeleportFlags.ViaHGLogin; | ||
6200 | |||
4937 | // Modify landing point based on possible banning, telehubs or parcel restrictions. | 6201 | // Modify landing point based on possible banning, telehubs or parcel restrictions. |
4938 | private void CheckAndAdjustLandingPoint(ref Vector3 pos) | 6202 | // This is the behavior in OpenSim for a very long time, different from SL |
6203 | private bool CheckAndAdjustLandingPoint_OS(ref Vector3 pos, ref Vector3 lookat, ref bool positionChanged) | ||
4939 | { | 6204 | { |
4940 | string reason; | 6205 | string reason; |
4941 | 6206 | ||
4942 | // Honor bans | 6207 | // Honor bans |
4943 | if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y)) | 6208 | if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y)) |
4944 | return; | 6209 | return false; |
4945 | 6210 | ||
4946 | SceneObjectGroup telehub = null; | 6211 | SceneObjectGroup telehub = null; |
4947 | if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) | 6212 | if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) |
4948 | { | 6213 | { |
4949 | if (!m_scene.RegionInfo.EstateSettings.AllowDirectTeleport) | 6214 | if (!m_scene.RegionInfo.EstateSettings.AllowDirectTeleport) |
4950 | { | 6215 | { |
4951 | CheckAndAdjustTelehub(telehub, ref pos); | 6216 | CheckAndAdjustTelehub(telehub, ref pos, ref positionChanged); |
4952 | return; | 6217 | return true; |
4953 | } | 6218 | } |
4954 | } | 6219 | } |
4955 | 6220 | ||
@@ -4964,27 +6229,84 @@ namespace OpenSim.Region.Framework.Scenes | |||
4964 | // to ignore them. | 6229 | // to ignore them. |
4965 | if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == | 6230 | if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == |
4966 | (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) || | 6231 | (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) || |
4967 | (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 || | 6232 | (m_teleportFlags & adicionalLandPointFlags) != 0) |
4968 | (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || | ||
4969 | (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0) | ||
4970 | { | 6233 | { |
4971 | // Don't restrict gods, estate managers, or land owners to | 6234 | // Don't restrict gods, estate managers, or land owners to |
4972 | // the TP point. This behaviour mimics agni. | 6235 | // the TP point. This behaviour mimics agni. |
4973 | if (land.LandData.LandingType == (byte)LandingType.LandingPoint && | 6236 | if (land.LandData.LandingType == (byte)LandingType.LandingPoint && |
4974 | land.LandData.UserLocation != Vector3.Zero && | 6237 | land.LandData.UserLocation != Vector3.Zero && |
4975 | GodLevel < 200 && | 6238 | !IsViewerUIGod && |
4976 | ((land.LandData.OwnerID != m_uuid && | 6239 | ((land.LandData.OwnerID != m_uuid && |
4977 | !m_scene.Permissions.IsGod(m_uuid) && | 6240 | !m_scene.Permissions.IsGod(m_uuid) && |
4978 | !m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) || | 6241 | !m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) || |
4979 | (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || | 6242 | (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || |
4980 | (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)) | 6243 | (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)) |
4981 | { | 6244 | { |
4982 | pos = land.LandData.UserLocation; | 6245 | pos = land.LandData.UserLocation; |
6246 | positionChanged = true; | ||
4983 | } | 6247 | } |
4984 | } | 6248 | } |
4985 | 6249 | ||
4986 | land.SendLandUpdateToClient(ControllingClient); | 6250 | land.SendLandUpdateToClient(ControllingClient); |
4987 | } | 6251 | } |
6252 | |||
6253 | return true; | ||
6254 | } | ||
6255 | |||
6256 | // Modify landing point based on telehubs or parcel restrictions. | ||
6257 | // This is a behavior coming from AVN, somewhat mimicking SL | ||
6258 | private bool CheckAndAdjustLandingPoint_SL(ref Vector3 pos, ref Vector3 lookat, ref bool positionChanged) | ||
6259 | { | ||
6260 | string reason; | ||
6261 | |||
6262 | // dont mess with gods | ||
6263 | if(IsGod) | ||
6264 | return true; | ||
6265 | |||
6266 | // respect region owner and managers | ||
6267 | // if(m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) | ||
6268 | // return true; | ||
6269 | |||
6270 | if (!m_scene.RegionInfo.EstateSettings.AllowDirectTeleport) | ||
6271 | { | ||
6272 | SceneObjectGroup telehub = null; | ||
6273 | if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) | ||
6274 | { | ||
6275 | if(CheckAndAdjustTelehub(telehub, ref pos, ref positionChanged)) | ||
6276 | return true; | ||
6277 | } | ||
6278 | } | ||
6279 | |||
6280 | // Honor bans, actually we don't honour them | ||
6281 | if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y)) | ||
6282 | return false; | ||
6283 | |||
6284 | ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); | ||
6285 | if (land != null) | ||
6286 | { | ||
6287 | if (Scene.DebugTeleporting) | ||
6288 | TeleportFlagsDebug(); | ||
6289 | |||
6290 | // If we come in via login, landmark or map, we want to | ||
6291 | // honor landing points. If we come in via Lure, we want | ||
6292 | // to ignore them. | ||
6293 | if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == | ||
6294 | (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) | ||
6295 | || (m_teleportFlags & adicionalLandPointFlags) != 0) | ||
6296 | { | ||
6297 | if (land.LandData.LandingType == (byte)LandingType.LandingPoint && | ||
6298 | land.LandData.UserLocation != Vector3.Zero ) | ||
6299 | // && | ||
6300 | // land.LandData.OwnerID != m_uuid ) | ||
6301 | { | ||
6302 | pos = land.LandData.UserLocation; | ||
6303 | if(land.LandData.UserLookAt != Vector3.Zero) | ||
6304 | lookat = land.LandData.UserLookAt; | ||
6305 | positionChanged = true; | ||
6306 | } | ||
6307 | } | ||
6308 | } | ||
6309 | return true; | ||
4988 | } | 6310 | } |
4989 | 6311 | ||
4990 | private DetectedObject CreateDetObject(SceneObjectPart obj) | 6312 | private DetectedObject CreateDetObject(SceneObjectPart obj) |
@@ -4998,6 +6320,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4998 | detobj.velVector = obj.Velocity; | 6320 | detobj.velVector = obj.Velocity; |
4999 | detobj.colliderType = 0; | 6321 | detobj.colliderType = 0; |
5000 | detobj.groupUUID = obj.GroupID; | 6322 | detobj.groupUUID = obj.GroupID; |
6323 | detobj.linkNumber = 0; | ||
5001 | 6324 | ||
5002 | return detobj; | 6325 | return detobj; |
5003 | } | 6326 | } |
@@ -5011,8 +6334,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
5011 | detobj.posVector = av.AbsolutePosition; | 6334 | detobj.posVector = av.AbsolutePosition; |
5012 | detobj.rotQuat = av.Rotation; | 6335 | detobj.rotQuat = av.Rotation; |
5013 | detobj.velVector = av.Velocity; | 6336 | detobj.velVector = av.Velocity; |
5014 | detobj.colliderType = 0; | 6337 | detobj.colliderType = av.IsNPC ? 0x20 : 0x1; // OpenSim\Region\ScriptEngine\Shared\Helpers.cs |
6338 | if(av.IsSatOnObject) | ||
6339 | detobj.colliderType |= 0x4; //passive | ||
6340 | else if(detobj.velVector != Vector3.Zero) | ||
6341 | detobj.colliderType |= 0x2; //active | ||
5015 | detobj.groupUUID = av.ControllingClient.ActiveGroupId; | 6342 | detobj.groupUUID = av.ControllingClient.ActiveGroupId; |
6343 | detobj.linkNumber = 0; | ||
5016 | 6344 | ||
5017 | return detobj; | 6345 | return detobj; |
5018 | } | 6346 | } |
@@ -5028,7 +6356,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
5028 | detobj.velVector = Vector3.Zero; | 6356 | detobj.velVector = Vector3.Zero; |
5029 | detobj.colliderType = 0; | 6357 | detobj.colliderType = 0; |
5030 | detobj.groupUUID = UUID.Zero; | 6358 | detobj.groupUUID = UUID.Zero; |
5031 | 6359 | detobj.linkNumber = 0; | |
5032 | return detobj; | 6360 | return detobj; |
5033 | } | 6361 | } |
5034 | 6362 | ||
@@ -5095,29 +6423,404 @@ namespace OpenSim.Region.Framework.Scenes | |||
5095 | } | 6423 | } |
5096 | } | 6424 | } |
5097 | 6425 | ||
6426 | private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata) | ||
6427 | { | ||
6428 | try | ||
6429 | { | ||
6430 | List<uint> thisHitColliders = new List<uint>(); | ||
6431 | List<uint> endedColliders = new List<uint>(); | ||
6432 | List<uint> startedColliders = new List<uint>(); | ||
6433 | |||
6434 | if (coldata.Count == 0) | ||
6435 | { | ||
6436 | if (m_lastColliders.Count == 0) | ||
6437 | return; // nothing to do | ||
6438 | |||
6439 | foreach (uint localID in m_lastColliders) | ||
6440 | { | ||
6441 | endedColliders.Add(localID); | ||
6442 | } | ||
6443 | m_lastColliders.Clear(); | ||
6444 | } | ||
6445 | else | ||
6446 | { | ||
6447 | List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>(); | ||
6448 | if(ParcelAllowThisAvatarSounds) | ||
6449 | { | ||
6450 | CollisionForSoundInfo soundinfo; | ||
6451 | ContactPoint curcontact; | ||
6452 | |||
6453 | foreach (uint id in coldata.Keys) | ||
6454 | { | ||
6455 | thisHitColliders.Add(id); | ||
6456 | if (!m_lastColliders.Contains(id)) | ||
6457 | { | ||
6458 | startedColliders.Add(id); | ||
6459 | curcontact = coldata[id]; | ||
6460 | if (Math.Abs(curcontact.RelativeSpeed) > 0.2) | ||
6461 | { | ||
6462 | soundinfo = new CollisionForSoundInfo(); | ||
6463 | soundinfo.colliderID = id; | ||
6464 | soundinfo.position = curcontact.Position; | ||
6465 | soundinfo.relativeVel = curcontact.RelativeSpeed; | ||
6466 | soundinfolist.Add(soundinfo); | ||
6467 | } | ||
6468 | } | ||
6469 | } | ||
6470 | } | ||
6471 | else | ||
6472 | { | ||
6473 | foreach (uint id in coldata.Keys) | ||
6474 | { | ||
6475 | thisHitColliders.Add(id); | ||
6476 | if (!m_lastColliders.Contains(id)) | ||
6477 | startedColliders.Add(id); | ||
6478 | } | ||
6479 | } | ||
6480 | // calculate things that ended colliding | ||
6481 | foreach (uint localID in m_lastColliders) | ||
6482 | { | ||
6483 | if (!thisHitColliders.Contains(localID)) | ||
6484 | { | ||
6485 | endedColliders.Add(localID); | ||
6486 | } | ||
6487 | } | ||
6488 | //add the items that started colliding this time to the last colliders list. | ||
6489 | foreach (uint localID in startedColliders) | ||
6490 | { | ||
6491 | m_lastColliders.Add(localID); | ||
6492 | } | ||
6493 | // remove things that ended colliding from the last colliders list | ||
6494 | foreach (uint localID in endedColliders) | ||
6495 | { | ||
6496 | m_lastColliders.Remove(localID); | ||
6497 | } | ||
6498 | |||
6499 | if (soundinfolist.Count > 0) | ||
6500 | CollisionSounds.AvatarCollisionSound(this, soundinfolist); | ||
6501 | } | ||
6502 | |||
6503 | foreach (SceneObjectGroup att in GetAttachments()) | ||
6504 | { | ||
6505 | SendCollisionEvent(att, scriptEvents.collision_start, startedColliders, m_scene.EventManager.TriggerScriptCollidingStart); | ||
6506 | SendCollisionEvent(att, scriptEvents.collision , m_lastColliders , m_scene.EventManager.TriggerScriptColliding); | ||
6507 | SendCollisionEvent(att, scriptEvents.collision_end , endedColliders , m_scene.EventManager.TriggerScriptCollidingEnd); | ||
6508 | |||
6509 | if (startedColliders.Contains(0)) | ||
6510 | SendLandCollisionEvent(att, scriptEvents.land_collision_start, m_scene.EventManager.TriggerScriptLandCollidingStart); | ||
6511 | if (m_lastColliders.Contains(0)) | ||
6512 | SendLandCollisionEvent(att, scriptEvents.land_collision, m_scene.EventManager.TriggerScriptLandColliding); | ||
6513 | if (endedColliders.Contains(0)) | ||
6514 | SendLandCollisionEvent(att, scriptEvents.land_collision_end, m_scene.EventManager.TriggerScriptLandCollidingEnd); | ||
6515 | } | ||
6516 | } | ||
6517 | catch { } | ||
6518 | // finally | ||
6519 | // { | ||
6520 | // m_collisionEventFlag = false; | ||
6521 | // } | ||
6522 | } | ||
6523 | |||
5098 | private void TeleportFlagsDebug() { | 6524 | private void TeleportFlagsDebug() { |
5099 | 6525 | ||
5100 | // Some temporary debugging help to show all the TeleportFlags we have... | 6526 | // Some temporary debugging help to show all the TeleportFlags we have... |
5101 | bool HG = false; | 6527 | bool HG = false; |
5102 | if((m_teleportFlags & TeleportFlags.ViaHGLogin) == TeleportFlags.ViaHGLogin) | 6528 | if((m_teleportFlags & TeleportFlags.ViaHGLogin) == TeleportFlags.ViaHGLogin) |
5103 | HG = true; | 6529 | HG = true; |
5104 | 6530 | ||
5105 | m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); | 6531 | m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); |
5106 | 6532 | ||
5107 | uint i = 0u; | 6533 | uint i = 0u; |
5108 | for (int x = 0; x <= 30 ; x++, i = 1u << x) | 6534 | for (int x = 0; x <= 30 ; x++, i = 1u << x) |
5109 | { | 6535 | { |
5110 | i = 1u << x; | 6536 | i = 1u << x; |
5111 | 6537 | ||
5112 | if((m_teleportFlags & (TeleportFlags)i) == (TeleportFlags)i) | 6538 | if((m_teleportFlags & (TeleportFlags)i) == (TeleportFlags)i) |
5113 | if (HG == false) | 6539 | if (HG == false) |
5114 | m_log.InfoFormat("[SCENE PRESENCE]: Teleport Flags include {0}", ((TeleportFlags) i).ToString()); | 6540 | m_log.InfoFormat("[SCENE PRESENCE]: Teleport Flags include {0}", ((TeleportFlags) i).ToString()); |
5115 | else | 6541 | else |
5116 | m_log.InfoFormat("[SCENE PRESENCE]: HG Teleport Flags include {0}", ((TeleportFlags)i).ToString()); | 6542 | m_log.InfoFormat("[SCENE PRESENCE]: HG Teleport Flags include {0}", ((TeleportFlags)i).ToString()); |
5117 | } | 6543 | } |
5118 | 6544 | ||
5119 | m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); | 6545 | m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); |
5120 | 6546 | ||
6547 | } | ||
6548 | |||
6549 | private void parcelGodCheck(UUID currentParcelID) | ||
6550 | { | ||
6551 | List<ScenePresence> allpresences = m_scene.GetScenePresences(); | ||
6552 | |||
6553 | foreach (ScenePresence p in allpresences) | ||
6554 | { | ||
6555 | if (p.IsDeleted || p.IsChildAgent || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) | ||
6556 | continue; | ||
6557 | |||
6558 | if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID) | ||
6559 | { | ||
6560 | if (IsViewerUIGod) | ||
6561 | p.SendViewTo(this); | ||
6562 | else | ||
6563 | p.SendKillTo(this); | ||
6564 | } | ||
6565 | } | ||
6566 | } | ||
6567 | |||
6568 | private void ParcelCrossCheck(UUID currentParcelID,UUID previusParcelID, | ||
6569 | bool currentParcelHide, bool previusParcelHide, bool oldhide, bool check) | ||
6570 | { | ||
6571 | List<ScenePresence> killsToSendto = new List<ScenePresence>(); | ||
6572 | List<ScenePresence> killsToSendme = new List<ScenePresence>(); | ||
6573 | List<ScenePresence> viewsToSendto = new List<ScenePresence>(); | ||
6574 | List<ScenePresence> viewsToSendme = new List<ScenePresence>(); | ||
6575 | List<ScenePresence> allpresences = null; | ||
6576 | |||
6577 | if (IsInTransit || IsChildAgent) | ||
6578 | return; | ||
6579 | |||
6580 | if (check) | ||
6581 | { | ||
6582 | // check is relative to current parcel only | ||
6583 | if (oldhide == currentParcelHide) | ||
6584 | return; | ||
6585 | |||
6586 | allpresences = m_scene.GetScenePresences(); | ||
6587 | |||
6588 | if (oldhide) | ||
6589 | { // where private | ||
6590 | foreach (ScenePresence p in allpresences) | ||
6591 | { | ||
6592 | if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) | ||
6593 | continue; | ||
6594 | |||
6595 | // those on not on parcel see me | ||
6596 | if (currentParcelID != p.currentParcelUUID) | ||
6597 | { | ||
6598 | viewsToSendto.Add(p); // they see me | ||
6599 | } | ||
6600 | } | ||
6601 | } // where private end | ||
6602 | |||
6603 | else | ||
6604 | { // where public | ||
6605 | foreach (ScenePresence p in allpresences) | ||
6606 | { | ||
6607 | if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) | ||
6608 | continue; | ||
6609 | |||
6610 | // those not on parcel dont see me | ||
6611 | if (currentParcelID != p.currentParcelUUID && !p.IsViewerUIGod) | ||
6612 | { | ||
6613 | killsToSendto.Add(p); // they dont see me | ||
6614 | } | ||
6615 | } | ||
6616 | } // where public end | ||
6617 | |||
6618 | allpresences.Clear(); | ||
6619 | } | ||
6620 | else | ||
6621 | { | ||
6622 | if (currentParcelHide) | ||
6623 | { | ||
6624 | // now on a private parcel | ||
6625 | allpresences = m_scene.GetScenePresences(); | ||
6626 | |||
6627 | if (previusParcelHide && previusParcelID != UUID.Zero) | ||
6628 | { | ||
6629 | foreach (ScenePresence p in allpresences) | ||
6630 | { | ||
6631 | if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) | ||
6632 | continue; | ||
6633 | |||
6634 | // only those on previus parcel need receive kills | ||
6635 | if (previusParcelID == p.currentParcelUUID) | ||
6636 | { | ||
6637 | if(!p.IsViewerUIGod) | ||
6638 | killsToSendto.Add(p); // they dont see me | ||
6639 | if(!IsViewerUIGod) | ||
6640 | killsToSendme.Add(p); // i dont see them | ||
6641 | } | ||
6642 | // only those on new parcel need see | ||
6643 | if (currentParcelID == p.currentParcelUUID) | ||
6644 | { | ||
6645 | viewsToSendto.Add(p); // they see me | ||
6646 | viewsToSendme.Add(p); // i see them | ||
6647 | } | ||
6648 | } | ||
6649 | } | ||
6650 | else | ||
6651 | { | ||
6652 | //was on a public area | ||
6653 | allpresences = m_scene.GetScenePresences(); | ||
6654 | |||
6655 | foreach (ScenePresence p in allpresences) | ||
6656 | { | ||
6657 | if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) | ||
6658 | continue; | ||
6659 | |||
6660 | // those not on new parcel dont see me | ||
6661 | if (currentParcelID != p.currentParcelUUID && !p.IsViewerUIGod) | ||
6662 | { | ||
6663 | killsToSendto.Add(p); // they dont see me | ||
6664 | } | ||
6665 | else | ||
6666 | { | ||
6667 | viewsToSendme.Add(p); // i see those on it | ||
6668 | } | ||
6669 | } | ||
6670 | } | ||
6671 | allpresences.Clear(); | ||
6672 | } // now on a private parcel end | ||
6673 | |||
6674 | else | ||
6675 | { | ||
6676 | // now on public parcel | ||
6677 | if (previusParcelHide && previusParcelID != UUID.Zero) | ||
6678 | { | ||
6679 | // was on private area | ||
6680 | allpresences = m_scene.GetScenePresences(); | ||
6681 | |||
6682 | foreach (ScenePresence p in allpresences) | ||
6683 | { | ||
6684 | if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) | ||
6685 | continue; | ||
6686 | // only those old parcel need kills | ||
6687 | if (previusParcelID == p.currentParcelUUID && !IsViewerUIGod) | ||
6688 | { | ||
6689 | killsToSendme.Add(p); // i dont see them | ||
6690 | } | ||
6691 | else | ||
6692 | { | ||
6693 | viewsToSendto.Add(p); // they see me | ||
6694 | } | ||
6695 | } | ||
6696 | } | ||
6697 | else | ||
6698 | return; // was on a public area also | ||
6699 | } // now on public parcel end | ||
6700 | } | ||
6701 | |||
6702 | // send the things | ||
6703 | |||
6704 | if (killsToSendto.Count > 0) | ||
6705 | { | ||
6706 | foreach (ScenePresence p in killsToSendto) | ||
6707 | { | ||
6708 | // m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname); | ||
6709 | SendKillTo(p); | ||
6710 | } | ||
6711 | } | ||
6712 | |||
6713 | if (killsToSendme.Count > 0) | ||
6714 | { | ||
6715 | foreach (ScenePresence p in killsToSendme) | ||
6716 | { | ||
6717 | // m_log.Debug("[AVATAR]: killToMe: " + Lastname + " " + p.Lastname); | ||
6718 | p.SendKillTo(this); | ||
6719 | } | ||
6720 | } | ||
6721 | |||
6722 | if (viewsToSendto.Count > 0) | ||
6723 | { | ||
6724 | foreach (ScenePresence p in viewsToSendto) | ||
6725 | { | ||
6726 | SendViewTo(p); | ||
6727 | } | ||
6728 | } | ||
6729 | |||
6730 | if (viewsToSendme.Count > 0 ) | ||
6731 | { | ||
6732 | foreach (ScenePresence p in viewsToSendme) | ||
6733 | { | ||
6734 | if (p.IsChildAgent) | ||
6735 | continue; | ||
6736 | // m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname); | ||
6737 | p.SendViewTo(this); | ||
6738 | } | ||
6739 | } | ||
6740 | } | ||
6741 | |||
6742 | public void HasMovedAway(bool nearRegion) | ||
6743 | { | ||
6744 | if (nearRegion) | ||
6745 | { | ||
6746 | if (Scene.AttachmentsModule != null) | ||
6747 | Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true); | ||
6748 | |||
6749 | if (!ParcelHideThisAvatar || IsViewerUIGod) | ||
6750 | return; | ||
6751 | |||
6752 | List<ScenePresence> allpresences = m_scene.GetScenePresences(); | ||
6753 | foreach (ScenePresence p in allpresences) | ||
6754 | { | ||
6755 | if (p.IsDeleted || p == this || p.IsChildAgent || p.ControllingClient == null || !p.ControllingClient.IsActive) | ||
6756 | continue; | ||
6757 | |||
6758 | if (p.currentParcelUUID == m_currentParcelUUID) | ||
6759 | { | ||
6760 | p.SendKillTo(this); | ||
6761 | } | ||
6762 | } | ||
6763 | } | ||
6764 | else | ||
6765 | { | ||
6766 | GodController.HasMovedAway(); | ||
6767 | List<ScenePresence> allpresences = m_scene.GetScenePresences(); | ||
6768 | foreach (ScenePresence p in allpresences) | ||
6769 | { | ||
6770 | if (p == this) | ||
6771 | continue; | ||
6772 | SendKillTo(p); | ||
6773 | if (!p.IsChildAgent) | ||
6774 | p.SendKillTo(this); | ||
6775 | } | ||
6776 | |||
6777 | if (Scene.AttachmentsModule != null) | ||
6778 | Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true); | ||
6779 | } | ||
6780 | } | ||
6781 | |||
6782 | |||
6783 | // kill with attachs root kills | ||
6784 | public void SendKillTo(ScenePresence p) | ||
6785 | { | ||
6786 | List<uint> ids = new List<uint>(m_attachments.Count + 1); | ||
6787 | foreach (SceneObjectGroup sog in m_attachments) | ||
6788 | { | ||
6789 | ids.Add(sog.RootPart.LocalId); | ||
6790 | } | ||
6791 | |||
6792 | ids.Add(LocalId); | ||
6793 | p.ControllingClient.SendKillObject(ids); | ||
6794 | } | ||
6795 | |||
6796 | /* | ||
6797 | // kill with hack | ||
6798 | public void SendKillTo(ScenePresence p) | ||
6799 | { | ||
6800 | foreach (SceneObjectGroup sog in m_attachments) | ||
6801 | p.ControllingClient.SendPartFullUpdate(sog.RootPart, LocalId + 1); | ||
6802 | p.ControllingClient.SendKillObject(new List<uint> { LocalId }); | ||
6803 | } | ||
6804 | */ | ||
6805 | public void SendViewTo(ScenePresence p) | ||
6806 | { | ||
6807 | SendAvatarDataToAgentNF(p); | ||
6808 | SendAppearanceToAgent(p); | ||
6809 | if (Animator != null) | ||
6810 | Animator.SendAnimPackToClient(p.ControllingClient); | ||
6811 | SendAttachmentsToAgentNF(p); | ||
6812 | } | ||
6813 | |||
6814 | public void SetAnimationOverride(string animState, UUID animID) | ||
6815 | { | ||
6816 | Overrides.SetOverride(animState, animID); | ||
6817 | // Animator.SendAnimPack(); | ||
6818 | Animator.ForceUpdateMovementAnimations(); | ||
6819 | } | ||
6820 | |||
6821 | public UUID GetAnimationOverride(string animState) | ||
6822 | { | ||
6823 | return Overrides.GetOverriddenAnimation(animState); | ||
5121 | } | 6824 | } |
5122 | } | 6825 | } |
5123 | } | 6826 | } |