aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/ScenePresence.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs3649
1 files changed, 3649 insertions, 0 deletions
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
new file mode 100644
index 0000000..36cd862
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -0,0 +1,3649 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Runtime.Serialization;
32using System.Security.Permissions;
33using OpenMetaverse;
34using OpenMetaverse.Packets;
35using log4net;
36using OpenSim.Framework;
37using OpenSim.Framework.Client;
38using OpenSim.Framework.Communications.Cache;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes.Types;
41using OpenSim.Region.Physics.Manager;
42using OSD = OpenMetaverse.StructuredData.OSD;
43
44namespace OpenSim.Region.Framework.Scenes
45{
46 enum ScriptControlled : uint
47 {
48 CONTROL_ZERO = 0,
49 CONTROL_FWD = 1,
50 CONTROL_BACK = 2,
51 CONTROL_LEFT = 4,
52 CONTROL_RIGHT = 8,
53 CONTROL_UP = 16,
54 CONTROL_DOWN = 32,
55 CONTROL_ROT_LEFT = 256,
56 CONTROL_ROT_RIGHT = 512,
57 CONTROL_LBUTTON = 268435456,
58 CONTROL_ML_LBUTTON = 1073741824
59 }
60
61 struct ScriptControllers
62 {
63 public UUID itemID;
64 public uint objID;
65 public ScriptControlled ignoreControls;
66 public ScriptControlled eventControls;
67 }
68
69 [Serializable]
70 public class ScenePresence : EntityBase, ISerializable
71 {
72// ~ScenePresence()
73// {
74// System.Console.WriteLine("[ScenePresence] Destructor called");
75// }
76
77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
78
79 public static byte[] DefaultTexture;
80
81 public UUID currentParcelUUID = UUID.Zero;
82 private AnimationSet m_animations = new AnimationSet();
83 private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
84 private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
85 private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
86 private bool MouseDown = false;
87 private SceneObjectGroup proxyObjectGroup = null;
88 //private SceneObjectPart proxyObjectPart = null;
89
90 public Vector3 lastKnownAllowedPosition = new Vector3();
91 public bool sentMessageAboutRestrictedParcelFlyingDown = false;
92
93 private bool m_updateflag = false;
94 private byte m_movementflag = 0;
95 private readonly List<NewForce> m_forcesList = new List<NewForce>();
96 private short m_updateCount = 0;
97 private uint m_requestedSitTargetID = 0;
98 private UUID m_requestedSitTargetUUID = UUID.Zero;
99
100 private bool m_startAnimationSet = false;
101
102 private Vector3 m_requestedSitOffset = new Vector3();
103
104 private Vector3 m_LastFinitePos = new Vector3();
105
106 private float m_sitAvatarHeight = 2.0f;
107
108 // experimentally determined "fudge factor" to make sit-target positions
109 // the same as in SecondLife. Fudge factor was tested for 36 different
110 // test cases including prims of type box, sphere, cylinder, and torus,
111 // with varying parameters for sit target location, prim size, prim
112 // rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
113 // issue #1716
114 private static readonly Vector3 m_sitTargetCorrectionOffset = new Vector3(0.1f, 0.0f, 0.3f);
115 private float m_godlevel = 0;
116
117 private bool m_invulnerable = true;
118
119 private Vector3 m_LastChildAgentUpdatePosition = new Vector3();
120
121 private int m_perfMonMS = 0;
122
123 private bool m_setAlwaysRun = false;
124
125 private Quaternion m_bodyRot= Quaternion.Identity;
126
127 public bool IsRestrictedToRegion = false;
128
129 public string JID = string.Empty;
130
131 // Agent moves with a PID controller causing a force to be exerted.
132 private bool m_newForce = false;
133 private bool m_newCoarseLocations = true;
134 private float m_health = 100f;
135
136 private Vector3 m_lastVelocity = Vector3.Zero;
137
138 // Default AV Height
139 private float m_avHeight = 127.0f;
140
141 protected RegionInfo m_regionInfo;
142 protected ulong crossingFromRegion = 0;
143
144 private readonly Vector3[] Dir_Vectors = new Vector3[6];
145
146 /// <value>
147 /// The avatar position last sent to clients
148 /// </value>
149 private Vector3 lastPhysPos = Vector3.Zero;
150
151 /// <value>
152 /// The avatar body rotation last sent to clients
153 /// </value>
154 private Quaternion lastPhysRot = Quaternion.Identity;
155
156 // Position of agent's camera in world (region cordinates)
157 protected Vector3 m_CameraCenter = Vector3.Zero;
158
159 // Use these three vectors to figure out what the agent is looking at
160 // Convert it to a Matrix and/or Quaternion
161 protected Vector3 m_CameraAtAxis = Vector3.Zero;
162 protected Vector3 m_CameraLeftAxis = Vector3.Zero;
163 protected Vector3 m_CameraUpAxis = Vector3.Zero;
164 private uint m_AgentControlFlags = 0;
165 private Quaternion m_headrotation = Quaternion.Identity;
166 private byte m_state = 0;
167
168 //Reuse the Vector3 instead of creating a new one on the UpdateMovement method
169 private Vector3 movementvector = Vector3.Zero;
170
171 private bool m_autopilotMoving = false;
172 private Vector3 m_autoPilotTarget = Vector3.Zero;
173 private bool m_sitAtAutoTarget = false;
174
175 private string m_nextSitAnimation = String.Empty;
176
177 //PauPaw:Proper PID Controler for autopilot************
178 private bool m_moveToPositionInProgress = false;
179 private Vector3 m_moveToPositionTarget = Vector3.Zero;
180 //private int m_moveToPositionStateStatus = 0;
181 //*****************************************************
182
183 // Agent's Draw distance.
184 protected float m_DrawDistance = 0f;
185
186 protected AvatarAppearance m_appearance;
187
188 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
189
190 // neighbouring regions we have enabled a child agent in
191 // holds the seed cap for the child agent in that region
192 private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>();
193
194 /// <summary>
195 /// Implemented Control Flags
196 /// </summary>
197 private enum Dir_ControlFlags
198 {
199 DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
200 DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
201 DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
202 DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
203 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
204 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
205 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
206 }
207
208 /// <summary>
209 /// Position at which a significant movement was made
210 /// </summary>
211 private Vector3 posLastSignificantMove = new Vector3();
212
213 private UpdateQueue m_partsUpdateQueue = new UpdateQueue();
214 private Queue<SceneObjectGroup> m_pendingObjects = null;
215
216 private Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>();
217
218 // For teleports and crossings callbacks
219 string m_callbackURI;
220 ulong m_rootRegionHandle;
221
222 #region Properties
223
224 /// <summary>
225 /// Physical scene representation of this Avatar.
226 /// </summary>
227 public PhysicsActor PhysicsActor
228 {
229 set { m_physicsActor = value; }
230 get { return m_physicsActor; }
231 }
232
233 public byte MovementFlag
234 {
235 set { m_movementflag = value; }
236 get { return m_movementflag; }
237 }
238
239 public bool Updated
240 {
241 set { m_updateflag = value; }
242 get { return m_updateflag; }
243 }
244
245 public bool Invulnerable
246 {
247 set { m_invulnerable = value; }
248 get { return m_invulnerable; }
249 }
250
251 public float GodLevel
252 {
253 get { return m_godlevel; }
254 }
255
256 private readonly ulong m_regionHandle;
257
258 public ulong RegionHandle
259 {
260 get { return m_regionHandle; }
261 }
262
263 public Vector3 CameraPosition
264 {
265 get { return m_CameraCenter; }
266 }
267
268 public Quaternion CameraRotation
269 {
270 get { return Util.Axes2Rot(m_CameraAtAxis, m_CameraLeftAxis, m_CameraUpAxis); }
271 }
272
273 public Vector3 Lookat
274 {
275 get
276 {
277 Vector3 a = new Vector3(m_CameraAtAxis.X, m_CameraAtAxis.Y, 0);
278
279 if (a == Vector3.Zero)
280 return a;
281
282 return Util.GetNormalizedVector(a);
283 }
284 }
285
286 private readonly string m_firstname;
287
288 public string Firstname
289 {
290 get { return m_firstname; }
291 }
292
293 private readonly string m_lastname;
294
295 public string Lastname
296 {
297 get { return m_lastname; }
298 }
299
300 private string m_grouptitle;
301
302 public string Grouptitle
303 {
304 get { return m_grouptitle; }
305 set { m_grouptitle = value; }
306 }
307
308 public float DrawDistance
309 {
310 get { return m_DrawDistance; }
311 }
312
313 protected bool m_allowMovement = true;
314
315 public bool AllowMovement
316 {
317 get { return m_allowMovement; }
318 set { m_allowMovement = value; }
319 }
320
321 public bool SetAlwaysRun
322 {
323 get
324 {
325 if (PhysicsActor != null)
326 {
327 return PhysicsActor.SetAlwaysRun;
328 }
329 else
330 {
331 return m_setAlwaysRun;
332 }
333 }
334 set
335 {
336 m_setAlwaysRun = value;
337 if (PhysicsActor != null)
338 {
339 PhysicsActor.SetAlwaysRun = value;
340 }
341 }
342 }
343
344 public byte State
345 {
346 get { return m_state; }
347 set { m_state = value; }
348 }
349
350 public uint AgentControlFlags
351 {
352 get { return m_AgentControlFlags; }
353 set { m_AgentControlFlags = value; }
354 }
355
356 /// <summary>
357 /// This works out to be the ClientView object associated with this avatar, or it's client connection manager
358 /// </summary>
359 private IClientAPI m_controllingClient;
360
361 protected PhysicsActor m_physicsActor;
362
363 /// <value>
364 /// The client controlling this presence
365 /// </value>
366 public IClientAPI ControllingClient
367 {
368 get { return m_controllingClient; }
369 }
370
371 public IClientCore ClientView
372 {
373 get { return (IClientCore) m_controllingClient; }
374 }
375
376 protected Vector3 m_parentPosition = new Vector3();
377 public Vector3 ParentPosition
378 {
379 get { return m_parentPosition; }
380 set { m_parentPosition = value; }
381 }
382
383 /// <summary>
384 /// Absolute position of this avatar in 'region cordinates'
385 /// </summary>
386 public override Vector3 AbsolutePosition
387 {
388 get
389 {
390 if (m_physicsActor != null)
391 {
392 m_pos.X = m_physicsActor.Position.X;
393 m_pos.Y = m_physicsActor.Position.Y;
394 m_pos.Z = m_physicsActor.Position.Z;
395 }
396
397 return m_parentPosition + m_pos;
398 }
399 set
400 {
401 if (m_physicsActor != null)
402 {
403 try
404 {
405 lock (m_scene.SyncRoot)
406 {
407 m_physicsActor.Position = new PhysicsVector(value.X, value.Y, value.Z);
408 }
409 }
410 catch (Exception e)
411 {
412 Console.WriteLine("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message);
413 }
414 }
415
416 m_pos = value;
417 m_parentPosition = new Vector3(0, 0, 0);
418 }
419 }
420
421 /// <summary>
422 /// Current velocity of the avatar.
423 /// </summary>
424 public override Vector3 Velocity
425 {
426 get
427 {
428 if (m_physicsActor != null)
429 {
430 m_velocity.X = m_physicsActor.Velocity.X;
431 m_velocity.Y = m_physicsActor.Velocity.Y;
432 m_velocity.Z = m_physicsActor.Velocity.Z;
433 }
434
435 return m_velocity;
436 }
437 set
438 {
439 //m_log.DebugFormat("In {0} setting velocity of {1} to {2}", m_scene.RegionInfo.RegionName, Name, value);
440
441 if (m_physicsActor != null)
442 {
443 try
444 {
445 lock (m_scene.SyncRoot)
446 {
447 m_physicsActor.Velocity = new PhysicsVector(value.X, value.Y, value.Z);
448 }
449 }
450 catch (Exception e)
451 {
452 Console.WriteLine("[SCENEPRESENCE]: VELOCITY " + e.Message);
453 }
454 }
455
456 m_velocity = value;
457 }
458 }
459
460 /// <summary>
461 /// If this is true, agent doesn't have a representation in this scene.
462 /// this is an agent 'looking into' this scene from a nearby scene(region)
463 ///
464 /// if False, this agent has a representation in this scene
465 /// </summary>
466 private bool m_isChildAgent = true;
467
468 public bool IsChildAgent
469 {
470 get { return m_isChildAgent; }
471 set { m_isChildAgent = value; }
472 }
473
474 private uint m_parentID = 0;
475
476 public uint ParentID
477 {
478 get { return m_parentID; }
479 set { m_parentID = value; }
480 }
481 public float Health
482 {
483 get { return m_health; }
484 set { m_health = value; }
485 }
486
487 /// <summary>
488 /// These are the region handles known by the avatar.
489 /// </summary>
490 public List<ulong> KnownChildRegionHandles
491 {
492 get
493 {
494 if (m_knownChildRegions.Count == 0)
495 return new List<ulong>();
496 else
497 return new List<ulong>(m_knownChildRegions.Keys);
498 }
499 }
500
501 public Dictionary<ulong, string> KnownRegions
502 {
503 get { return m_knownChildRegions; }
504 set
505 {
506 m_knownChildRegions = value;
507 }
508 }
509
510 public void AdjustKnownSeeds()
511 {
512 Dictionary<ulong, string> seeds = Scene.CapsModule.GetChildrenSeeds(UUID);
513 List<ulong> old = new List<ulong>();
514 foreach (ulong handle in seeds.Keys)
515 {
516 uint x, y;
517 Utils.LongToUInts(handle, out x, out y);
518 x = x / Constants.RegionSize;
519 y = y / Constants.RegionSize;
520 if (Util.IsOutsideView(x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
521 {
522 old.Add(handle);
523 }
524 }
525 DropOldNeighbours(old);
526 Scene.CapsModule.SetChildrenSeed(UUID, seeds);
527 KnownRegions = seeds;
528 //Console.WriteLine(" ++++++++++AFTER+++++++++++++ ");
529 //DumpKnownRegions();
530 }
531
532 public void DumpKnownRegions()
533 {
534 Console.WriteLine("================ KnownRegions {0} ================", Scene.RegionInfo.RegionName);
535 foreach (KeyValuePair<ulong, string> kvp in KnownRegions)
536 {
537 uint x, y;
538 Utils.LongToUInts(kvp.Key, out x, out y);
539 x = x / Constants.RegionSize;
540 y = y / Constants.RegionSize;
541 Console.WriteLine(" >> {0}, {1}: {2}", x, y, kvp.Value);
542 }
543 }
544
545 public AnimationSet Animations
546 {
547 get { return m_animations; }
548 }
549
550 #endregion
551
552 #region Constructor(s)
553
554 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo)
555 {
556 m_regionHandle = reginfo.RegionHandle;
557 m_controllingClient = client;
558 m_firstname = m_controllingClient.FirstName;
559 m_lastname = m_controllingClient.LastName;
560 m_name = String.Format("{0} {1}", m_firstname, m_lastname);
561
562 m_scene = world;
563 m_uuid = client.AgentId;
564 m_regionInfo = reginfo;
565 m_localId = m_scene.AllocateLocalId();
566
567 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
568 if (gm != null)
569 m_grouptitle = gm.GetGroupTitle(m_uuid);
570
571 AbsolutePosition = m_controllingClient.StartPos;
572 AdjustKnownSeeds();
573
574 TrySetMovementAnimation("STAND"); // TODO: I think, this won't send anything, as we are still a child here...
575
576 // we created a new ScenePresence (a new child agent) in a fresh region.
577 // Request info about all the (root) agents in this region
578 // Note: This won't send data *to* other clients in that region (children don't send)
579 SendInitialFullUpdateToAllClients();
580
581 RegisterToEvents();
582 SetDirectionVectors();
583
584 CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid);
585 if (userInfo != null)
586 userInfo.OnItemReceived += ItemReceived;
587 }
588
589 public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams,
590 AvatarWearable[] wearables)
591 : this(client, world, reginfo)
592 {
593 m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams);
594 }
595
596 public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance)
597 : this(client, world, reginfo)
598 {
599 m_appearance = appearance;
600 }
601
602 public void RegisterToEvents()
603 {
604 m_controllingClient.OnRequestWearables += SendWearables;
605 m_controllingClient.OnSetAppearance += SetAppearance;
606 m_controllingClient.OnCompleteMovementToRegion += CompleteMovement;
607 m_controllingClient.OnCompleteMovementToRegion += SendInitialData;
608 m_controllingClient.OnAgentUpdate += HandleAgentUpdate;
609 m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit;
610 m_controllingClient.OnAgentSit += HandleAgentSit;
611 m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
612 m_controllingClient.OnStartAnim += HandleStartAnim;
613 m_controllingClient.OnStopAnim += HandleStopAnim;
614 m_controllingClient.OnForceReleaseControls += HandleForceReleaseControls;
615 m_controllingClient.OnAutoPilotGo += DoAutoPilot;
616 m_controllingClient.AddGenericPacketHandler("autopilot", DoMoveToPosition);
617
618 // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
619 // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
620 }
621
622 private void SetDirectionVectors()
623 {
624 Dir_Vectors[0] = new Vector3(1, 0, 0); //FORWARD
625 Dir_Vectors[1] = new Vector3(-1, 0, 0); //BACK
626 Dir_Vectors[2] = new Vector3(0, 1, 0); //LEFT
627 Dir_Vectors[3] = new Vector3(0, -1, 0); //RIGHT
628 Dir_Vectors[4] = new Vector3(0, 0, 1); //UP
629 Dir_Vectors[5] = new Vector3(0, 0, -1); //DOWN
630 Dir_Vectors[5] = new Vector3(0, 0, -0.5f); //DOWN_Nudge
631 }
632
633 #endregion
634
635 /// <summary>
636 /// Add the part to the queue of parts for which we need to send an update to the client
637 /// </summary>
638 /// <param name="part"></param>
639 public void QueuePartForUpdate(SceneObjectPart part)
640 {
641 //if (InterestList.Contains(part.ParentGroup))
642 //{
643 lock (m_partsUpdateQueue)
644 {
645 m_partsUpdateQueue.Enqueue(part);
646 }
647 // }
648 }
649
650 public uint GenerateClientFlags(UUID ObjectID)
651 {
652 return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID);
653 }
654
655 /// <summary>
656 /// Send updates to the client about prims which have been placed on the update queue. We don't
657 /// necessarily send updates for all the parts on the queue, e.g. if an updates with a more recent
658 /// timestamp has already been sent.
659 /// </summary>
660 public void SendPrimUpdates()
661 {
662 // if (m_scene.QuadTree.GetNodeID(this.AbsolutePosition.X, this.AbsolutePosition.Y) != m_currentQuadNode)
663 //{
664 // this.UpdateQuadTreeNode();
665 //this.RefreshQuadObject();
666 //}
667 m_perfMonMS = System.Environment.TickCount;
668
669 if (m_pendingObjects == null)
670 {
671 if (!m_isChildAgent || m_scene.m_seeIntoRegionFromNeighbor)
672 {
673 m_pendingObjects = new Queue<SceneObjectGroup>();
674
675 List<EntityBase> ents = new List<EntityBase>(m_scene.Entities);
676 if (!m_isChildAgent) // Proximity sort makes no sense for
677 { // Child agents
678 ents.Sort(delegate(EntityBase a, EntityBase b)
679 {
680 return Vector3.Distance(AbsolutePosition, a.AbsolutePosition).CompareTo(Vector3.Distance(AbsolutePosition, b.AbsolutePosition));
681 });
682 }
683
684 foreach (EntityBase e in ents)
685 {
686 if (e is SceneObjectGroup)
687 m_pendingObjects.Enqueue((SceneObjectGroup)e);
688 }
689 }
690 }
691
692 while (m_pendingObjects.Count > 0 && m_partsUpdateQueue.Count < 60)
693 {
694 SceneObjectGroup g = m_pendingObjects.Dequeue();
695
696 // This is where we should check for draw distance
697 // do culling and stuff. Problem with that is that until
698 // we recheck in movement, that won't work right.
699 // So it's not implemented now.
700 //
701
702 // Don't even queue if we have sent this one
703 //
704 if (!m_updateTimes.ContainsKey(g.UUID))
705 g.ScheduleFullUpdateToAvatar(this);
706 }
707
708 int updateCount = 0;
709
710 while (m_partsUpdateQueue.Count > 0)
711 {
712 SceneObjectPart part = m_partsUpdateQueue.Dequeue();
713
714 if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
715 continue;
716
717 if (m_updateTimes.ContainsKey(part.UUID))
718 {
719 ScenePartUpdate update = m_updateTimes[part.UUID];
720
721 // We deal with the possibility that two updates occur at
722 // the same unix time at the update point itself.
723
724 if ((update.LastFullUpdateTime < part.TimeStampFull) ||
725 part.IsAttachment)
726 {
727// m_log.DebugFormat(
728// "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}",
729// part.Name, part.UUID, part.TimeStampFull);
730
731 part.SendFullUpdate(ControllingClient,
732 GenerateClientFlags(part.UUID));
733
734 // We'll update to the part's timestamp rather than
735 // the current time to avoid the race condition
736 // whereby the next tick occurs while we are doing
737 // this update. If this happened, then subsequent
738 // updates which occurred on the same tick or the
739 // next tick of the last update would be ignored.
740
741 update.LastFullUpdateTime = part.TimeStampFull;
742
743 updateCount++;
744 }
745 else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
746 {
747// m_log.DebugFormat(
748// "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}",
749// part.Name, part.UUID, part.TimeStampTerse);
750
751 part.SendTerseUpdateToClient(ControllingClient);
752
753 update.LastTerseUpdateTime = part.TimeStampTerse;
754 updateCount++;
755 }
756 }
757 else
758 {
759 //never been sent to client before so do full update
760 ScenePartUpdate update = new ScenePartUpdate();
761 update.FullID = part.UUID;
762 update.LastFullUpdateTime = part.TimeStampFull;
763 m_updateTimes.Add(part.UUID, update);
764
765 // Attachment handling
766 //
767 if (part.ParentGroup.RootPart.Shape.PCode == 9 && part.ParentGroup.RootPart.Shape.State != 0)
768 {
769 if (part != part.ParentGroup.RootPart)
770 continue;
771
772 part.ParentGroup.SendFullUpdateToClient(ControllingClient);
773 continue;
774 }
775
776 part.SendFullUpdate(ControllingClient,
777 GenerateClientFlags(part.UUID));
778 updateCount++;
779 }
780
781 if (updateCount > 60)
782 break;
783 }
784
785 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
786 }
787
788 #region Status Methods
789
790 /// <summary>
791 /// This turns a child agent, into a root agent
792 /// This is called when an agent teleports into a region, or if an
793 /// agent crosses into this region from a neighbor over the border
794 /// </summary>
795 public void MakeRootAgent(Vector3 pos, bool isFlying)
796 {
797 m_log.DebugFormat(
798 "[SCENE]: Upgrading child to root agent for {0} in {1}",
799 Name, m_scene.RegionInfo.RegionName);
800
801 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
802
803 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
804 if (gm != null)
805 m_grouptitle = gm.GetGroupTitle(m_uuid);
806
807 m_scene.SetRootAgentScene(m_uuid);
808
809 // Moved this from SendInitialData to ensure that m_appearance is initialized
810 // before the inventory is processed in MakeRootAgent. This fixes a race condition
811 // related to the handling of attachments
812 m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
813
814 if (pos.X < 0 || pos.X > Constants.RegionSize || pos.Y < 0 || pos.Y > Constants.RegionSize || pos.Z < 0)
815 {
816 Vector3 emergencyPos = new Vector3(128, 128, 128);
817
818 m_log.WarnFormat(
819 "[SCENE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}",
820 pos, Name, UUID, emergencyPos);
821
822 pos = emergencyPos;
823 }
824
825 m_isChildAgent = false;
826
827 float localAVHeight = 1.56f;
828 if (m_avHeight != 127.0f)
829 {
830 localAVHeight = m_avHeight;
831 }
832
833 float posZLimit = (float)m_scene.GetLandHeight((int)pos.X, (int)pos.Y);
834 float newPosZ = posZLimit + localAVHeight / 2;
835 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
836 {
837 pos.Z = newPosZ;
838 }
839 AbsolutePosition = pos;
840
841 AddToPhysicalScene();
842 m_physicsActor.Flying = isFlying;
843
844 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
845 // avatar to return to the standing position in mid-air. On login it looks like this is being sent
846 // elsewhere anyway
847 //SendAnimPack();
848
849 m_scene.SwapRootAgentCount(false);
850 m_scene.CommsManager.UserProfileCacheService.RequestInventoryForUser(m_uuid);
851 m_scene.CapsModule.AddCapsHandler(m_uuid);
852
853 // On the next prim update, all objects will be sent
854 //
855 m_pendingObjects = null;
856
857 m_scene.EventManager.TriggerOnMakeRootAgent(this);
858 }
859
860 /// <summary>
861 /// This turns a root agent into a child agent
862 /// when an agent departs this region for a neighbor, this gets called.
863 ///
864 /// It doesn't get called for a teleport. Reason being, an agent that
865 /// teleports out may not end up anywhere near this region
866 /// </summary>
867 public void MakeChildAgent()
868 {
869 m_animations.Clear();
870
871// m_log.DebugFormat(
872// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
873// Name, UUID, m_scene.RegionInfo.RegionName);
874
875 // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing,
876 // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated.
877 //Velocity = new Vector3(0, 0, 0);
878
879 m_isChildAgent = true;
880 m_scene.SwapRootAgentCount(true);
881 RemoveFromPhysicalScene();
882 m_scene.EventManager.TriggerOnMakeChildAgent(this);
883 }
884
885 /// <summary>
886 /// Removes physics plugin scene representation of this agent if it exists.
887 /// </summary>
888 private void RemoveFromPhysicalScene()
889 {
890 if (PhysicsActor != null)
891 {
892 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
893 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
894 m_physicsActor.UnSubscribeEvents();
895 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
896 PhysicsActor = null;
897 }
898 }
899
900 /// <summary>
901 ///
902 /// </summary>
903 /// <param name="pos"></param>
904 public void Teleport(Vector3 pos)
905 {
906 RemoveFromPhysicalScene();
907 Velocity = new Vector3(0, 0, 0);
908 AbsolutePosition = pos;
909 AddToPhysicalScene();
910 SendTerseUpdateToAllClients();
911 }
912
913 /// <summary>
914 ///
915 /// </summary>
916 public void StopMovement()
917 {
918 }
919
920 public void StopFlying()
921 {
922 // It turns out to get the agent to stop flying, you have to feed it stop flying velocities
923 // and send a full object update.
924 // There's no message to send the client to tell it to stop flying
925
926 // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air
927 // when the avatar stands up
928
929 if (m_avHeight != 127.0f)
930 {
931 AbsolutePosition = AbsolutePosition + new Vector3(0, 0, (m_avHeight / 6f));
932 }
933 else
934 {
935 AbsolutePosition = AbsolutePosition + new Vector3(0, 0, (1.56f / 6f));
936 }
937 TrySetMovementAnimation("LAND");
938 SendFullUpdateToAllClients();
939 }
940
941 public void AddNeighbourRegion(ulong regionHandle, string cap)
942 {
943 lock (m_knownChildRegions)
944 {
945 if (!m_knownChildRegions.ContainsKey(regionHandle))
946 {
947 uint x, y;
948 Utils.LongToUInts(regionHandle, out x, out y);
949 m_knownChildRegions.Add(regionHandle, cap);
950 }
951 }
952 }
953
954 public void RemoveNeighbourRegion(ulong regionHandle)
955 {
956 lock (m_knownChildRegions)
957 {
958 if (m_knownChildRegions.ContainsKey(regionHandle))
959 {
960 m_knownChildRegions.Remove(regionHandle);
961 //Console.WriteLine(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count);
962 }
963 }
964 }
965
966 public void DropOldNeighbours(List<ulong> oldRegions)
967 {
968 foreach (ulong handle in oldRegions)
969 {
970 RemoveNeighbourRegion(handle);
971 Scene.CapsModule.DropChildSeed(UUID, handle);
972 }
973 }
974
975 public List<ulong> GetKnownRegionList()
976 {
977 return new List<ulong>(m_knownChildRegions.Keys);
978 }
979
980 #endregion
981
982 #region Event Handlers
983
984 /// <summary>
985 /// Sets avatar height in the phyiscs plugin
986 /// </summary>
987 internal void SetHeight(float height)
988 {
989 m_avHeight = height;
990 if (PhysicsActor != null)
991 {
992 PhysicsVector SetSize = new PhysicsVector(0.45f, 0.6f, m_avHeight);
993 PhysicsActor.Size = SetSize;
994 }
995 }
996
997 /// <summary>
998 /// Complete Avatar's movement into the region
999 /// </summary>
1000 public void CompleteMovement()
1001 {
1002 Vector3 look = Velocity;
1003 if ((look.X == 0) && (look.Y == 0) && (look.Z == 0))
1004 {
1005 look = new Vector3(0.99f, 0.042f, 0);
1006 }
1007
1008 m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look);
1009
1010 if (m_isChildAgent)
1011 {
1012 m_isChildAgent = false;
1013
1014 MakeRootAgent(AbsolutePosition, false);
1015
1016 if ((m_callbackURI != null) && !m_callbackURI.Equals(""))
1017 {
1018 m_log.DebugFormat("[SCENE PRESENCE]: Releasing agent in URI {0}", m_callbackURI);
1019 Scene.SendReleaseAgent(m_rootRegionHandle, UUID, m_callbackURI);
1020 m_callbackURI = null;
1021 }
1022
1023 //m_log.DebugFormat("Completed movement");
1024 }
1025 }
1026
1027 /// <summary>
1028 /// This is the event handler for client movement. If a client is moving, this event is triggering.
1029 /// </summary>
1030 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
1031 {
1032 //if (m_isChildAgent)
1033 //{
1034 // // Console.WriteLine("DEBUG: HandleAgentUpdate: child agent");
1035 // return;
1036 //}
1037
1038 // Must check for standing up even when PhysicsActor is null,
1039 // since sitting currently removes avatar from physical scene
1040 //m_log.Debug("agentPos:" + AbsolutePosition.ToString());
1041
1042 // This is irritating. Really.
1043 if (!AbsolutePosition.IsFinite())
1044 {
1045 RemoveFromPhysicalScene();
1046 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error# 9999902");
1047
1048 m_pos = m_LastFinitePos;
1049 if (!m_pos.IsFinite())
1050 {
1051 m_pos.X = 127f;
1052 m_pos.Y = 127f;
1053 m_pos.Z = 127f;
1054 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error# 9999903");
1055 }
1056
1057 AddToPhysicalScene();
1058 }
1059 else
1060 {
1061 m_LastFinitePos = m_pos;
1062 }
1063 //m_physicsActor.AddForce(new PhysicsVector(999999999, 99999999, 999999999999999), true);
1064
1065
1066 //ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
1067 //if (land != null)
1068 //{
1069 //if (land.landData.landingType == (byte)1 && land.landData.userLocation != Vector3.Zero)
1070 //{
1071 // agent.startpos = land.landData.userLocation;
1072 //}
1073 //}
1074
1075 m_perfMonMS = System.Environment.TickCount;
1076
1077 uint flags = agentData.ControlFlags;
1078 Quaternion bodyRotation = agentData.BodyRotation;
1079
1080 // Camera location in world. We'll need to raytrace
1081 // from this location from time to time.
1082 m_CameraCenter = agentData.CameraCenter;
1083
1084 // Use these three vectors to figure out what the agent is looking at
1085 // Convert it to a Matrix and/or Quaternion
1086 m_CameraAtAxis = agentData.CameraAtAxis;
1087 m_CameraLeftAxis = agentData.CameraLeftAxis;
1088 m_CameraUpAxis = agentData.CameraUpAxis;
1089
1090 // The Agent's Draw distance setting
1091 m_DrawDistance = agentData.Far;
1092
1093 if ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
1094 {
1095 StandUp();
1096 }
1097 lock (scriptedcontrols)
1098 {
1099 if (scriptedcontrols.Count > 0)
1100 {
1101 SendControlToScripts(flags);
1102 flags = this.RemoveIgnoredControls(flags, IgnoredControls);
1103
1104 }
1105 }
1106
1107 if (PhysicsActor == null)
1108 {
1109 return;
1110 }
1111
1112 if (m_autopilotMoving)
1113 CheckAtSitTarget();
1114
1115 if ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1116 {
1117 // TODO: This doesn't prevent the user from walking yet.
1118 // Setting parent ID would fix this, if we knew what value
1119 // to use. Or we could add a m_isSitting variable.
1120
1121 TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1122 }
1123 // In the future, these values might need to go global.
1124 // Here's where you get them.
1125
1126 m_AgentControlFlags = flags;
1127 m_headrotation = agentData.HeadRotation;
1128 m_state = agentData.State;
1129
1130 if (m_allowMovement)
1131 {
1132 int i = 0;
1133 bool update_movementflag = false;
1134 bool update_rotation = false;
1135 bool DCFlagKeyPressed = false;
1136 Vector3 agent_control_v3 = new Vector3(0, 0, 0);
1137 Quaternion q = bodyRotation;
1138 if (PhysicsActor != null)
1139 {
1140 bool oldflying = PhysicsActor.Flying;
1141
1142 PhysicsActor.Flying = ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1143
1144 if (PhysicsActor.Flying != oldflying)
1145 {
1146 update_movementflag = true;
1147 }
1148 }
1149
1150 if (q != m_bodyRot)
1151 {
1152 m_bodyRot = q;
1153 update_rotation = true;
1154 }
1155
1156 if (m_parentID == 0)
1157 {
1158 bool bAllowUpdateMoveToPosition = false;
1159 bool bResetMoveToPosition = false;
1160 foreach (Dir_ControlFlags DCF in Enum.GetValues(typeof (Dir_ControlFlags)))
1161 {
1162 if ((flags & (uint) DCF) != 0)
1163 {
1164 bResetMoveToPosition = true;
1165 DCFlagKeyPressed = true;
1166 try
1167 {
1168 agent_control_v3 += Dir_Vectors[i];
1169 }
1170 catch (IndexOutOfRangeException)
1171 {
1172 // Why did I get this?
1173 }
1174
1175 if ((m_movementflag & (uint) DCF) == 0)
1176 {
1177 m_movementflag += (byte) (uint) DCF;
1178 update_movementflag = true;
1179 }
1180 }
1181 else
1182 {
1183 if ((m_movementflag & (uint) DCF) != 0)
1184 {
1185 m_movementflag -= (byte) (uint) DCF;
1186 update_movementflag = true;
1187 }
1188 else
1189 {
1190 bAllowUpdateMoveToPosition = true;
1191 }
1192 }
1193 i++;
1194 }
1195
1196 //Paupaw:Do Proper PID for Autopilot here
1197 if (bResetMoveToPosition)
1198 {
1199 m_moveToPositionTarget = Vector3.Zero;
1200 m_moveToPositionInProgress = false;
1201 update_movementflag = true;
1202 bAllowUpdateMoveToPosition = false;
1203 }
1204
1205 if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
1206 {
1207 //Check the error term of the current position in relation to the target position
1208 if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 1.5)
1209 {
1210 // we are close enough to the target
1211 m_moveToPositionTarget = Vector3.Zero;
1212 m_moveToPositionInProgress = false;
1213 update_movementflag = true;
1214 }
1215 else
1216 {
1217 try
1218 {
1219 // move avatar in 2D at one meter/second towards target, in avatar coordinate frame.
1220 // This movement vector gets added to the velocity through AddNewMovement().
1221 // Theoretically we might need a more complex PID approach here if other
1222 // unknown forces are acting on the avatar and we need to adaptively respond
1223 // to such forces, but the following simple approach seems to works fine.
1224 Vector3 LocalVectorToTarget3D =
1225 (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
1226 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
1227 // Ignore z component of vector
1228 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1229 LocalVectorToTarget2D.Normalize();
1230 agent_control_v3 += LocalVectorToTarget2D;
1231
1232 // update avatar movement flags. the avatar coordinate system is as follows:
1233 //
1234 // +X (forward)
1235 //
1236 // ^
1237 // |
1238 // |
1239 // |
1240 // |
1241 // (left) +Y <--------o--------> -Y
1242 // avatar
1243 // |
1244 // |
1245 // |
1246 // |
1247 // v
1248 // -X
1249 //
1250
1251 // based on the above avatar coordinate system, classify the movement into
1252 // one of left/right/back/forward.
1253 if (LocalVectorToTarget2D.Y > 0)//MoveLeft
1254 {
1255 m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
1256 update_movementflag = true;
1257 }
1258 else if (LocalVectorToTarget2D.Y < 0) //MoveRight
1259 {
1260 m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
1261 update_movementflag = true;
1262 }
1263 if (LocalVectorToTarget2D.X < 0) //MoveBack
1264 {
1265 m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
1266 update_movementflag = true;
1267 }
1268 else if (LocalVectorToTarget2D.X > 0) //Move Forward
1269 {
1270 m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
1271 update_movementflag = true;
1272 }
1273 }
1274 catch (Exception)
1275 {
1276
1277 //Avoid system crash, can be slower but...
1278 }
1279
1280 }
1281 }
1282 }
1283
1284 // Cause the avatar to stop flying if it's colliding
1285 // with something with the down arrow pressed.
1286
1287 // Only do this if we're flying
1288 if (m_physicsActor != null && m_physicsActor.Flying)
1289 {
1290 // Are the landing controls requirements filled?
1291 bool controlland = (((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
1292 ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1293
1294 // Are the collision requirements fulfilled?
1295 bool colliding = (m_physicsActor.IsColliding == true);
1296
1297 if (m_physicsActor.Flying && colliding && controlland)
1298 {
1299 StopFlying();
1300 }
1301 }
1302
1303 if (update_movementflag || (update_rotation && DCFlagKeyPressed))
1304 {
1305// m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed));
1306// m_log.DebugFormat(
1307// "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1308
1309 AddNewMovement(agent_control_v3, q);
1310
1311 if (update_movementflag)
1312 UpdateMovementAnimations();
1313 }
1314 }
1315
1316 m_scene.EventManager.TriggerOnClientMovement(this);
1317
1318 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
1319 }
1320
1321 public void DoAutoPilot(uint not_used, Vector3 Pos, IClientAPI remote_client)
1322 {
1323 m_autopilotMoving = true;
1324 m_autoPilotTarget = Pos;
1325 m_sitAtAutoTarget = false;
1326 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1327 //proxy.PCode = (byte)PCode.ParticleSystem;
1328
1329 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1330 proxyObjectGroup.AttachToScene(m_scene);
1331
1332 // Commented out this code since it could never have executed, but might still be informative.
1333// if (proxyObjectGroup != null)
1334// {
1335 proxyObjectGroup.SendGroupFullUpdate();
1336 remote_client.SendSitResponse(proxyObjectGroup.UUID, Vector3.Zero, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false);
1337 m_scene.DeleteSceneObject(proxyObjectGroup, false);
1338// }
1339// else
1340// {
1341// m_autopilotMoving = false;
1342// m_autoPilotTarget = Vector3.Zero;
1343// ControllingClient.SendAlertMessage("Autopilot cancelled");
1344// }
1345 }
1346
1347 public void DoMoveToPosition(Object sender, string method, List<String> args)
1348 {
1349 try
1350 {
1351 float locx = 0f;
1352 float locy = 0f;
1353 float locz = 0f;
1354 uint regionX = 0;
1355 uint regionY = 0;
1356 try
1357 {
1358 Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY);
1359 locx = Convert.ToSingle(args[0]) - (float)regionX;
1360 locy = Convert.ToSingle(args[1]) - (float)regionY;
1361 locz = Convert.ToSingle(args[2]);
1362 }
1363 catch (InvalidCastException)
1364 {
1365 m_log.Error("[CLIENT]: Invalid autopilot request");
1366 return;
1367 }
1368 m_moveToPositionInProgress = true;
1369 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1370 }
1371 catch (Exception ex)
1372 {
1373 //Why did I get this error?
1374 Console.WriteLine("[SCENEPRESENCE]: DoMoveToPosition" + ex.ToString());
1375 }
1376 }
1377
1378 private void CheckAtSitTarget()
1379 {
1380 //m_log.Debug("[AUTOPILOT]: " + Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget).ToString());
1381 if (Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget) <= 1.5)
1382 {
1383 if (m_sitAtAutoTarget)
1384 {
1385 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetUUID);
1386 if (part != null)
1387 {
1388 AbsolutePosition = part.AbsolutePosition;
1389 Velocity = new Vector3(0, 0, 0);
1390 SendFullUpdateToAllClients();
1391
1392 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID);
1393 }
1394 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1395 m_requestedSitTargetUUID = UUID.Zero;
1396 }
1397 else
1398 {
1399 //ControllingClient.SendAlertMessage("Autopilot cancelled");
1400 //SendTerseUpdateToAllClients();
1401 //PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1402 //proxy.PCode = (byte)PCode.ParticleSystem;
1403 ////uint nextUUID = m_scene.NextLocalId;
1404
1405 //proxyObjectGroup = new SceneObjectGroup(m_scene, m_scene.RegionInfo.RegionHandle, UUID, nextUUID, m_autoPilotTarget, Quaternion.Identity, proxy);
1406 //if (proxyObjectGroup != null)
1407 //{
1408 //proxyObjectGroup.SendGroupFullUpdate();
1409 //ControllingClient.SendSitResponse(UUID.Zero, m_autoPilotTarget, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false);
1410 //m_scene.DeleteSceneObject(proxyObjectGroup);
1411 //}
1412 }
1413
1414 m_autoPilotTarget = Vector3.Zero;
1415 m_autopilotMoving = false;
1416 }
1417 }
1418 /// <summary>
1419 /// Perform the logic necessary to stand the client up. This method also executes
1420 /// the stand animation.
1421 /// </summary>
1422 public void StandUp()
1423 {
1424 if (m_parentID != 0)
1425 {
1426 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1427 if (part != null)
1428 {
1429 TaskInventoryDictionary taskIDict = part.TaskInventory;
1430 if (taskIDict != null)
1431 {
1432 lock (taskIDict)
1433 {
1434 foreach (UUID taskID in taskIDict.Keys)
1435 {
1436 UnRegisterControlEventsToScript(LocalId, taskID);
1437 taskIDict[taskID].PermsMask &= ~(
1438 2048 | //PERMISSION_CONTROL_CAMERA
1439 4); // PERMISSION_TAKE_CONTROLS
1440 }
1441 }
1442
1443 }
1444 // Reset sit target.
1445 if (part.GetAvatarOnSitTarget() == UUID)
1446 part.SetAvatarOnSitTarget(UUID.Zero);
1447
1448 m_parentPosition = part.GetWorldPosition();
1449 }
1450
1451 if (m_physicsActor == null)
1452 {
1453 AddToPhysicalScene();
1454 }
1455
1456 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight);
1457 m_parentPosition = new Vector3();
1458
1459 m_parentID = 0;
1460 SendFullUpdateToAllClients();
1461 m_requestedSitTargetID = 0;
1462 if (m_physicsActor != null)
1463 {
1464 SetHeight(m_avHeight);
1465 }
1466 }
1467
1468 TrySetMovementAnimation("STAND");
1469 }
1470
1471 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
1472 {
1473 SceneObjectPart targetPart = m_scene.GetSceneObjectPart(targetID);
1474 if (targetPart == null)
1475 return null;
1476
1477 // If the primitive the player clicked on has a sit target and that sit target is not full, that sit target is used.
1478 // If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used.
1479
1480 // Get our own copy of the part array, and sort into the order we want to test
1481 SceneObjectPart[] partArray = targetPart.ParentGroup.GetParts();
1482 Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2)
1483 {
1484 // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1)
1485 int linkNum1 = p1==targetPart ? -1 : p1.LinkNum;
1486 int linkNum2 = p2==targetPart ? -1 : p2.LinkNum;
1487 return linkNum1 - linkNum2;
1488 }
1489 );
1490
1491 //look for prims with explicit sit targets that are available
1492 foreach (SceneObjectPart part in partArray)
1493 {
1494 // Is a sit target available?
1495 Vector3 avSitOffSet = part.SitTargetPosition;
1496 Quaternion avSitOrientation = part.SitTargetOrientation;
1497 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1498
1499 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero));
1500 bool SitTargetisSet =
1501 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1502 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1503
1504 if (SitTargetisSet && SitTargetUnOccupied)
1505 {
1506 //switch the target to this prim
1507 return part;
1508 }
1509 }
1510
1511 // no explicit sit target found - use original target
1512 return targetPart;
1513 }
1514
1515 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset)
1516 {
1517 bool autopilot = true;
1518 Vector3 pos = new Vector3();
1519 Quaternion sitOrientation = Quaternion.Identity;
1520 Vector3 cameraEyeOffset = Vector3.Zero;
1521 Vector3 cameraAtOffset = Vector3.Zero;
1522 bool forceMouselook = false;
1523
1524 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1525 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1526 if (part != null)
1527 {
1528 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1529 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1530
1531 // Is a sit target available?
1532 Vector3 avSitOffSet = part.SitTargetPosition;
1533 Quaternion avSitOrientation = part.SitTargetOrientation;
1534 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1535
1536 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero));
1537 bool SitTargetisSet =
1538 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 0f &&
1539 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f));
1540
1541 if (SitTargetisSet && SitTargetUnOccupied)
1542 {
1543 part.SetAvatarOnSitTarget(UUID);
1544 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z);
1545 sitOrientation = avSitOrientation;
1546 autopilot = false;
1547 }
1548
1549 pos = part.AbsolutePosition + offset;
1550 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1)
1551 //{
1552 // offset = pos;
1553 //autopilot = false;
1554 //}
1555 if (m_physicsActor != null)
1556 {
1557 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1558 // We can remove the physicsActor until they stand up.
1559 m_sitAvatarHeight = m_physicsActor.Size.Z;
1560
1561 if (autopilot)
1562 {
1563 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5)
1564 {
1565 autopilot = false;
1566
1567 RemoveFromPhysicalScene();
1568 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1569 }
1570 }
1571 else
1572 {
1573 RemoveFromPhysicalScene();
1574 }
1575 }
1576
1577 cameraAtOffset = part.GetCameraAtOffset();
1578 cameraEyeOffset = part.GetCameraEyeOffset();
1579 forceMouselook = part.GetForceMouselook();
1580 }
1581
1582 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
1583 m_requestedSitTargetUUID = targetID;
1584 // This calls HandleAgentSit twice, once from here, and the client calls
1585 // HandleAgentSit itself after it gets to the location
1586 // It doesn't get to the location until we've moved them there though
1587 // which happens in HandleAgentSit :P
1588 m_autopilotMoving = autopilot;
1589 m_autoPilotTarget = pos;
1590 m_sitAtAutoTarget = autopilot;
1591 if (!autopilot)
1592 HandleAgentSit(remoteClient, UUID);
1593 }
1594
1595 public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset)
1596 {
1597 if (m_parentID != 0)
1598 {
1599 StandUp();
1600 }
1601 m_nextSitAnimation = "SIT";
1602
1603 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1604 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1605
1606 if (part != null)
1607 {
1608 if (!String.IsNullOrEmpty(part.SitAnimation))
1609 {
1610 m_nextSitAnimation = part.SitAnimation;
1611 }
1612 m_requestedSitTargetID = part.LocalId;
1613 m_requestedSitOffset = offset;
1614 }
1615 else
1616 {
1617
1618 m_log.Warn("Sit requested on unknown object: " + targetID.ToString());
1619 }
1620 SendSitResponse(remoteClient, targetID, offset);
1621 }
1622
1623 public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset, string sitAnimation)
1624 {
1625 if (m_parentID != 0)
1626 {
1627 StandUp();
1628 }
1629 if (!String.IsNullOrEmpty(sitAnimation))
1630 {
1631 m_nextSitAnimation = sitAnimation;
1632 }
1633 else
1634 {
1635 m_nextSitAnimation = "SIT";
1636 }
1637
1638 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1639 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1640 if (part != null)
1641 {
1642 m_requestedSitTargetID = part.LocalId;
1643 m_requestedSitOffset = offset;
1644 }
1645 else
1646 {
1647 m_log.Warn("Sit requested on unknown object: " + targetID.ToString());
1648 }
1649 SendSitResponse(remoteClient, targetID, offset);
1650 }
1651
1652 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
1653 {
1654 if (!String.IsNullOrEmpty(m_nextSitAnimation))
1655 {
1656 HandleAgentSit(remoteClient, agentID, m_nextSitAnimation);
1657 }
1658 else
1659 {
1660 HandleAgentSit(remoteClient, agentID, "SIT");
1661 }
1662 }
1663
1664 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID, string sitAnimation)
1665 {
1666 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1667
1668 if (m_sitAtAutoTarget || !m_autopilotMoving)
1669 {
1670 if (part != null)
1671 {
1672 if (part.GetAvatarOnSitTarget() == UUID)
1673 {
1674 Vector3 sitTargetPos = part.SitTargetPosition;
1675 Quaternion sitTargetOrient = part.SitTargetOrientation;
1676
1677 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
1678 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
1679
1680 //Quaternion result = (sitTargetOrient * vq) * nq;
1681
1682 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
1683 m_pos += m_sitTargetCorrectionOffset;
1684 m_bodyRot = sitTargetOrient;
1685 //Rotation = sitTargetOrient;
1686 m_parentPosition = part.AbsolutePosition;
1687
1688 //SendTerseUpdateToAllClients();
1689 }
1690 else
1691 {
1692 m_pos -= part.AbsolutePosition;
1693 m_parentPosition = part.AbsolutePosition;
1694 }
1695 }
1696 else
1697 {
1698 return;
1699 }
1700 }
1701 m_parentID = m_requestedSitTargetID;
1702
1703 Velocity = new Vector3(0, 0, 0);
1704 RemoveFromPhysicalScene();
1705
1706 TrySetMovementAnimation(sitAnimation);
1707 SendFullUpdateToAllClients();
1708 // This may seem stupid, but Our Full updates don't send avatar rotation :P
1709 // So we're also sending a terse update (which has avatar rotation)
1710 // [Update] We do now.
1711 //SendTerseUpdateToAllClients();
1712 }
1713
1714 /// <summary>
1715 /// Event handler for the 'Always run' setting on the client
1716 /// Tells the physics plugin to increase speed of movement.
1717 /// </summary>
1718 public void HandleSetAlwaysRun(IClientAPI remoteClient, bool SetAlwaysRun)
1719 {
1720 m_setAlwaysRun = SetAlwaysRun;
1721 if (PhysicsActor != null)
1722 {
1723 PhysicsActor.SetAlwaysRun = SetAlwaysRun;
1724 }
1725 }
1726
1727 public void AddAnimation(UUID animID)
1728 {
1729 if (m_isChildAgent)
1730 return;
1731
1732 if (m_animations.Add(animID, m_controllingClient.NextAnimationSequenceNumber))
1733 {
1734 SendAnimPack();
1735 }
1736 }
1737
1738 public void AddAnimation(string name)
1739 {
1740 if (m_isChildAgent)
1741 return;
1742
1743 UUID animID = m_controllingClient.GetDefaultAnimation(name);
1744 if (animID == UUID.Zero)
1745 return;
1746
1747 AddAnimation(animID);
1748 }
1749
1750 public void RemoveAnimation(UUID animID)
1751 {
1752 if (m_isChildAgent)
1753 return;
1754
1755 if (m_animations.Remove(animID))
1756 {
1757 SendAnimPack();
1758 }
1759 }
1760
1761 public void RemoveAnimation(string name)
1762 {
1763 if (m_isChildAgent)
1764 return;
1765
1766 UUID animID = m_controllingClient.GetDefaultAnimation(name);
1767 if (animID == UUID.Zero)
1768 return;
1769
1770 RemoveAnimation(animID);
1771 }
1772
1773 public UUID[] GetAnimationArray()
1774 {
1775 UUID[] animIDs;
1776 int[] sequenceNums;
1777 m_animations.GetArrays( out animIDs, out sequenceNums );
1778 return animIDs;
1779 }
1780
1781 public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
1782 {
1783 AddAnimation(animID);
1784 }
1785
1786 public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
1787 {
1788 RemoveAnimation(animID);
1789 }
1790
1791 /// <summary>
1792 /// The movement animation is reserved for "main" animations
1793 /// that are mutually exclusive, e.g. flying and sitting.
1794 /// </summary>
1795 protected void TrySetMovementAnimation(string anim)
1796 {
1797 //m_log.DebugFormat("Updating movement animation to {0}", anim);
1798
1799 if (m_animations.TrySetDefaultAnimation(anim, m_controllingClient.NextAnimationSequenceNumber))
1800 {
1801 SendAnimPack();
1802 }
1803 }
1804
1805 /// <summary>
1806 /// This method determines the proper movement related animation
1807 /// </summary>
1808 public string GetMovementAnimation()
1809 {
1810 if (m_movementflag != 0)
1811 {
1812 // We are moving
1813 if (PhysicsActor != null && PhysicsActor.Flying)
1814 {
1815 return "FLY";
1816 }
1817 else if (PhysicsActor != null && (m_movementflag & (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 &&
1818 PhysicsActor.IsColliding)
1819 {
1820 if ((m_movementflag & (uint) AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 ||
1821 (m_movementflag & (uint) AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0)
1822 {
1823 return "CROUCHWALK";
1824 }
1825 else
1826 {
1827 return "CROUCH";
1828 }
1829 }
1830 else if (PhysicsActor != null && !PhysicsActor.IsColliding && PhysicsActor.Velocity.Z < -2)
1831 {
1832 return "FALLDOWN";
1833 }
1834 else if (PhysicsActor != null && !PhysicsActor.IsColliding && Velocity.Z > 1e-6 &&
1835 (m_movementflag & (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0)
1836 {
1837 return "JUMP";
1838 }
1839 else if (m_setAlwaysRun)
1840 {
1841 return "RUN";
1842 }
1843 else
1844 {
1845 return "WALK";
1846 }
1847 }
1848 else
1849 {
1850 // We are not moving
1851 if (PhysicsActor != null && !PhysicsActor.IsColliding && PhysicsActor.Velocity.Z < -2 && !PhysicsActor.Flying)
1852 {
1853 return "FALLDOWN";
1854 }
1855 else if (PhysicsActor != null && !PhysicsActor.IsColliding && Velocity.Z > 6 && !PhysicsActor.Flying)
1856 {
1857 // HACK: We check if Velocity.Z > 6 for this animation in order to avoid false positives during normal movement.
1858 // TODO: set this animation only when on the ground and UP_POS is received?
1859
1860 // This is the standing jump
1861 return "JUMP";
1862 }
1863 else if (PhysicsActor != null && PhysicsActor.Flying)
1864 {
1865 return "HOVER";
1866 }
1867 else
1868 {
1869 return "STAND";
1870 }
1871 }
1872 }
1873
1874 /// <summary>
1875 /// Update the movement animation of this avatar according to its current state
1876 /// </summary>
1877 protected void UpdateMovementAnimations()
1878 {
1879 string animation = GetMovementAnimation();
1880 TrySetMovementAnimation(animation);
1881 }
1882
1883 /// <summary>
1884 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
1885 /// </summary>
1886 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
1887 /// <param name="rotation">The direction in which this avatar should now face.
1888 public void AddNewMovement(Vector3 vec, Quaternion rotation)
1889 {
1890 if (m_isChildAgent)
1891 {
1892 Console.WriteLine("DEBUG: AddNewMovement: child agent");
1893 return;
1894 }
1895
1896 m_perfMonMS = System.Environment.TickCount;
1897
1898 m_rotation = rotation;
1899 NewForce newVelocity = new NewForce();
1900 Vector3 direc = vec * rotation;
1901 direc.Normalize();
1902
1903 direc *= 0.03f * 128f;
1904 if (m_physicsActor.Flying)
1905 {
1906 direc *= 4;
1907 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1908 //bool colliding = (m_physicsActor.IsColliding==true);
1909 //if (controlland)
1910 // m_log.Info("[AGENT]: landCommand");
1911 //if (colliding)
1912 // m_log.Info("[AGENT]: colliding");
1913 //if (m_physicsActor.Flying && colliding && controlland)
1914 //{
1915 // StopFlying();
1916 // m_log.Info("[AGENT]: Stop FLying");
1917 //}
1918 }
1919 else
1920 {
1921 if (!m_physicsActor.Flying && m_physicsActor.IsColliding)
1922 {
1923 if (direc.Z > 2.0f)
1924 {
1925 direc.Z *= 3;
1926
1927 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
1928 TrySetMovementAnimation("PREJUMP");
1929 TrySetMovementAnimation("JUMP");
1930 }
1931 }
1932 }
1933
1934 newVelocity.X = direc.X;
1935 newVelocity.Y = direc.Y;
1936 newVelocity.Z = direc.Z;
1937 m_forcesList.Add(newVelocity);
1938
1939 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
1940 }
1941
1942 #endregion
1943
1944 #region Overridden Methods
1945
1946 public override void Update()
1947 {
1948 SendPrimUpdates();
1949
1950 if (m_newCoarseLocations)
1951 {
1952 SendCoarseLocations();
1953 m_newCoarseLocations = false;
1954 }
1955
1956 if (m_isChildAgent == false)
1957 {
1958 if (m_newForce) // user movement 'forces' (ie commands to move)
1959 {
1960 SendTerseUpdateToAllClients();
1961 m_updateCount = 0;
1962 }
1963 else if (m_movementflag != 0) // scripted movement (?)
1964 {
1965 m_updateCount++;
1966 if (m_updateCount > 3)
1967 {
1968 SendTerseUpdateToAllClients();
1969 m_updateCount = 0;
1970 }
1971 }
1972 else if ((Util.GetDistanceTo(lastPhysPos, AbsolutePosition) > 0.02)
1973 || (Util.GetDistanceTo(m_lastVelocity, m_velocity) > 0.02)
1974 || lastPhysRot != m_bodyRot)
1975 {
1976 // Send Terse Update to all clients updates lastPhysPos and m_lastVelocity
1977 // doing the above assures us that we know what we sent the clients last
1978 SendTerseUpdateToAllClients();
1979 m_updateCount = 0;
1980 }
1981
1982 // followed suggestion from mic bowman. reversed the two lines below.
1983 CheckForBorderCrossing();
1984 CheckForSignificantMovement(); // sends update to the modules.
1985 }
1986 }
1987
1988 #endregion
1989
1990 #region Update Client(s)
1991
1992 /// <summary>
1993 /// Sends a location update to the client connected to this scenePresence
1994 /// </summary>
1995 /// <param name="remoteClient"></param>
1996 public void SendTerseUpdateToClient(IClientAPI remoteClient)
1997 {
1998 m_perfMonMS = System.Environment.TickCount;
1999
2000 Vector3 pos = m_pos;
2001 Vector3 vel = Velocity;
2002 Quaternion rot = m_bodyRot;
2003 pos.Z -= m_appearance.HipOffset;
2004 remoteClient.SendAvatarTerseUpdate(m_regionHandle, (ushort)(m_scene.TimeDilation * (float)ushort.MaxValue), LocalId, new Vector3(pos.X, pos.Y, pos.Z),
2005 new Vector3(vel.X, vel.Y, vel.Z), rot);
2006
2007 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
2008 m_scene.AddAgentUpdates(1);
2009 }
2010
2011 /// <summary>
2012 /// Send a location/velocity/accelleration update to all agents in scene
2013 /// </summary>
2014 public void SendTerseUpdateToAllClients()
2015 {
2016 m_perfMonMS = System.Environment.TickCount;
2017
2018 m_scene.Broadcast(SendTerseUpdateToClient);
2019
2020 m_lastVelocity = m_velocity;
2021 lastPhysPos = AbsolutePosition;
2022 lastPhysRot = m_bodyRot;
2023
2024 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
2025
2026 }
2027
2028 public void SendCoarseLocations()
2029 {
2030 m_perfMonMS = System.Environment.TickCount;
2031
2032 List<Vector3> CoarseLocations = new List<Vector3>();
2033 List<ScenePresence> avatars = m_scene.GetAvatars();
2034 for (int i = 0; i < avatars.Count; i++)
2035 {
2036 if (avatars[i] != this)
2037 {
2038 if (avatars[i].ParentID != 0)
2039 {
2040 // sitting avatar
2041 SceneObjectPart sop = m_scene.GetSceneObjectPart(avatars[i].ParentID);
2042 if (sop != null)
2043 {
2044 CoarseLocations.Add(sop.AbsolutePosition + avatars[i].m_pos);
2045 }
2046 else
2047 {
2048 // we can't find the parent.. ! arg!
2049 CoarseLocations.Add(avatars[i].m_pos);
2050 }
2051 }
2052 else
2053 {
2054 CoarseLocations.Add(avatars[i].m_pos);
2055 }
2056 }
2057 }
2058
2059 m_controllingClient.SendCoarseLocationUpdate(CoarseLocations);
2060
2061 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
2062 }
2063
2064 public void CoarseLocationChange()
2065 {
2066 m_newCoarseLocations = true;
2067 }
2068
2069 /// <summary>
2070 /// Tell other client about this avatar (The client previously didn't know or had outdated details about this avatar)
2071 /// </summary>
2072 /// <param name="remoteAvatar"></param>
2073 public void SendFullUpdateToOtherClient(ScenePresence remoteAvatar)
2074 {
2075 // 2 stage check is needed.
2076 if (remoteAvatar == null)
2077 return;
2078 IClientAPI cl=remoteAvatar.ControllingClient;
2079 if (cl == null)
2080 return;
2081 if (m_appearance.Texture == null)
2082 return;
2083
2084 // Note: because Quaternion is a struct, it can't be null
2085 Quaternion rot = m_bodyRot;
2086
2087 Vector3 pos = m_pos;
2088 pos.Z -= m_appearance.HipOffset;
2089
2090 remoteAvatar.m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid,
2091 LocalId, m_pos, m_appearance.Texture.ToBytes(),
2092 m_parentID, rot);
2093 m_scene.AddAgentUpdates(1);
2094 }
2095
2096 /// <summary>
2097 /// Tell *ALL* agents about this agent
2098 /// </summary>
2099 public void SendInitialFullUpdateToAllClients()
2100 {
2101 m_perfMonMS = System.Environment.TickCount;
2102
2103 List<ScenePresence> avatars = m_scene.GetScenePresences();
2104 foreach (ScenePresence avatar in avatars)
2105 {
2106 // only send if this is the root (children are only "listening posts" in a foreign region)
2107 if (!IsChildAgent)
2108 {
2109 SendFullUpdateToOtherClient(avatar);
2110 }
2111
2112 if (avatar.LocalId != LocalId)
2113 {
2114 if (!avatar.IsChildAgent)
2115 {
2116 avatar.SendFullUpdateToOtherClient(this);
2117 avatar.SendAppearanceToOtherAgent(this);
2118 avatar.SendAnimPackToClient(this.ControllingClient);
2119 }
2120 }
2121 }
2122 m_scene.AddAgentUpdates(avatars.Count);
2123 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
2124 }
2125
2126 public void SendFullUpdateToAllClients()
2127 {
2128 m_perfMonMS = System.Environment.TickCount;
2129
2130 // only send update from root agents to other clients; children are only "listening posts"
2131 List<ScenePresence> avatars = m_scene.GetAvatars();
2132 foreach (ScenePresence avatar in avatars)
2133 {
2134 SendFullUpdateToOtherClient(avatar);
2135
2136 }
2137 m_scene.AddAgentUpdates(avatars.Count);
2138 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
2139
2140 SendAnimPack();
2141 }
2142
2143 /// <summary>
2144 /// Do everything required once a client completes its movement into a region
2145 /// </summary>
2146 public void SendInitialData()
2147 {
2148 // Moved this into CompleteMovement to ensure that m_appearance is initialized before
2149 // the inventory arrives
2150 // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
2151
2152 // Note: because Quaternion is a struct, it can't be null
2153 Quaternion rot = m_bodyRot;
2154
2155 Vector3 pos = m_pos;
2156 pos.Z -= m_appearance.HipOffset;
2157
2158 m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId,
2159 m_pos, m_appearance.Texture.ToBytes(), m_parentID, rot);
2160
2161 if (!m_isChildAgent)
2162 {
2163 m_scene.InformClientOfNeighbours(this);
2164 }
2165
2166 SendInitialFullUpdateToAllClients();
2167 SendAppearanceToAllOtherAgents();
2168 }
2169
2170 /// <summary>
2171 /// Tell the client for this scene presence what items it should be wearing now
2172 /// </summary>
2173 /// <param name="client"></param>
2174 public void SendWearables()
2175 {
2176 ControllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++);
2177 }
2178
2179 /// <summary>
2180 ///
2181 /// </summary>
2182 public void SendAppearanceToAllOtherAgents()
2183 {
2184 m_perfMonMS = System.Environment.TickCount;
2185
2186 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
2187 {
2188 if (scenePresence.UUID != UUID)
2189 {
2190 SendAppearanceToOtherAgent(scenePresence);
2191 }
2192 });
2193
2194 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
2195 }
2196
2197 /// <summary>
2198 /// Send appearance data to an agent that isn't this one.
2199 /// </summary>
2200 /// <param name="avatar"></param>
2201 public void SendAppearanceToOtherAgent(ScenePresence avatar)
2202 {
2203 avatar.ControllingClient.SendAppearance(
2204 m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.ToBytes());
2205 }
2206
2207 /// <summary>
2208 /// Set appearance data (textureentry and slider settings) received from the client
2209 /// </summary>
2210 /// <param name="texture"></param>
2211 /// <param name="visualParam"></param>
2212 public void SetAppearance(byte[] texture, List<byte> visualParam)
2213 {
2214 if (m_physicsActor != null)
2215 {
2216 // This may seem like it's redundant, remove the avatar from the physics scene
2217 // just to add it back again, but it saves us from having to update
2218 // 3 variables 10 times a second.
2219 m_scene.PhysicsScene.RemoveAvatar(m_physicsActor);
2220 AddToPhysicalScene();
2221 }
2222 m_appearance.SetAppearance(texture, visualParam);
2223 SetHeight(m_appearance.AvatarHeight);
2224 m_scene.CommsManager.AvatarService.UpdateUserAppearance(m_controllingClient.AgentId, m_appearance);
2225
2226 SendAppearanceToAllOtherAgents();
2227 //SendWearables();
2228 if (!m_startAnimationSet)
2229 {
2230 UpdateMovementAnimations();
2231 m_startAnimationSet = true;
2232 }
2233 }
2234
2235 public void SetWearable(int wearableId, AvatarWearable wearable)
2236 {
2237 m_appearance.SetWearable(wearableId, wearable);
2238 m_scene.CommsManager.AvatarService.UpdateUserAppearance(m_controllingClient.AgentId, m_appearance);
2239 m_controllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++);
2240 }
2241
2242 // Because appearance setting is in a module, we actually need
2243 // to give it access to our appearance directly, otherwise we
2244 // get a synchronization issue.
2245 public AvatarAppearance Appearance
2246 {
2247 get { return m_appearance; }
2248 set { m_appearance = value; }
2249 }
2250
2251 /// <summary>
2252 ///
2253 /// </summary>
2254 /// <param name="animations"></param>
2255 /// <param name="seqs"></param>
2256 public void SendAnimPack(UUID[] animations, int[] seqs)
2257 {
2258 if (m_isChildAgent)
2259 return;
2260
2261 m_scene.Broadcast(
2262 delegate(IClientAPI client) { client.SendAnimations(animations, seqs, m_controllingClient.AgentId); });
2263 }
2264
2265 public void SendAnimPackToClient(IClientAPI client)
2266 {
2267 if (m_isChildAgent)
2268 return;
2269 UUID[] animIDs;
2270 int[] sequenceNums;
2271
2272 m_animations.GetArrays(out animIDs, out sequenceNums);
2273
2274 client.SendAnimations(animIDs, sequenceNums, m_controllingClient.AgentId);
2275 }
2276
2277 /// <summary>
2278 /// Send animation information about this avatar to all clients.
2279 /// </summary>
2280 public void SendAnimPack()
2281 {
2282 //m_log.Debug("Sending animation pack");
2283
2284 if (m_isChildAgent)
2285 return;
2286
2287 UUID[] animIDs;
2288 int[] sequenceNums;
2289
2290 m_animations.GetArrays(out animIDs, out sequenceNums);
2291
2292 SendAnimPack(animIDs, sequenceNums);
2293 }
2294
2295 #endregion
2296
2297 #region Significant Movement Method
2298
2299 /// <summary>
2300 /// This checks for a significant movement and sends a courselocationchange update
2301 /// </summary>
2302 protected void CheckForSignificantMovement()
2303 {
2304 if (Util.GetDistanceTo(AbsolutePosition, posLastSignificantMove) > 0.5)
2305 {
2306 posLastSignificantMove = AbsolutePosition;
2307 m_scene.EventManager.TriggerSignificantClientMovement(m_controllingClient);
2308 m_scene.NotifyMyCoarseLocationChange();
2309 }
2310
2311 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
2312 if (Util.GetDistanceTo(AbsolutePosition,m_LastChildAgentUpdatePosition) > 32)
2313 {
2314 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
2315 cadu.ActiveGroupID = UUID.Zero.Guid;
2316 cadu.AgentID = UUID.Guid;
2317 cadu.alwaysrun = m_setAlwaysRun;
2318 cadu.AVHeight = m_avHeight;
2319 sLLVector3 tempCameraCenter = new sLLVector3(new Vector3(m_CameraCenter.X, m_CameraCenter.Y, m_CameraCenter.Z));
2320 cadu.cameraPosition = tempCameraCenter;
2321 cadu.drawdistance = m_DrawDistance;
2322 if (m_scene.Permissions.IsGod(new UUID(cadu.AgentID)))
2323 cadu.godlevel = m_godlevel;
2324 cadu.GroupAccess = 0;
2325 cadu.Position = new sLLVector3(AbsolutePosition);
2326 cadu.regionHandle = m_scene.RegionInfo.RegionHandle;
2327 float multiplier = 1;
2328 int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
2329 if (innacurateNeighbors != 0)
2330 {
2331 multiplier = 1f / (float)innacurateNeighbors;
2332 }
2333 if (multiplier <= 0f)
2334 {
2335 multiplier = 0.25f;
2336 }
2337
2338 //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
2339 cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
2340 cadu.Velocity = new sLLVector3(Velocity);
2341
2342 AgentPosition agentpos = new AgentPosition();
2343 agentpos.CopyFrom(cadu);
2344
2345 m_scene.SendOutChildAgentUpdates(agentpos, this);
2346
2347 m_LastChildAgentUpdatePosition.X = AbsolutePosition.X;
2348 m_LastChildAgentUpdatePosition.Y = AbsolutePosition.Y;
2349 m_LastChildAgentUpdatePosition.Z = AbsolutePosition.Z;
2350 }
2351 }
2352
2353 #endregion
2354
2355 #region Border Crossing Methods
2356
2357 /// <summary>
2358 /// Checks to see if the avatar is in range of a border and calls CrossToNewRegion
2359 /// </summary>
2360 protected void CheckForBorderCrossing()
2361 {
2362 if (IsChildAgent)
2363 return;
2364
2365 Vector3 pos2 = AbsolutePosition;
2366 Vector3 vel = Velocity;
2367
2368 float timeStep = 0.1f;
2369 pos2.X = pos2.X + (vel.X*timeStep);
2370 pos2.Y = pos2.Y + (vel.Y*timeStep);
2371 pos2.Z = pos2.Z + (vel.Z*timeStep);
2372
2373 if ((pos2.X < 0) || (pos2.X > Constants.RegionSize))
2374 {
2375 CrossToNewRegion();
2376 }
2377
2378 if ((pos2.Y < 0) || (pos2.Y > Constants.RegionSize))
2379 {
2380 CrossToNewRegion();
2381 }
2382 }
2383
2384 /// <summary>
2385 /// Moves the agent outside the region bounds
2386 /// Tells neighbor region that we're crossing to it
2387 /// If the neighbor accepts, remove the agent's viewable avatar from this scene
2388 /// set them to a child agent.
2389 /// </summary>
2390 protected void CrossToNewRegion()
2391 {
2392 Vector3 pos = AbsolutePosition;
2393 Vector3 newpos = new Vector3(pos.X, pos.Y, pos.Z);
2394 uint neighbourx = m_regionInfo.RegionLocX;
2395 uint neighboury = m_regionInfo.RegionLocY;
2396
2397 // distance to edge that will trigger crossing
2398 const float boundaryDistance = 1.7f;
2399
2400 // distance into new region to place avatar
2401 const float enterDistance = 0.1f;
2402
2403 if (pos.X < boundaryDistance)
2404 {
2405 neighbourx--;
2406 newpos.X = Constants.RegionSize - enterDistance;
2407 }
2408 else if (pos.X > Constants.RegionSize - boundaryDistance)
2409 {
2410 neighbourx++;
2411 newpos.X = enterDistance;
2412 }
2413
2414 if (pos.Y < boundaryDistance)
2415 {
2416 neighboury--;
2417 newpos.Y = Constants.RegionSize - enterDistance;
2418 }
2419 else if (pos.Y > Constants.RegionSize - boundaryDistance)
2420 {
2421 neighboury++;
2422 newpos.Y = enterDistance;
2423 }
2424
2425 Vector3 vel = m_velocity;
2426 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
2427 SimpleRegionInfo neighbourRegion = m_scene.RequestNeighbouringRegionInfo(neighbourHandle);
2428 if (neighbourRegion != null && ValidateAttachments())
2429 {
2430 // When the neighbour is informed of the border crossing, it will set up CAPS handlers for the avatar
2431 // This means we need to remove the current caps handler here and possibly compensate later,
2432 // in case both scenes are being hosted on the same region server. Messy
2433 //m_scene.RemoveCapsHandler(UUID);
2434 newpos = newpos + (vel);
2435
2436 CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(UUID);
2437 if (userInfo != null)
2438 {
2439 userInfo.DropInventory();
2440 }
2441 else
2442 {
2443 m_log.WarnFormat("[SCENE PRESENCE]: No cached user info found for {0} {1} on leaving region", Name, UUID);
2444 }
2445
2446 bool crossingSuccessful =
2447 m_scene.InformNeighbourOfCrossing(neighbourHandle, m_controllingClient.AgentId, newpos,
2448 m_physicsActor.Flying);
2449 if (crossingSuccessful)
2450 {
2451 // Next, let's close the child agent connections that are too far away.
2452 CloseChildAgents(neighbourx, neighboury);
2453
2454 //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo();
2455 m_controllingClient.RequestClientInfo();
2456
2457 //Console.WriteLine("BEFORE CROSS");
2458 //Scene.DumpChildrenSeeds(UUID);
2459 //DumpKnownRegions();
2460 string agentcaps;
2461 if (!m_knownChildRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
2462 {
2463 m_log.ErrorFormat("[SCENE PRESENCE]: No CAPS information for region handle {0}, exiting CrossToNewRegion.",
2464 neighbourRegion.RegionHandle);
2465 return;
2466 }
2467 // TODO Should construct this behind a method
2468 string capsPath =
2469 "http://" + neighbourRegion.ExternalHostName + ":" + neighbourRegion.HttpPort
2470 + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/";
2471
2472 m_log.DebugFormat("[CAPS]: Sending new CAPS seed url {0} to client {1}", capsPath, m_uuid);
2473
2474 IEventQueue eq = m_scene.RequestModuleInterface<IEventQueue>();
2475 if (eq != null)
2476 {
2477 eq.CrossRegion(neighbourHandle, newpos, vel, neighbourRegion.ExternalEndPoint,
2478 capsPath, UUID, ControllingClient.SessionId);
2479 }
2480 else
2481 {
2482 m_controllingClient.CrossRegion(neighbourHandle, newpos, vel, neighbourRegion.ExternalEndPoint,
2483 capsPath);
2484 }
2485
2486 MakeChildAgent();
2487 // now we have a child agent in this region. Request all interesting data about other (root) agents
2488 SendInitialFullUpdateToAllClients();
2489
2490 CrossAttachmentsIntoNewRegion(neighbourHandle, true);
2491
2492 // m_scene.SendKillObject(m_localId);
2493
2494 m_scene.NotifyMyCoarseLocationChange();
2495 // the user may change their profile information in other region,
2496 // so the userinfo in UserProfileCache is not reliable any more, delete it
2497 if (m_scene.NeedSceneCacheClear(UUID))
2498 {
2499 m_scene.CommsManager.UserProfileCacheService.RemoveUser(UUID);
2500 m_log.DebugFormat(
2501 "[SCENE PRESENCE]: User {0} is going to another region, profile cache removed", UUID);
2502 }
2503 }
2504 else
2505 {
2506 // Restore the user structures that we needed to delete before asking the receiving region to complete the crossing
2507 m_scene.CommsManager.UserProfileCacheService.RequestInventoryForUser(UUID);
2508 m_scene.CapsModule.AddCapsHandler(UUID);
2509 }
2510 }
2511
2512 //Console.WriteLine("AFTER CROSS");
2513 //Scene.DumpChildrenSeeds(UUID);
2514 //DumpKnownRegions();
2515 }
2516
2517 /// <summary>
2518 /// Computes which child agents to close when the scene presence moves to another region.
2519 /// Removes those regions from m_knownRegions.
2520 /// </summary>
2521 /// <param name="newRegionX">The new region's x on the map</param>
2522 /// <param name="newRegionY">The new region's y on the map</param>
2523 /// <returns></returns>
2524 public void CloseChildAgents(uint newRegionX, uint newRegionY)
2525 {
2526 List<ulong> byebyeRegions = new List<ulong>();
2527 m_log.DebugFormat(
2528 "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}",
2529 m_knownChildRegions.Keys.Count, Scene.RegionInfo.RegionName);
2530 //DumpKnownRegions();
2531
2532 lock (m_knownChildRegions)
2533 {
2534 foreach (ulong handle in m_knownChildRegions.Keys)
2535 {
2536 // Don't close the agent on this region yet
2537 if (handle != Scene.RegionInfo.RegionHandle)
2538 {
2539 uint x, y;
2540 Utils.LongToUInts(handle, out x, out y);
2541 x = x / Constants.RegionSize;
2542 y = y / Constants.RegionSize;
2543
2544 //Console.WriteLine("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
2545 //Console.WriteLine("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
2546 if (Util.IsOutsideView(x, newRegionX, y, newRegionY))
2547 {
2548 byebyeRegions.Add(handle);
2549 }
2550 }
2551 }
2552 }
2553
2554 if (byebyeRegions.Count > 0)
2555 {
2556 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
2557 m_scene.SceneGridService.SendCloseChildAgentConnections(m_controllingClient.AgentId, byebyeRegions);
2558 }
2559
2560 foreach (ulong handle in byebyeRegions)
2561 {
2562 RemoveNeighbourRegion(handle);
2563 }
2564
2565 }
2566
2567 #endregion
2568
2569 /// <summary>
2570 /// This allows the Sim owner the abiility to kick users from their sim currently.
2571 /// It tells the client that the agent has permission to do so.
2572 /// </summary>
2573 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
2574 {
2575 if (godStatus)
2576 {
2577 // For now, assign god level 200 to anyone
2578 // who is granted god powers, but has no god level set.
2579 //
2580 CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID);
2581 if (profile.UserProfile.GodLevel > 0)
2582 m_godlevel = profile.UserProfile.GodLevel;
2583 else
2584 m_godlevel = 200;
2585 }
2586 else
2587 {
2588 m_godlevel = 0;
2589 }
2590
2591 ControllingClient.SendAdminResponse(token, (uint)m_godlevel);
2592 }
2593
2594 #region Child Agent Updates
2595
2596 public void ChildAgentDataUpdate(AgentData cAgentData)
2597 {
2598 //Console.WriteLine(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
2599 if (!IsChildAgent)
2600 return;
2601
2602 CopyFrom(cAgentData);
2603 }
2604
2605 /// <summary>
2606 /// This updates important decision making data about a child agent
2607 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
2608 /// </summary>
2609 public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
2610 {
2611 if (!IsChildAgent)
2612 return;
2613
2614 //Console.WriteLine(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
2615 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize;
2616 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize;
2617
2618 m_DrawDistance = cAgentData.Far;
2619 if (cAgentData.Position != new Vector3(-1, -1, -1)) // UGH!!
2620 m_pos = new Vector3(cAgentData.Position.X + shiftx, cAgentData.Position.Y + shifty, cAgentData.Position.Z);
2621
2622 // It's hard to say here.. We can't really tell where the camera position is unless it's in world cordinates from the sending region
2623 m_CameraCenter = cAgentData.Center;
2624
2625 m_avHeight = cAgentData.Size.Z;
2626 //SetHeight(cAgentData.AVHeight);
2627
2628 if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0)
2629 ControllingClient.SetChildAgentThrottle(cAgentData.Throttles);
2630
2631 // Sends out the objects in the user's draw distance if m_sendTasksToChild is true.
2632 if (m_scene.m_seeIntoRegionFromNeighbor)
2633 m_pendingObjects = null;
2634
2635 //cAgentData.AVHeight;
2636 //cAgentData.regionHandle;
2637 //m_velocity = cAgentData.Velocity;
2638 }
2639
2640 public void CopyTo(AgentData cAgent)
2641 {
2642 cAgent.AgentID = UUID;
2643 cAgent.RegionHandle = m_scene.RegionInfo.RegionHandle;
2644
2645 cAgent.Position = m_pos;
2646 cAgent.Velocity = m_velocity;
2647 cAgent.Center = m_CameraCenter;
2648 cAgent.Size = new Vector3(0, 0, m_avHeight);
2649 cAgent.AtAxis = m_CameraAtAxis;
2650 cAgent.LeftAxis = m_CameraLeftAxis;
2651 cAgent.UpAxis = m_CameraUpAxis;
2652
2653 cAgent.Far = m_DrawDistance;
2654
2655 // Throttles
2656 float multiplier = 1;
2657 int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
2658 if (innacurateNeighbors != 0)
2659 {
2660 multiplier = 1f / (float)innacurateNeighbors;
2661 }
2662 if (multiplier <= 0f)
2663 {
2664 multiplier = 0.25f;
2665 }
2666 //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
2667 cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
2668
2669 cAgent.HeadRotation = m_headrotation;
2670 cAgent.BodyRotation = m_bodyRot;
2671 cAgent.ControlFlags = m_AgentControlFlags;
2672 if ((m_physicsActor != null) && (m_physicsActor.Flying))
2673 {
2674 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
2675 }
2676
2677 if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
2678 cAgent.GodLevel = (byte)m_godlevel;
2679 else
2680 cAgent.GodLevel = (byte) 0;
2681
2682 cAgent.AlwaysRun = m_setAlwaysRun;
2683
2684 //cAgent.AgentTextures = ???
2685 //cAgent.GroupID = ??
2686 // Groups???
2687
2688 // Animations???
2689
2690 cAgent.VisualParams = m_appearance.VisualParams;
2691 }
2692
2693 public void CopyFrom(AgentData cAgent)
2694 {
2695 m_rootRegionHandle= cAgent.RegionHandle;
2696 m_callbackURI = cAgent.CallbackURI;
2697
2698 m_pos = cAgent.Position;
2699 m_velocity = cAgent.Velocity;
2700 m_CameraCenter = cAgent.Center;
2701 m_avHeight = cAgent.Size.Z;
2702 m_CameraAtAxis = cAgent.AtAxis;
2703 m_CameraLeftAxis = cAgent.LeftAxis;
2704 m_CameraUpAxis = cAgent.UpAxis;
2705
2706 m_DrawDistance = cAgent.Far;
2707
2708 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
2709 ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
2710
2711 m_headrotation = cAgent.HeadRotation;
2712 m_bodyRot = cAgent.BodyRotation;
2713 m_AgentControlFlags = cAgent.ControlFlags; // We need more flags!
2714 if (m_physicsActor != null)
2715 {
2716 m_physicsActor.Flying = ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
2717 }
2718 if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
2719 m_godlevel = cAgent.GodLevel;
2720 m_setAlwaysRun = cAgent.AlwaysRun;
2721
2722 //cAgent.AgentTextures = ???
2723
2724 //cAgent.GroupID = ??
2725 //Groups???
2726
2727 // Animations???
2728
2729 m_appearance.VisualParams = cAgent.VisualParams;
2730 }
2731
2732 #endregion Child Agent Updates
2733
2734 /// <summary>
2735 /// Handles part of the PID controller function for moving an avatar.
2736 /// </summary>
2737 public override void UpdateMovement()
2738 {
2739 m_newForce = false;
2740 lock (m_forcesList)
2741 {
2742 if (m_forcesList.Count > 0)
2743 {
2744 for (int i = 0; i < m_forcesList.Count; i++)
2745 {
2746 NewForce force = m_forcesList[i];
2747
2748 m_updateflag = true;
2749 try
2750 {
2751 movementvector.X = force.X;
2752 movementvector.Y = force.Y;
2753 movementvector.Z = force.Z;
2754 Velocity = movementvector;
2755 }
2756 catch (NullReferenceException)
2757 {
2758 // Under extreme load, this returns a NullReference Exception that we can ignore.
2759 // Ignoring this causes no movement to be sent to the physics engine...
2760 // which when the scene is moving at 1 frame every 10 seconds, it doesn't really matter!
2761 }
2762 m_newForce = true;
2763 }
2764 for (int i = 0; i < m_forcesList.Count; i++)
2765 {
2766 m_forcesList.RemoveAt(0);
2767 }
2768 }
2769 }
2770 }
2771
2772 static ScenePresence()
2773 {
2774 Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture();
2775 DefaultTexture = textu.ToBytes();
2776 }
2777
2778 [Serializable]
2779 public class NewForce
2780 {
2781 public float X;
2782 public float Y;
2783 public float Z;
2784
2785 public NewForce()
2786 {
2787 }
2788 }
2789
2790 [Serializable]
2791 public class ScenePartUpdate : ISerializable
2792 {
2793 public UUID FullID;
2794 public uint LastFullUpdateTime;
2795 public uint LastTerseUpdateTime;
2796
2797 public ScenePartUpdate()
2798 {
2799 FullID = UUID.Zero;
2800 LastFullUpdateTime = 0;
2801 LastTerseUpdateTime = 0;
2802 }
2803
2804 protected ScenePartUpdate(SerializationInfo info, StreamingContext context)
2805 {
2806 //System.Console.WriteLine("ScenePartUpdate Deserialize BGN");
2807
2808 if (info == null)
2809 {
2810 throw new ArgumentNullException("info");
2811 }
2812
2813 FullID = new UUID((Guid)info.GetValue("FullID", typeof(Guid)));
2814 LastFullUpdateTime = (uint)info.GetValue("LastFullUpdateTime", typeof(uint));
2815 LastTerseUpdateTime = (uint)info.GetValue("LastTerseUpdateTime", typeof(uint));
2816
2817 //System.Console.WriteLine("ScenePartUpdate Deserialize END");
2818 }
2819
2820 [SecurityPermission(SecurityAction.LinkDemand,
2821 Flags = SecurityPermissionFlag.SerializationFormatter)]
2822 public virtual void GetObjectData(
2823 SerializationInfo info, StreamingContext context)
2824 {
2825 if (info == null)
2826 {
2827 throw new ArgumentNullException("info");
2828 }
2829
2830 info.AddValue("FullID", FullID.Guid);
2831 info.AddValue("LastFullUpdateTime", LastFullUpdateTime);
2832 info.AddValue("LastTerseUpdateTime", LastTerseUpdateTime);
2833 }
2834 }
2835
2836 public override void SetText(string text, Vector3 color, double alpha)
2837 {
2838 throw new Exception("Can't set Text on avatar.");
2839 }
2840
2841 /// <summary>
2842 /// Adds a physical representation of the avatar to the Physics plugin
2843 /// </summary>
2844 public void AddToPhysicalScene()
2845 {
2846 PhysicsScene scene = m_scene.PhysicsScene;
2847
2848 PhysicsVector pVec =
2849 new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y,
2850 AbsolutePosition.Z);
2851
2852 if (m_avHeight == 127.0f)
2853 {
2854 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, new PhysicsVector(0, 0, 1.56f));
2855 }
2856 else
2857 {
2858 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, new PhysicsVector(0, 0, m_avHeight));
2859 }
2860
2861 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
2862 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
2863 m_physicsActor.SubscribeEvents(1000);
2864 m_physicsActor.LocalID = LocalId;
2865 }
2866
2867 // Event called by the physics plugin to tell the avatar about a collision.
2868 private void PhysicsCollisionUpdate(EventArgs e)
2869 {
2870 if (e == null)
2871 return;
2872 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
2873 Dictionary<uint, float> coldata = collisionData.m_objCollisionList;
2874 float starthealth = Health;
2875 uint killerObj = 0;
2876 foreach (uint localid in coldata.Keys)
2877 {
2878 if (coldata[localid] <= 0.10f || m_invulnerable)
2879 continue;
2880 //if (localid == 0)
2881 //continue;
2882
2883 Health -= coldata[localid] * 5;
2884
2885 if (Health <= 0)
2886 {
2887 if (localid != 0)
2888 killerObj = localid;
2889 }
2890 //m_log.Debug("[AVATAR]: Collision with localid: " + localid.ToString() + " at depth: " + coldata[localid].ToString());
2891 }
2892 //Health = 100;
2893 if (!m_invulnerable)
2894 {
2895 if (starthealth != Health)
2896 {
2897 ControllingClient.SendHealth(Health);
2898 }
2899 if (m_health <= 0)
2900 m_scene.EventManager.TriggerAvatarKill(killerObj, this);
2901 }
2902
2903 if (Velocity.X > 0 || Velocity.Y > 0)
2904 UpdateMovementAnimations();
2905 }
2906
2907 public void setHealthWithUpdate(float health)
2908 {
2909 Health = health;
2910 ControllingClient.SendHealth(Health);
2911 }
2912
2913 public void Close()
2914 {
2915 lock (m_attachments)
2916 {
2917 // Delete attachments from scene
2918 // Don't try to save, as this thread won't live long
2919 // enough to complete the save. This would cause no copy
2920 // attachments to poof!
2921 //
2922 foreach (SceneObjectGroup grp in m_attachments)
2923 {
2924 m_scene.DeleteSceneObject(grp, false);
2925 }
2926 m_attachments.Clear();
2927 }
2928 lock (m_knownChildRegions)
2929 {
2930 m_knownChildRegions.Clear();
2931 }
2932 lock (m_updateTimes)
2933 {
2934 m_updateTimes.Clear();
2935 }
2936 lock (m_partsUpdateQueue)
2937 {
2938 m_partsUpdateQueue.Clear();
2939 }
2940
2941 RemoveFromPhysicalScene();
2942 GC.Collect();
2943 }
2944
2945 public ScenePresence()
2946 {
2947/* JB
2948 if (Animations == null)
2949 {
2950 Animations = new AvatarAnimations();
2951 Animations.LoadAnims();
2952 }
2953*/
2954 if (DefaultTexture == null)
2955 {
2956 Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture();
2957 DefaultTexture = textu.ToBytes();
2958 }
2959 }
2960
2961 public void AddAttachment(SceneObjectGroup gobj)
2962 {
2963 lock (m_attachments)
2964 {
2965 m_attachments.Add(gobj);
2966 }
2967 }
2968
2969 public bool HasAttachments()
2970 {
2971 return m_attachments.Count > 0;
2972 }
2973
2974 public bool HasScriptedAttachments()
2975 {
2976 lock (m_attachments)
2977 {
2978 foreach (SceneObjectGroup gobj in m_attachments)
2979 {
2980 if (gobj != null)
2981 {
2982 if (gobj.RootPart.Inventory.ContainsScripts())
2983 return true;
2984 }
2985 }
2986 }
2987 return false;
2988 }
2989
2990 public void RemoveAttachment(SceneObjectGroup gobj)
2991 {
2992 lock (m_attachments)
2993 {
2994 if (m_attachments.Contains(gobj))
2995 {
2996 m_attachments.Remove(gobj);
2997 }
2998 }
2999 }
3000
3001 public bool ValidateAttachments()
3002 {
3003 lock (m_attachments)
3004 {
3005 // Validate
3006 foreach (SceneObjectGroup gobj in m_attachments)
3007 {
3008 if (gobj == null)
3009 return false;
3010
3011 if (gobj.IsDeleted)
3012 return false;
3013 }
3014 }
3015 return true;
3016 }
3017
3018 public bool CrossAttachmentsIntoNewRegion(ulong regionHandle, bool silent)
3019 {
3020 lock (m_attachments)
3021 {
3022 // Validate
3023 foreach (SceneObjectGroup gobj in m_attachments)
3024 {
3025 if (gobj == null || gobj.IsDeleted)
3026 return false;
3027 }
3028
3029 foreach (SceneObjectGroup gobj in m_attachments)
3030 {
3031 // If the prim group is null then something must have happened to it!
3032 if (gobj != null && gobj.RootPart != null)
3033 {
3034 // Set the parent localID to 0 so it transfers over properly.
3035 gobj.RootPart.SetParentLocalId(0);
3036 gobj.RootPart.IsAttachment = false;
3037 gobj.AbsolutePosition = gobj.RootPart.AttachedPos;
3038 gobj.RootPart.LastOwnerID = gobj.GetFromAssetID();
3039 m_log.DebugFormat("[ATTACHMENT]: Sending attachment {0} to region {1}", gobj.UUID, regionHandle);
3040 m_scene.CrossPrimGroupIntoNewRegion(regionHandle, gobj, silent);
3041 }
3042 }
3043 m_attachments.Clear();
3044
3045 return true;
3046 }
3047 }
3048
3049 public void initializeScenePresence(IClientAPI client, RegionInfo region, Scene scene)
3050 {
3051 m_controllingClient = client;
3052 m_regionInfo = region;
3053 m_scene = scene;
3054
3055 RegisterToEvents();
3056
3057 /*
3058 AbsolutePosition = client.StartPos;
3059
3060 Animations = new AvatarAnimations();
3061 Animations.LoadAnims();
3062
3063 m_animations = new List<UUID>();
3064 m_animations.Add(Animations.AnimsUUID["STAND"]);
3065 m_animationSeqs.Add(m_controllingClient.NextAnimationSequenceNumber);
3066
3067 SetDirectionVectors();
3068 */
3069 }
3070
3071 protected ScenePresence(SerializationInfo info, StreamingContext context)
3072 : base (info, context)
3073 {
3074 //System.Console.WriteLine("ScenePresence Deserialize BGN");
3075
3076 if (info == null)
3077 {
3078 throw new ArgumentNullException("info");
3079 }
3080/* JB
3081 if (Animations == null)
3082 {
3083 Animations = new AvatarAnimations();
3084 Animations.LoadAnims();
3085 }
3086*/
3087 if (DefaultTexture == null)
3088 {
3089 Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture();
3090 DefaultTexture = textu.ToBytes();
3091 }
3092
3093 m_animations = (AnimationSet)info.GetValue("m_animations", typeof(AnimationSet));
3094 m_updateflag = (bool)info.GetValue("m_updateflag", typeof(bool));
3095 m_movementflag = (byte)info.GetValue("m_movementflag", typeof(byte));
3096 m_forcesList = (List<NewForce>)info.GetValue("m_forcesList", typeof(List<NewForce>));
3097 m_updateCount = (short)info.GetValue("m_updateCount", typeof(short));
3098 m_requestedSitTargetID = (uint)info.GetValue("m_requestedSitTargetID", typeof(uint));
3099
3100 m_requestedSitOffset
3101 = new Vector3(
3102 (float)info.GetValue("m_requestedSitOffset.X", typeof(float)),
3103 (float)info.GetValue("m_requestedSitOffset.Y", typeof(float)),
3104 (float)info.GetValue("m_requestedSitOffset.Z", typeof(float)));
3105
3106 m_sitAvatarHeight = (float)info.GetValue("m_sitAvatarHeight", typeof(float));
3107 m_godlevel = (float)info.GetValue("m_godlevel", typeof(float));
3108 m_setAlwaysRun = (bool)info.GetValue("m_setAlwaysRun", typeof(bool));
3109
3110 m_bodyRot
3111 = new Quaternion(
3112 (float)info.GetValue("m_bodyRot.X", typeof(float)),
3113 (float)info.GetValue("m_bodyRot.Y", typeof(float)),
3114 (float)info.GetValue("m_bodyRot.Z", typeof(float)),
3115 (float)info.GetValue("m_bodyRot.W", typeof(float)));
3116
3117 IsRestrictedToRegion = (bool)info.GetValue("IsRestrictedToRegion", typeof(bool));
3118 m_newForce = (bool)info.GetValue("m_newForce", typeof(bool));
3119 //m_newAvatar = (bool)info.GetValue("m_newAvatar", typeof(bool));
3120 m_newCoarseLocations = (bool)info.GetValue("m_newCoarseLocations", typeof(bool));
3121 m_avHeight = (float)info.GetValue("m_avHeight", typeof(float));
3122 crossingFromRegion = (ulong)info.GetValue("crossingFromRegion", typeof(ulong));
3123
3124 List<float[]> Dir_Vectors_work = (List<float[]>)info.GetValue("Dir_Vectors", typeof(List<float[]>));
3125 List<Vector3> Dir_Vectors_work2 = new List<Vector3>();
3126
3127 foreach (float[] f3 in Dir_Vectors_work)
3128 {
3129 Dir_Vectors_work2.Add(new Vector3(f3[0], f3[1], f3[2]));
3130 }
3131
3132 Dir_Vectors = Dir_Vectors_work2.ToArray();
3133
3134 lastPhysPos
3135 = new Vector3(
3136 (float)info.GetValue("lastPhysPos.X", typeof(float)),
3137 (float)info.GetValue("lastPhysPos.Y", typeof(float)),
3138 (float)info.GetValue("lastPhysPos.Z", typeof(float)));
3139
3140 // Possibly we should store lastPhysRot. But there may well be not much point since rotation changes
3141 // wouldn't carry us across borders anyway
3142
3143 m_CameraCenter
3144 = new Vector3(
3145 (float)info.GetValue("m_CameraCenter.X", typeof(float)),
3146 (float)info.GetValue("m_CameraCenter.Y", typeof(float)),
3147 (float)info.GetValue("m_CameraCenter.Z", typeof(float)));
3148
3149 m_CameraAtAxis
3150 = new Vector3(
3151 (float)info.GetValue("m_CameraAtAxis.X", typeof(float)),
3152 (float)info.GetValue("m_CameraAtAxis.Y", typeof(float)),
3153 (float)info.GetValue("m_CameraAtAxis.Z", typeof(float)));
3154
3155 m_CameraLeftAxis
3156 = new Vector3(
3157 (float)info.GetValue("m_CameraLeftAxis.X", typeof(float)),
3158 (float)info.GetValue("m_CameraLeftAxis.Y", typeof(float)),
3159 (float)info.GetValue("m_CameraLeftAxis.Z", typeof(float)));
3160
3161 m_CameraUpAxis
3162 = new Vector3(
3163 (float)info.GetValue("m_CameraUpAxis.X", typeof(float)),
3164 (float)info.GetValue("m_CameraUpAxis.Y", typeof(float)),
3165 (float)info.GetValue("m_CameraUpAxis.Z", typeof(float)));
3166
3167 m_DrawDistance = (float)info.GetValue("m_DrawDistance", typeof(float));
3168 m_appearance = (AvatarAppearance)info.GetValue("m_appearance", typeof(AvatarAppearance));
3169
3170 m_knownChildRegions = (Dictionary<ulong, string>)info.GetValue("m_knownChildRegions", typeof(Dictionary<ulong, string>));
3171
3172 posLastSignificantMove
3173 = new Vector3(
3174 (float)info.GetValue("posLastSignificantMove.X", typeof(float)),
3175 (float)info.GetValue("posLastSignificantMove.Y", typeof(float)),
3176 (float)info.GetValue("posLastSignificantMove.Z", typeof(float)));
3177
3178 // m_partsUpdateQueue = (UpdateQueue)info.GetValue("m_partsUpdateQueue", typeof(UpdateQueue));
3179
3180 /*
3181 Dictionary<Guid, ScenePartUpdate> updateTimes_work
3182 = (Dictionary<Guid, ScenePartUpdate>)info.GetValue("m_updateTimes", typeof(Dictionary<Guid, ScenePartUpdate>));
3183
3184 foreach (Guid id in updateTimes_work.Keys)
3185 {
3186 m_updateTimes.Add(new UUID(id), updateTimes_work[id]);
3187 }
3188 */
3189 m_regionHandle = (ulong)info.GetValue("m_regionHandle", typeof(ulong));
3190 m_firstname = (string)info.GetValue("m_firstname", typeof(string));
3191 m_lastname = (string)info.GetValue("m_lastname", typeof(string));
3192 m_allowMovement = (bool)info.GetValue("m_allowMovement", typeof(bool));
3193 m_parentPosition = new Vector3((float)info.GetValue("m_parentPosition.X", typeof(float)),
3194 (float)info.GetValue("m_parentPosition.Y", typeof(float)),
3195 (float)info.GetValue("m_parentPosition.Z", typeof(float)));
3196
3197 m_isChildAgent = (bool)info.GetValue("m_isChildAgent", typeof(bool));
3198 m_parentID = (uint)info.GetValue("m_parentID", typeof(uint));
3199
3200// for OpenSim_v0.5
3201 currentParcelUUID = new UUID((Guid)info.GetValue("currentParcelUUID", typeof(Guid)));
3202
3203 lastKnownAllowedPosition
3204 = new Vector3(
3205 (float)info.GetValue("lastKnownAllowedPosition.X", typeof(float)),
3206 (float)info.GetValue("lastKnownAllowedPosition.Y", typeof(float)),
3207 (float)info.GetValue("lastKnownAllowedPosition.Z", typeof(float)));
3208
3209 sentMessageAboutRestrictedParcelFlyingDown = (bool)info.GetValue("sentMessageAboutRestrictedParcelFlyingDown", typeof(bool));
3210
3211 m_LastChildAgentUpdatePosition
3212 = new Vector3(
3213 (float)info.GetValue("m_LastChildAgentUpdatePosition.X", typeof(float)),
3214 (float)info.GetValue("m_LastChildAgentUpdatePosition.Y", typeof(float)),
3215 (float)info.GetValue("m_LastChildAgentUpdatePosition.Z", typeof(float)));
3216
3217 m_perfMonMS = (int)info.GetValue("m_perfMonMS", typeof(int));
3218 m_AgentControlFlags = (uint)info.GetValue("m_AgentControlFlags", typeof(uint));
3219
3220 m_headrotation
3221 = new Quaternion(
3222 (float)info.GetValue("m_headrotation.X", typeof(float)),
3223 (float)info.GetValue("m_headrotation.Y", typeof(float)),
3224 (float)info.GetValue("m_headrotation.Z", typeof(float)),
3225 (float)info.GetValue("m_headrotation.W", typeof(float)));
3226
3227 m_state = (byte)info.GetValue("m_state", typeof(byte));
3228
3229 //System.Console.WriteLine("ScenePresence Deserialize END");
3230 }
3231
3232 [SecurityPermission(SecurityAction.LinkDemand,
3233 Flags = SecurityPermissionFlag.SerializationFormatter)]
3234 public override void GetObjectData(
3235 SerializationInfo info, StreamingContext context)
3236 {
3237 if (info == null)
3238 {
3239 throw new ArgumentNullException("info");
3240 }
3241
3242 base.GetObjectData(info, context);
3243
3244 info.AddValue("m_animations", m_animations);
3245 info.AddValue("m_updateflag", m_updateflag);
3246 info.AddValue("m_movementflag", m_movementflag);
3247 info.AddValue("m_forcesList", m_forcesList);
3248 info.AddValue("m_updateCount", m_updateCount);
3249 info.AddValue("m_requestedSitTargetID", m_requestedSitTargetID);
3250
3251 // Vector3
3252 info.AddValue("m_requestedSitOffset.X", m_requestedSitOffset.X);
3253 info.AddValue("m_requestedSitOffset.Y", m_requestedSitOffset.Y);
3254 info.AddValue("m_requestedSitOffset.Z", m_requestedSitOffset.Z);
3255
3256 info.AddValue("m_sitAvatarHeight", m_sitAvatarHeight);
3257 info.AddValue("m_godlevel", m_godlevel);
3258 info.AddValue("m_setAlwaysRun", m_setAlwaysRun);
3259
3260 // Quaternion
3261 info.AddValue("m_bodyRot.X", m_bodyRot.X);
3262 info.AddValue("m_bodyRot.Y", m_bodyRot.Y);
3263 info.AddValue("m_bodyRot.Z", m_bodyRot.Z);
3264 info.AddValue("m_bodyRot.W", m_bodyRot.W);
3265
3266 info.AddValue("IsRestrictedToRegion", IsRestrictedToRegion);
3267 info.AddValue("m_newForce", m_newForce);
3268 //info.AddValue("m_newAvatar", m_newAvatar);
3269 info.AddValue("m_newCoarseLocations", m_newCoarseLocations);
3270 info.AddValue("m_gotAPrimitivesInScene", false);
3271 info.AddValue("m_avHeight", m_avHeight);
3272
3273 // info.AddValue("m_regionInfo", m_regionInfo);
3274
3275 info.AddValue("crossingFromRegion", crossingFromRegion);
3276
3277 List<float[]> Dir_Vectors_work = new List<float[]>();
3278
3279 foreach (Vector3 v3 in Dir_Vectors)
3280 {
3281 Dir_Vectors_work.Add(new float[] { v3.X, v3.Y, v3.Z });
3282 }
3283
3284 info.AddValue("Dir_Vectors", Dir_Vectors_work);
3285
3286 // Vector3
3287 info.AddValue("lastPhysPos.X", lastPhysPos.X);
3288 info.AddValue("lastPhysPos.Y", lastPhysPos.Y);
3289 info.AddValue("lastPhysPos.Z", lastPhysPos.Z);
3290
3291 // Possibly we should retrieve lastPhysRot. But there may well be not much point since rotation changes
3292 // wouldn't carry us across borders anyway
3293
3294 // Vector3
3295 info.AddValue("m_CameraCenter.X", m_CameraCenter.X);
3296 info.AddValue("m_CameraCenter.Y", m_CameraCenter.Y);
3297 info.AddValue("m_CameraCenter.Z", m_CameraCenter.Z);
3298
3299 // Vector3
3300 info.AddValue("m_CameraAtAxis.X", m_CameraAtAxis.X);
3301 info.AddValue("m_CameraAtAxis.Y", m_CameraAtAxis.Y);
3302 info.AddValue("m_CameraAtAxis.Z", m_CameraAtAxis.Z);
3303
3304 // Vector3
3305 info.AddValue("m_CameraLeftAxis.X", m_CameraLeftAxis.X);
3306 info.AddValue("m_CameraLeftAxis.Y", m_CameraLeftAxis.Y);
3307 info.AddValue("m_CameraLeftAxis.Z", m_CameraLeftAxis.Z);
3308
3309 // Vector3
3310 info.AddValue("m_CameraUpAxis.X", m_CameraUpAxis.X);
3311 info.AddValue("m_CameraUpAxis.Y", m_CameraUpAxis.Y);
3312 info.AddValue("m_CameraUpAxis.Z", m_CameraUpAxis.Z);
3313
3314 info.AddValue("m_DrawDistance", m_DrawDistance);
3315 info.AddValue("m_appearance", m_appearance);
3316 info.AddValue("m_knownChildRegions", m_knownChildRegions);
3317
3318 // Vector3
3319 info.AddValue("posLastSignificantMove.X", posLastSignificantMove.X);
3320 info.AddValue("posLastSignificantMove.Y", posLastSignificantMove.Y);
3321 info.AddValue("posLastSignificantMove.Z", posLastSignificantMove.Z);
3322
3323 //info.AddValue("m_partsUpdateQueue", m_partsUpdateQueue);
3324
3325 /*
3326 Dictionary<Guid, ScenePartUpdate> updateTimes_work = new Dictionary<Guid, ScenePartUpdate>();
3327
3328 foreach (UUID id in m_updateTimes.Keys)
3329 {
3330 updateTimes_work.Add(id.UUID, m_updateTimes[id]);
3331 }
3332
3333 info.AddValue("m_updateTimes", updateTimes_work);
3334 */
3335
3336 info.AddValue("m_regionHandle", m_regionHandle);
3337 info.AddValue("m_firstname", m_firstname);
3338 info.AddValue("m_lastname", m_lastname);
3339 info.AddValue("m_allowMovement", m_allowMovement);
3340 //info.AddValue("m_physicsActor", m_physicsActor);
3341 info.AddValue("m_parentPosition.X", m_parentPosition.X);
3342 info.AddValue("m_parentPosition.Y", m_parentPosition.Y);
3343 info.AddValue("m_parentPosition.Z", m_parentPosition.Z);
3344 info.AddValue("m_isChildAgent", m_isChildAgent);
3345 info.AddValue("m_parentID", m_parentID);
3346
3347// for OpenSim_v0.5
3348 info.AddValue("currentParcelUUID", currentParcelUUID.Guid);
3349
3350 info.AddValue("lastKnownAllowedPosition.X", lastKnownAllowedPosition.X);
3351 info.AddValue("lastKnownAllowedPosition.Y", lastKnownAllowedPosition.Y);
3352 info.AddValue("lastKnownAllowedPosition.Z", lastKnownAllowedPosition.Z);
3353
3354 info.AddValue("sentMessageAboutRestrictedParcelFlyingDown", sentMessageAboutRestrictedParcelFlyingDown);
3355
3356 info.AddValue("m_LastChildAgentUpdatePosition.X", m_LastChildAgentUpdatePosition.X);
3357 info.AddValue("m_LastChildAgentUpdatePosition.Y", m_LastChildAgentUpdatePosition.Y);
3358 info.AddValue("m_LastChildAgentUpdatePosition.Z", m_LastChildAgentUpdatePosition.Z);
3359
3360 info.AddValue("m_perfMonMS", m_perfMonMS);
3361 info.AddValue("m_AgentControlFlags", m_AgentControlFlags);
3362
3363 info.AddValue("m_headrotation.W", m_headrotation.W);
3364 info.AddValue("m_headrotation.X", m_headrotation.X);
3365 info.AddValue("m_headrotation.Y", m_headrotation.Y);
3366 info.AddValue("m_headrotation.Z", m_headrotation.Z);
3367
3368 info.AddValue("m_state", m_state);
3369
3370 List<Guid> knownPrimUUID_work = new List<Guid>();
3371
3372 info.AddValue("m_knownPrimUUID", knownPrimUUID_work);
3373 }
3374
3375 internal void PushForce(PhysicsVector impulse)
3376 {
3377 if (PhysicsActor != null)
3378 {
3379 PhysicsActor.AddForce(impulse,true);
3380 }
3381 }
3382
3383 public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID)
3384 {
3385 ScriptControllers obj = new ScriptControllers();
3386 obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
3387 obj.eventControls = ScriptControlled.CONTROL_ZERO;
3388
3389 obj.itemID = Script_item_UUID;
3390 obj.objID = Obj_localID;
3391 if (pass_on == 0 && accept == 0)
3392 {
3393 IgnoredControls |= (ScriptControlled)controls;
3394 obj.ignoreControls = (ScriptControlled)controls;
3395 }
3396
3397 if (pass_on == 0 && accept == 1)
3398 {
3399 IgnoredControls |= (ScriptControlled)controls;
3400 obj.ignoreControls = (ScriptControlled)controls;
3401 obj.eventControls = (ScriptControlled)controls;
3402 }
3403 if (pass_on == 1 && accept == 1)
3404 {
3405 IgnoredControls = ScriptControlled.CONTROL_ZERO;
3406 obj.eventControls = (ScriptControlled)controls;
3407 obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
3408 }
3409
3410 lock (scriptedcontrols)
3411 {
3412 if (pass_on == 1 && accept == 0)
3413 {
3414 IgnoredControls &= ~(ScriptControlled)controls;
3415 if (scriptedcontrols.ContainsKey(Script_item_UUID))
3416 scriptedcontrols.Remove(Script_item_UUID);
3417
3418 }
3419 else
3420 {
3421
3422 if (scriptedcontrols.ContainsKey(Script_item_UUID))
3423 {
3424 scriptedcontrols[Script_item_UUID] = obj;
3425 }
3426 else
3427 {
3428 scriptedcontrols.Add(Script_item_UUID, obj);
3429 }
3430 }
3431 }
3432 ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true);
3433 }
3434
3435 public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID)
3436 {
3437 IgnoredControls = ScriptControlled.CONTROL_ZERO;
3438 lock (scriptedcontrols)
3439 {
3440 scriptedcontrols.Clear();
3441 }
3442 ControllingClient.SendTakeControls(int.MaxValue, false, false);
3443 }
3444
3445 public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID)
3446 {
3447 lock (scriptedcontrols)
3448 {
3449 if (scriptedcontrols.ContainsKey(Script_item_UUID))
3450 {
3451 ScriptControllers takecontrolls = scriptedcontrols[Script_item_UUID];
3452 ScriptControlled sctc = takecontrolls.eventControls;
3453 ControllingClient.SendTakeControls((int)sctc, false, false);
3454 ControllingClient.SendTakeControls((int)sctc, true, false);
3455
3456 scriptedcontrols.Remove(Script_item_UUID);
3457 IgnoredControls = ScriptControlled.CONTROL_ZERO;
3458 foreach (ScriptControllers scData in scriptedcontrols.Values)
3459 {
3460 IgnoredControls |= scData.ignoreControls;
3461 }
3462 }
3463
3464 }
3465 }
3466
3467 internal void SendControlToScripts(uint flags)
3468 {
3469
3470 ScriptControlled allflags = ScriptControlled.CONTROL_ZERO;
3471
3472 if (MouseDown)
3473 {
3474 allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON);
3475 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0)
3476 {
3477 allflags = ScriptControlled.CONTROL_ZERO;
3478 MouseDown = true;
3479 }
3480 }
3481
3482 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0)
3483 {
3484 allflags |= ScriptControlled.CONTROL_ML_LBUTTON;
3485 MouseDown = true;
3486 }
3487 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0)
3488 {
3489 allflags |= ScriptControlled.CONTROL_LBUTTON;
3490 MouseDown = true;
3491 }
3492
3493 // find all activated controls, whether the scripts are interested in them or not
3494 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0)
3495 {
3496 allflags |= ScriptControlled.CONTROL_FWD;
3497 }
3498 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0)
3499 {
3500 allflags |= ScriptControlled.CONTROL_BACK;
3501 }
3502 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0)
3503 {
3504 allflags |= ScriptControlled.CONTROL_UP;
3505 }
3506 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)
3507 {
3508 allflags |= ScriptControlled.CONTROL_DOWN;
3509 }
3510 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) != 0)
3511 {
3512 allflags |= ScriptControlled.CONTROL_LEFT;
3513 }
3514 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0)
3515 {
3516 allflags |= ScriptControlled.CONTROL_RIGHT;
3517 }
3518 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
3519 {
3520 allflags |= ScriptControlled.CONTROL_ROT_RIGHT;
3521 }
3522 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
3523 {
3524 allflags |= ScriptControlled.CONTROL_ROT_LEFT;
3525 }
3526 // optimization; we have to check per script, but if nothing is pressed and nothing changed, we can skip that
3527 if (allflags != ScriptControlled.CONTROL_ZERO || allflags != LastCommands)
3528 {
3529 lock (scriptedcontrols)
3530 {
3531 foreach (UUID scriptUUID in scriptedcontrols.Keys)
3532 {
3533 ScriptControllers scriptControlData = scriptedcontrols[scriptUUID];
3534 ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us
3535 ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle
3536 ScriptControlled localChange = localHeld ^ localLast; // the changed bits
3537 if (localHeld != ScriptControlled.CONTROL_ZERO || localChange != ScriptControlled.CONTROL_ZERO)
3538 {
3539 // only send if still pressed or just changed
3540 m_scene.EventManager.TriggerControlEvent(scriptControlData.objID, scriptUUID, UUID, (uint)localHeld, (uint)localChange);
3541 }
3542 }
3543 }
3544 }
3545
3546 LastCommands = allflags;
3547 }
3548
3549 internal uint RemoveIgnoredControls(uint flags, ScriptControlled Ignored)
3550 {
3551 if (Ignored == ScriptControlled.CONTROL_ZERO)
3552 return flags;
3553 if ((Ignored & ScriptControlled.CONTROL_BACK) != 0)
3554 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG);
3555 if ((Ignored & ScriptControlled.CONTROL_FWD) != 0)
3556 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS);
3557 if ((Ignored & ScriptControlled.CONTROL_DOWN) != 0)
3558 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG);
3559 if ((Ignored & ScriptControlled.CONTROL_UP) != 0)
3560 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS | (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS);
3561 if ((Ignored & ScriptControlled.CONTROL_LEFT) != 0)
3562 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS);
3563 if ((Ignored & ScriptControlled.CONTROL_RIGHT) != 0)
3564 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG);
3565 if ((Ignored & ScriptControlled.CONTROL_ROT_LEFT) != 0)
3566 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG);
3567 if ((Ignored & ScriptControlled.CONTROL_ROT_RIGHT) != 0)
3568 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS);
3569 if ((Ignored & ScriptControlled.CONTROL_ML_LBUTTON) != 0)
3570 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN);
3571 if ((Ignored & ScriptControlled.CONTROL_LBUTTON) != 0)
3572 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP | (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN);
3573 //DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
3574 //DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
3575 //DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
3576 //DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
3577 //DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
3578 //DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
3579 //DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
3580 return flags;
3581 }
3582
3583 private void ItemReceived(UUID itemID)
3584 {
3585 if (IsChildAgent)
3586 return;
3587
3588 if (null == m_appearance)
3589 {
3590 m_log.Warn("[ATTACHMENT] Appearance has not been initialized");
3591 return;
3592 }
3593
3594 int attachpoint = m_appearance.GetAttachpoint(itemID);
3595 if (attachpoint == 0)
3596 return;
3597
3598 UUID asset = m_appearance.GetAttachedAsset(attachpoint);
3599 if (UUID.Zero == asset) // We have just logged in
3600 {
3601 try
3602 {
3603 // Rez from inventory
3604 asset = m_scene.RezSingleAttachment(ControllingClient,
3605 itemID, (uint)attachpoint);
3606 // Corner case: We are not yet a Scene Entity
3607 // Setting attachment info in RezSingleAttachment will fail
3608 // Set it here
3609 //
3610 m_appearance.SetAttachment((int)attachpoint, itemID,
3611 asset);
3612 m_log.InfoFormat("[ATTACHMENT] Rezzed attachment {0}, inworld asset {1}",
3613 itemID.ToString(), asset);
3614
3615 }
3616 catch (Exception e)
3617 {
3618 m_log.ErrorFormat("[ATTACHMENT] Unable to rez attachment: {0}", e.ToString());
3619 }
3620
3621 return;
3622 }
3623
3624 SceneObjectPart att = m_scene.GetSceneObjectPart(asset);
3625
3626
3627 // If this is null, then the asset has not yet appeared in world
3628 // so we revisit this when it does
3629 //
3630 if (att != null && att.UUID != asset) // Yes. It's really needed
3631 {
3632 m_log.DebugFormat("[ATTACHMENT]: Attach from in world: ItemID {0}, Asset ID {1}, Attachment inworld: {2}", itemID.ToString(), asset.ToString(), att.UUID.ToString());
3633
3634 // This will throw if crossing katty-korner
3635 // So catch it here to avoid the noid
3636 //
3637 try
3638 {
3639 // Attach from world, if not already attached
3640 if (att.ParentGroup != null && !att.IsAttachment)
3641 m_scene.AttachObject(ControllingClient, att.ParentGroup.LocalId, (uint)0, Quaternion.Identity, att.ParentGroup.AbsolutePosition, false);
3642 }
3643 catch (NullReferenceException)
3644 {
3645 }
3646 }
3647 }
3648 }
3649}