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