corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) 2006-2014, openmetaverse.org
3 * All rights reserved.
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 *
8 * - Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * - Neither the name of the openmetaverse.org nor the names
11 * of its contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26  
27 using System;
28 using System.Net;
29 using System.Text;
30 using System.Text.RegularExpressions;
31 using System.Threading;
32 using System.Reflection;
33 using System.Collections.Generic;
34 using OpenMetaverse.StructuredData;
35 using OpenMetaverse.Http;
36 using OpenMetaverse.Assets;
37 using OpenMetaverse.Packets;
38 using OpenMetaverse.Interfaces;
39 using OpenMetaverse.Messages.Linden;
40  
41 namespace OpenMetaverse
42 {
43 #region Enums
44  
45 /// <summary>
46 /// Permission request flags, asked when a script wants to control an Avatar
47 /// </summary>
48 [Flags]
49 public enum ScriptPermission : int
50 {
51 /// <summary>Placeholder for empty values, shouldn't ever see this</summary>
52 None = 0,
53 /// <summary>Script wants ability to take money from you</summary>
54 Debit = 1 << 1,
55 /// <summary>Script wants to take camera controls for you</summary>
56 TakeControls = 1 << 2,
57 /// <summary>Script wants to remap avatars controls</summary>
58 RemapControls = 1 << 3,
59 /// <summary>Script wants to trigger avatar animations</summary>
60 /// <remarks>This function is not implemented on the grid</remarks>
61 TriggerAnimation = 1 << 4,
62 /// <summary>Script wants to attach or detach the prim or primset to your avatar</summary>
63 Attach = 1 << 5,
64 /// <summary>Script wants permission to release ownership</summary>
65 /// <remarks>This function is not implemented on the grid
66 /// The concept of "public" objects does not exist anymore.</remarks>
67 ReleaseOwnership = 1 << 6,
68 /// <summary>Script wants ability to link/delink with other prims</summary>
69 ChangeLinks = 1 << 7,
70 /// <summary>Script wants permission to change joints</summary>
71 /// <remarks>This function is not implemented on the grid</remarks>
72 ChangeJoints = 1 << 8,
73 /// <summary>Script wants permissions to change permissions</summary>
74 /// <remarks>This function is not implemented on the grid</remarks>
75 ChangePermissions = 1 << 9,
76 /// <summary>Script wants to track avatars camera position and rotation </summary>
77 TrackCamera = 1 << 10,
78 /// <summary>Script wants to control your camera</summary>
79 ControlCamera = 1 << 11,
80 /// <summary>Script wants the ability to teleport you</summary>
81 Teleport = 1 << 12
82 }
83  
84 /// <summary>
85 /// Special commands used in Instant Messages
86 /// </summary>
87 public enum InstantMessageDialog : byte
88 {
89 /// <summary>Indicates a regular IM from another agent</summary>
90 MessageFromAgent = 0,
91 /// <summary>Simple notification box with an OK button</summary>
92 MessageBox = 1,
93 // <summary>Used to show a countdown notification with an OK
94 // button, deprecated now</summary>
95 //[Obsolete]
96 //MessageBoxCountdown = 2,
97 /// <summary>You've been invited to join a group.</summary>
98 GroupInvitation = 3,
99 /// <summary>Inventory offer</summary>
100 InventoryOffered = 4,
101 /// <summary>Accepted inventory offer</summary>
102 InventoryAccepted = 5,
103 /// <summary>Declined inventory offer</summary>
104 InventoryDeclined = 6,
105 /// <summary>Group vote</summary>
106 GroupVote = 7,
107 // <summary>A message to everyone in the agent's group, no longer
108 // used</summary>
109 //[Obsolete]
110 //DeprecatedGroupMessage = 8,
111 /// <summary>An object is offering its inventory</summary>
112 TaskInventoryOffered = 9,
113 /// <summary>Accept an inventory offer from an object</summary>
114 TaskInventoryAccepted = 10,
115 /// <summary>Decline an inventory offer from an object</summary>
116 TaskInventoryDeclined = 11,
117 /// <summary>Unknown</summary>
118 NewUserDefault = 12,
119 /// <summary>Start a session, or add users to a session</summary>
120 SessionAdd = 13,
121 /// <summary>Start a session, but don't prune offline users</summary>
122 SessionOfflineAdd = 14,
123 /// <summary>Start a session with your group</summary>
124 SessionGroupStart = 15,
125 /// <summary>Start a session without a calling card (finder or objects)</summary>
126 SessionCardlessStart = 16,
127 /// <summary>Send a message to a session</summary>
128 SessionSend = 17,
129 /// <summary>Leave a session</summary>
130 SessionDrop = 18,
131 /// <summary>Indicates that the IM is from an object</summary>
132 MessageFromObject = 19,
133 /// <summary>Sent an IM to a busy user, this is the auto response</summary>
134 BusyAutoResponse = 20,
135 /// <summary>Shows the message in the console and chat history</summary>
136 ConsoleAndChatHistory = 21,
137 /// <summary>Send a teleport lure</summary>
138 RequestTeleport = 22,
139 /// <summary>Response sent to the agent which inititiated a teleport invitation</summary>
140 AcceptTeleport = 23,
141 /// <summary>Response sent to the agent which inititiated a teleport invitation</summary>
142 DenyTeleport = 24,
143 /// <summary>Only useful if you have Linden permissions</summary>
144 GodLikeRequestTeleport = 25,
145 /// <summary>Request a teleport lure</summary>
146 RequestLure = 26,
147 // <summary>Notification of a new group election, this is
148 // deprecated</summary>
149 //[Obsolete]
150 //DeprecatedGroupElection = 27,
151 /// <summary>IM to tell the user to go to an URL</summary>
152 GotoUrl = 28,
153 /// <summary>IM for help</summary>
154 Session911Start = 29,
155 /// <summary>IM sent automatically on call for help, sends a lure
156 /// to each Helper reached</summary>
157 Lure911 = 30,
158 /// <summary>Like an IM but won't go to email</summary>
159 FromTaskAsAlert = 31,
160 /// <summary>IM from a group officer to all group members</summary>
161 GroupNotice = 32,
162 /// <summary>Unknown</summary>
163 GroupNoticeInventoryAccepted = 33,
164 /// <summary>Unknown</summary>
165 GroupNoticeInventoryDeclined = 34,
166 /// <summary>Accept a group invitation</summary>
167 GroupInvitationAccept = 35,
168 /// <summary>Decline a group invitation</summary>
169 GroupInvitationDecline = 36,
170 /// <summary>Unknown</summary>
171 GroupNoticeRequested = 37,
172 /// <summary>An avatar is offering you friendship</summary>
173 FriendshipOffered = 38,
174 /// <summary>An avatar has accepted your friendship offer</summary>
175 FriendshipAccepted = 39,
176 /// <summary>An avatar has declined your friendship offer</summary>
177 FriendshipDeclined = 40,
178 /// <summary>Indicates that a user has started typing</summary>
179 StartTyping = 41,
180 /// <summary>Indicates that a user has stopped typing</summary>
181 StopTyping = 42
182 }
183  
184 /// <summary>
185 /// Flag in Instant Messages, whether the IM should be delivered to
186 /// offline avatars as well
187 /// </summary>
188 public enum InstantMessageOnline
189 {
190 /// <summary>Only deliver to online avatars</summary>
191 Online = 0,
192 /// <summary>If the avatar is offline the message will be held until
193 /// they login next, and possibly forwarded to their e-mail account</summary>
194 Offline = 1
195 }
196  
197 /// <summary>
198 /// Conversion type to denote Chat Packet types in an easier-to-understand format
199 /// </summary>
200 public enum ChatType : byte
201 {
202 /// <summary>Whisper (5m radius)</summary>
203 Whisper = 0,
204 /// <summary>Normal chat (10/20m radius), what the official viewer typically sends</summary>
205 Normal = 1,
206 /// <summary>Shouting! (100m radius)</summary>
207 Shout = 2,
208 // <summary>Say chat (10/20m radius) - The official viewer will
209 // print "[4:15] You say, hey" instead of "[4:15] You: hey"</summary>
210 //[Obsolete]
211 //Say = 3,
212 /// <summary>Event message when an Avatar has begun to type</summary>
213 StartTyping = 4,
214 /// <summary>Event message when an Avatar has stopped typing</summary>
215 StopTyping = 5,
216 /// <summary>Send the message to the debug channel</summary>
217 Debug = 6,
218 /// <summary>Event message when an object uses llOwnerSay</summary>
219 OwnerSay = 8,
220 /// <summary>Event message when an object uses llRegionSayTo</summary>
221 RegionSayTo = 9,
222 /// <summary>Special value to support llRegionSay, never sent to the client</summary>
223 RegionSay = Byte.MaxValue,
224 }
225  
226 /// <summary>
227 /// Identifies the source of a chat message
228 /// </summary>
229 public enum ChatSourceType : byte
230 {
231 /// <summary>Chat from the grid or simulator</summary>
232 System = 0,
233 /// <summary>Chat from another avatar</summary>
234 Agent = 1,
235 /// <summary>Chat from an object</summary>
236 Object = 2
237 }
238  
239 /// <summary>
240 ///
241 /// </summary>
242 public enum ChatAudibleLevel : sbyte
243 {
244 /// <summary></summary>
245 Not = -1,
246 /// <summary></summary>
247 Barely = 0,
248 /// <summary></summary>
249 Fully = 1
250 }
251  
252 /// <summary>
253 /// Effect type used in ViewerEffect packets
254 /// </summary>
255 public enum EffectType : byte
256 {
257 /// <summary></summary>
258 Text = 0,
259 /// <summary></summary>
260 Icon,
261 /// <summary></summary>
262 Connector,
263 /// <summary></summary>
264 FlexibleObject,
265 /// <summary></summary>
266 AnimalControls,
267 /// <summary></summary>
268 AnimationObject,
269 /// <summary></summary>
270 Cloth,
271 /// <summary>Project a beam from a source to a destination, such as
272 /// the one used when editing an object</summary>
273 Beam,
274 /// <summary></summary>
275 Glow,
276 /// <summary></summary>
277 Point,
278 /// <summary></summary>
279 Trail,
280 /// <summary>Create a swirl of particles around an object</summary>
281 Sphere,
282 /// <summary></summary>
283 Spiral,
284 /// <summary></summary>
285 Edit,
286 /// <summary>Cause an avatar to look at an object</summary>
287 LookAt,
288 /// <summary>Cause an avatar to point at an object</summary>
289 PointAt
290 }
291  
292 /// <summary>
293 /// The action an avatar is doing when looking at something, used in
294 /// ViewerEffect packets for the LookAt effect
295 /// </summary>
296 public enum LookAtType : byte
297 {
298 /// <summary></summary>
299 None,
300 /// <summary></summary>
301 Idle,
302 /// <summary></summary>
303 AutoListen,
304 /// <summary></summary>
305 FreeLook,
306 /// <summary></summary>
307 Respond,
308 /// <summary></summary>
309 Hover,
310 /// <summary>Deprecated</summary>
311 [Obsolete]
312 Conversation,
313 /// <summary></summary>
314 Select,
315 /// <summary></summary>
316 Focus,
317 /// <summary></summary>
318 Mouselook,
319 /// <summary></summary>
320 Clear
321 }
322  
323 /// <summary>
324 /// The action an avatar is doing when pointing at something, used in
325 /// ViewerEffect packets for the PointAt effect
326 /// </summary>
327 public enum PointAtType : byte
328 {
329 /// <summary></summary>
330 None,
331 /// <summary></summary>
332 Select,
333 /// <summary></summary>
334 Grab,
335 /// <summary></summary>
336 Clear
337 }
338  
339 /// <summary>
340 /// Money transaction types
341 /// </summary>
342 public enum MoneyTransactionType : int
343 {
344 /// <summary></summary>
345 None = 0,
346 /// <summary></summary>
347 FailSimulatorTimeout = 1,
348 /// <summary></summary>
349 FailDataserverTimeout = 2,
350 /// <summary></summary>
351 ObjectClaim = 1000,
352 /// <summary></summary>
353 LandClaim = 1001,
354 /// <summary></summary>
355 GroupCreate = 1002,
356 /// <summary></summary>
357 ObjectPublicClaim = 1003,
358 /// <summary></summary>
359 GroupJoin = 1004,
360 /// <summary></summary>
361 TeleportCharge = 1100,
362 /// <summary></summary>
363 UploadCharge = 1101,
364 /// <summary></summary>
365 LandAuction = 1102,
366 /// <summary></summary>
367 ClassifiedCharge = 1103,
368 /// <summary></summary>
369 ObjectTax = 2000,
370 /// <summary></summary>
371 LandTax = 2001,
372 /// <summary></summary>
373 LightTax = 2002,
374 /// <summary></summary>
375 ParcelDirFee = 2003,
376 /// <summary></summary>
377 GroupTax = 2004,
378 /// <summary></summary>
379 ClassifiedRenew = 2005,
380 /// <summary></summary>
381 GiveInventory = 3000,
382 /// <summary></summary>
383 ObjectSale = 5000,
384 /// <summary></summary>
385 Gift = 5001,
386 /// <summary></summary>
387 LandSale = 5002,
388 /// <summary></summary>
389 ReferBonus = 5003,
390 /// <summary></summary>
391 InventorySale = 5004,
392 /// <summary></summary>
393 RefundPurchase = 5005,
394 /// <summary></summary>
395 LandPassSale = 5006,
396 /// <summary></summary>
397 DwellBonus = 5007,
398 /// <summary></summary>
399 PayObject = 5008,
400 /// <summary></summary>
401 ObjectPays = 5009,
402 /// <summary></summary>
403 GroupLandDeed = 6001,
404 /// <summary></summary>
405 GroupObjectDeed = 6002,
406 /// <summary></summary>
407 GroupLiability = 6003,
408 /// <summary></summary>
409 GroupDividend = 6004,
410 /// <summary></summary>
411 GroupMembershipDues = 6005,
412 /// <summary></summary>
413 ObjectRelease = 8000,
414 /// <summary></summary>
415 LandRelease = 8001,
416 /// <summary></summary>
417 ObjectDelete = 8002,
418 /// <summary></summary>
419 ObjectPublicDecay = 8003,
420 /// <summary></summary>
421 ObjectPublicDelete = 8004,
422 /// <summary></summary>
423 LindenAdjustment = 9000,
424 /// <summary></summary>
425 LindenGrant = 9001,
426 /// <summary></summary>
427 LindenPenalty = 9002,
428 /// <summary></summary>
429 EventFee = 9003,
430 /// <summary></summary>
431 EventPrize = 9004,
432 /// <summary></summary>
433 StipendBasic = 10000,
434 /// <summary></summary>
435 StipendDeveloper = 10001,
436 /// <summary></summary>
437 StipendAlways = 10002,
438 /// <summary></summary>
439 StipendDaily = 10003,
440 /// <summary></summary>
441 StipendRating = 10004,
442 /// <summary></summary>
443 StipendDelta = 10005
444 }
445 /// <summary>
446 ///
447 /// </summary>
448 [Flags]
449 public enum TransactionFlags : byte
450 {
451 /// <summary></summary>
452 None = 0,
453 /// <summary></summary>
454 SourceGroup = 1,
455 /// <summary></summary>
456 DestGroup = 2,
457 /// <summary></summary>
458 OwnerGroup = 4,
459 /// <summary></summary>
460 SimultaneousContribution = 8,
461 /// <summary></summary>
462 ContributionRemoval = 16
463 }
464 /// <summary>
465 ///
466 /// </summary>
467 public enum MeanCollisionType : byte
468 {
469 /// <summary></summary>
470 None,
471 /// <summary></summary>
472 Bump,
473 /// <summary></summary>
474 LLPushObject,
475 /// <summary></summary>
476 SelectedObjectCollide,
477 /// <summary></summary>
478 ScriptedObjectCollide,
479 /// <summary></summary>
480 PhysicalObjectCollide
481 }
482  
483 /// <summary>
484 /// Flags sent when a script takes or releases a control
485 /// </summary>
486 /// <remarks>NOTE: (need to verify) These might be a subset of the ControlFlags enum in Movement,</remarks>
487 [Flags]
488 public enum ScriptControlChange : uint
489 {
490 /// <summary>No Flags set</summary>
491 None = 0,
492 /// <summary>Forward (W or up Arrow)</summary>
493 Forward = 1,
494 /// <summary>Back (S or down arrow)</summary>
495 Back = 2,
496 /// <summary>Move left (shift+A or left arrow)</summary>
497 Left = 4,
498 /// <summary>Move right (shift+D or right arrow)</summary>
499 Right = 8,
500 /// <summary>Up (E or PgUp)</summary>
501 Up = 16,
502 /// <summary>Down (C or PgDown)</summary>
503 Down = 32,
504 /// <summary>Rotate left (A or left arrow)</summary>
505 RotateLeft = 256,
506 /// <summary>Rotate right (D or right arrow)</summary>
507 RotateRight = 512,
508 /// <summary>Left Mouse Button</summary>
509 LeftButton = 268435456,
510 /// <summary>Left Mouse button in MouseLook</summary>
511 MouseLookLeftButton = 1073741824
512 }
513  
514 /// <summary>
515 /// Currently only used to hide your group title
516 /// </summary>
517 [Flags]
518 public enum AgentFlags : byte
519 {
520 /// <summary>No flags set</summary>
521 None = 0,
522 /// <summary>Hide your group title</summary>
523 HideTitle = 0x01,
524 }
525  
526 /// <summary>
527 /// Action state of the avatar, which can currently be typing and
528 /// editing
529 /// </summary>
530 [Flags]
531 public enum AgentState : byte
532 {
533 /// <summary></summary>
534 None = 0x00,
535 /// <summary></summary>
536 Typing = 0x04,
537 /// <summary></summary>
538 Editing = 0x10
539 }
540  
541 /// <summary>
542 /// Current teleport status
543 /// </summary>
544 public enum TeleportStatus
545 {
546 /// <summary>Unknown status</summary>
547 None,
548 /// <summary>Teleport initialized</summary>
549 Start,
550 /// <summary>Teleport in progress</summary>
551 Progress,
552 /// <summary>Teleport failed</summary>
553 Failed,
554 /// <summary>Teleport completed</summary>
555 Finished,
556 /// <summary>Teleport cancelled</summary>
557 Cancelled
558 }
559  
560 /// <summary>
561 ///
562 /// </summary>
563 [Flags]
564 public enum TeleportFlags : uint
565 {
566 /// <summary>No flags set, or teleport failed</summary>
567 Default = 0,
568 /// <summary>Set when newbie leaves help island for first time</summary>
569 SetHomeToTarget = 1 << 0,
570 /// <summary></summary>
571 SetLastToTarget = 1 << 1,
572 /// <summary>Via Lure</summary>
573 ViaLure = 1 << 2,
574 /// <summary>Via Landmark</summary>
575 ViaLandmark = 1 << 3,
576 /// <summary>Via Location</summary>
577 ViaLocation = 1 << 4,
578 /// <summary>Via Home</summary>
579 ViaHome = 1 << 5,
580 /// <summary>Via Telehub</summary>
581 ViaTelehub = 1 << 6,
582 /// <summary>Via Login</summary>
583 ViaLogin = 1 << 7,
584 /// <summary>Linden Summoned</summary>
585 ViaGodlikeLure = 1 << 8,
586 /// <summary>Linden Forced me</summary>
587 Godlike = 1 << 9,
588 /// <summary></summary>
589 NineOneOne = 1 << 10,
590 /// <summary>Agent Teleported Home via Script</summary>
591 DisableCancel = 1 << 11,
592 /// <summary></summary>
593 ViaRegionID = 1 << 12,
594 /// <summary></summary>
595 IsFlying = 1 << 13,
596 /// <summary></summary>
597 ResetHome = 1 << 14,
598 /// <summary>forced to new location for example when avatar is banned or ejected</summary>
599 ForceRedirect = 1 << 15,
600 /// <summary>Teleport Finished via a Lure</summary>
601 FinishedViaLure = 1 << 26,
602 /// <summary>Finished, Sim Changed</summary>
603 FinishedViaNewSim = 1 << 28,
604 /// <summary>Finished, Same Sim</summary>
605 FinishedViaSameSim = 1 << 29
606 }
607  
608 /// <summary>
609 ///
610 /// </summary>
611 [Flags]
612 public enum TeleportLureFlags
613 {
614 /// <summary></summary>
615 NormalLure = 0,
616 /// <summary></summary>
617 GodlikeLure = 1,
618 /// <summary></summary>
619 GodlikePursuit = 2
620 }
621  
622 /// <summary>
623 ///
624 /// </summary>
625 [Flags]
626 public enum ScriptSensorTypeFlags
627 {
628 /// <summary></summary>
629 Agent = 1,
630 /// <summary></summary>
631 Active = 2,
632 /// <summary></summary>
633 Passive = 4,
634 /// <summary></summary>
635 Scripted = 8,
636 }
637  
638 /// <summary>
639 /// Type of mute entry
640 /// </summary>
641 public enum MuteType
642 {
643 /// <summary>Object muted by name</summary>
644 ByName = 0,
645 /// <summary>Muted residet</summary>
646 Resident = 1,
647 /// <summary>Object muted by UUID</summary>
648 Object = 2,
649 /// <summary>Muted group</summary>
650 Group = 3,
651 /// <summary>Muted external entry</summary>
652 External = 4
653 }
654  
655 /// <summary>
656 /// Flags of mute entry
657 /// </summary>
658 [Flags]
659 public enum MuteFlags : int
660 {
661 /// <summary>No exceptions</summary>
662 Default = 0x0,
663 /// <summary>Don't mute text chat</summary>
664 TextChat = 0x1,
665 /// <summary>Don't mute voice chat</summary>
666 VoiceChat = 0x2,
667 /// <summary>Don't mute particles</summary>
668 Particles = 0x4,
669 /// <summary>Don't mute sounds</summary>
670 ObjectSounds = 0x8,
671 /// <summary>Don't mute</summary>
672 All = 0xf
673 }
674 #endregion Enums
675  
676 #region Structs
677  
678 /// <summary>
679 /// Instant Message
680 /// </summary>
681 public struct InstantMessage
682 {
683 /// <summary>Key of sender</summary>
684 public UUID FromAgentID;
685 /// <summary>Name of sender</summary>
686 public string FromAgentName;
687 /// <summary>Key of destination avatar</summary>
688 public UUID ToAgentID;
689 /// <summary>ID of originating estate</summary>
690 public uint ParentEstateID;
691 /// <summary>Key of originating region</summary>
692 public UUID RegionID;
693 /// <summary>Coordinates in originating region</summary>
694 public Vector3 Position;
695 /// <summary>Instant message type</summary>
696 public InstantMessageDialog Dialog;
697 /// <summary>Group IM session toggle</summary>
698 public bool GroupIM;
699 /// <summary>Key of IM session, for Group Messages, the groups UUID</summary>
700 public UUID IMSessionID;
701 /// <summary>Timestamp of the instant message</summary>
702 public DateTime Timestamp;
703 /// <summary>Instant message text</summary>
704 public string Message;
705 /// <summary>Whether this message is held for offline avatars</summary>
706 public InstantMessageOnline Offline;
707 /// <summary>Context specific packed data</summary>
708 public byte[] BinaryBucket;
709  
710 /// <summary>Print the struct data as a string</summary>
711 /// <returns>A string containing the field name, and field value</returns>
712 public override string ToString()
713 {
714 return Helpers.StructToString(this);
715 }
716 }
717  
718 /// <summary>Represents muted object or resident</summary>
719 public class MuteEntry
720 {
721 /// <summary>Type of the mute entry</summary>
722 public MuteType Type;
723 /// <summary>UUID of the mute etnry</summary>
724 public UUID ID;
725 /// <summary>Mute entry name</summary>
726 public string Name;
727 /// <summary>Mute flags</summary>
728 public MuteFlags Flags;
729 }
730  
731 /// <summary>Transaction detail sent with MoneyBalanceReply message</summary>
732 public class TransactionInfo
733 {
734 /// <summary>Type of the transaction</summary>
735 public int TransactionType; // FIXME: this should be an enum
736 /// <summary>UUID of the transaction source</summary>
737 public UUID SourceID;
738 /// <summary>Is the transaction source a group</summary>
739 public bool IsSourceGroup;
740 /// <summary>UUID of the transaction destination</summary>
741 public UUID DestID;
742 /// <summary>Is transaction destination a group</summary>
743 public bool IsDestGroup;
744 /// <summary>Transaction amount</summary>
745 public int Amount;
746 /// <summary>Transaction description</summary>
747 public string ItemDescription;
748 }
749 #endregion Structs
750  
751 /// <summary>
752 /// Manager class for our own avatar
753 /// </summary>
754 public partial class AgentManager
755 {
756 #region Delegates
757 /// <summary>
758 /// Called once attachment resource usage information has been collected
759 /// </summary>
760 /// <param name="success">Indicates if operation was successfull</param>
761 /// <param name="info">Attachment resource usage information</param>
762 public delegate void AttachmentResourcesCallback(bool success, AttachmentResourcesMessage info);
763 #endregion Delegates
764  
765 #region Event Delegates
766  
767 /// <summary>The event subscribers. null if no subcribers</summary>
768 private EventHandler<ChatEventArgs> m_Chat;
769  
770 /// <summary>Raises the ChatFromSimulator event</summary>
771 /// <param name="e">A ChatEventArgs object containing the
772 /// data returned from the data server</param>
773 protected virtual void OnChat(ChatEventArgs e)
774 {
775 EventHandler<ChatEventArgs> handler = m_Chat;
776 if (handler != null)
777 handler(this, e);
778 }
779  
780 /// <summary>Thread sync lock object</summary>
781 private readonly object m_ChatLock = new object();
782  
783 /// <summary>Raised when a scripted object or agent within range sends a public message</summary>
784 public event EventHandler<ChatEventArgs> ChatFromSimulator
785 {
786 add { lock (m_ChatLock) { m_Chat += value; } }
787 remove { lock (m_ChatLock) { m_Chat -= value; } }
788 }
789  
790 /// <summary>The event subscribers. null if no subcribers</summary>
791 private EventHandler<ScriptDialogEventArgs> m_ScriptDialog;
792  
793 /// <summary>Raises the ScriptDialog event</summary>
794 /// <param name="e">A SctriptDialogEventArgs object containing the
795 /// data returned from the data server</param>
796 protected virtual void OnScriptDialog(ScriptDialogEventArgs e)
797 {
798 EventHandler<ScriptDialogEventArgs> handler = m_ScriptDialog;
799 if (handler != null)
800 handler(this, e);
801 }
802  
803 /// <summary>Thread sync lock object</summary>
804 private readonly object m_ScriptDialogLock = new object();
805 /// <summary>Raised when a scripted object sends a dialog box containing possible
806 /// options an agent can respond to</summary>
807 public event EventHandler<ScriptDialogEventArgs> ScriptDialog
808 {
809 add { lock (m_ScriptDialogLock) { m_ScriptDialog += value; } }
810 remove { lock (m_ScriptDialogLock) { m_ScriptDialog -= value; } }
811 }
812  
813 /// <summary>The event subscribers. null if no subcribers</summary>
814 private EventHandler<ScriptQuestionEventArgs> m_ScriptQuestion;
815  
816 /// <summary>Raises the ScriptQuestion event</summary>
817 /// <param name="e">A ScriptQuestionEventArgs object containing the
818 /// data returned from the data server</param>
819 protected virtual void OnScriptQuestion(ScriptQuestionEventArgs e)
820 {
821 EventHandler<ScriptQuestionEventArgs> handler = m_ScriptQuestion;
822 if (handler != null)
823 handler(this, e);
824 }
825  
826 /// <summary>Thread sync lock object</summary>
827 private readonly object m_ScriptQuestionLock = new object();
828 /// <summary>Raised when an object requests a change in the permissions an agent has permitted</summary>
829 public event EventHandler<ScriptQuestionEventArgs> ScriptQuestion
830 {
831 add { lock (m_ScriptQuestionLock) { m_ScriptQuestion += value; } }
832 remove { lock (m_ScriptQuestionLock) { m_ScriptQuestion -= value; } }
833 }
834  
835 /// <summary>The event subscribers. null if no subcribers</summary>
836 private EventHandler<LoadUrlEventArgs> m_LoadURL;
837  
838 /// <summary>Raises the LoadURL event</summary>
839 /// <param name="e">A LoadUrlEventArgs object containing the
840 /// data returned from the data server</param>
841 protected virtual void OnLoadURL(LoadUrlEventArgs e)
842 {
843 EventHandler<LoadUrlEventArgs> handler = m_LoadURL;
844 if (handler != null)
845 handler(this, e);
846 }
847  
848 /// <summary>Thread sync lock object</summary>
849 private readonly object m_LoadUrlLock = new object();
850 /// <summary>Raised when a script requests an agent open the specified URL</summary>
851 public event EventHandler<LoadUrlEventArgs> LoadURL
852 {
853 add { lock (m_LoadUrlLock) { m_LoadURL += value; } }
854 remove { lock (m_LoadUrlLock) { m_LoadURL -= value; } }
855 }
856  
857 /// <summary>The event subscribers. null if no subcribers</summary>
858 private EventHandler<BalanceEventArgs> m_Balance;
859  
860 /// <summary>Raises the MoneyBalance event</summary>
861 /// <param name="e">A BalanceEventArgs object containing the
862 /// data returned from the data server</param>
863 protected virtual void OnBalance(BalanceEventArgs e)
864 {
865 EventHandler<BalanceEventArgs> handler = m_Balance;
866 if (handler != null)
867 handler(this, e);
868 }
869  
870 /// <summary>Thread sync lock object</summary>
871 private readonly object m_BalanceLock = new object();
872  
873 /// <summary>Raised when an agents currency balance is updated</summary>
874 public event EventHandler<BalanceEventArgs> MoneyBalance
875 {
876 add { lock (m_BalanceLock) { m_Balance += value; } }
877 remove { lock (m_BalanceLock) { m_Balance -= value; } }
878 }
879  
880 /// <summary>The event subscribers. null if no subcribers</summary>
881 private EventHandler<MoneyBalanceReplyEventArgs> m_MoneyBalance;
882  
883 /// <summary>Raises the MoneyBalanceReply event</summary>
884 /// <param name="e">A MoneyBalanceReplyEventArgs object containing the
885 /// data returned from the data server</param>
886 protected virtual void OnMoneyBalanceReply(MoneyBalanceReplyEventArgs e)
887 {
888 EventHandler<MoneyBalanceReplyEventArgs> handler = m_MoneyBalance;
889 if (handler != null)
890 handler(this, e);
891 }
892  
893 /// <summary>Thread sync lock object</summary>
894 private readonly object m_MoneyBalanceReplyLock = new object();
895  
896 /// <summary>Raised when a transaction occurs involving currency such as a land purchase</summary>
897 public event EventHandler<MoneyBalanceReplyEventArgs> MoneyBalanceReply
898 {
899 add { lock (m_MoneyBalanceReplyLock) { m_MoneyBalance += value; } }
900 remove { lock (m_MoneyBalanceReplyLock) { m_MoneyBalance -= value; } }
901 }
902  
903 /// <summary>The event subscribers. null if no subcribers</summary>
904 private EventHandler<InstantMessageEventArgs> m_InstantMessage;
905  
906 /// <summary>Raises the IM event</summary>
907 /// <param name="e">A InstantMessageEventArgs object containing the
908 /// data returned from the data server</param>
909 protected virtual void OnInstantMessage(InstantMessageEventArgs e)
910 {
911 EventHandler<InstantMessageEventArgs> handler = m_InstantMessage;
912 if (handler != null)
913 handler(this, e);
914 }
915  
916 /// <summary>Thread sync lock object</summary>
917 private readonly object m_InstantMessageLock = new object();
918 /// <summary>Raised when an ImprovedInstantMessage packet is recieved from the simulator, this is used for everything from
919 /// private messaging to friendship offers. The Dialog field defines what type of message has arrived</summary>
920 public event EventHandler<InstantMessageEventArgs> IM
921 {
922 add { lock (m_InstantMessageLock) { m_InstantMessage += value; } }
923 remove { lock (m_InstantMessageLock) { m_InstantMessage -= value; } }
924 }
925  
926 /// <summary>The event subscribers. null if no subcribers</summary>
927 private EventHandler<TeleportEventArgs> m_Teleport;
928  
929 /// <summary>Raises the TeleportProgress event</summary>
930 /// <param name="e">A TeleportEventArgs object containing the
931 /// data returned from the data server</param>
932 protected virtual void OnTeleport(TeleportEventArgs e)
933 {
934 EventHandler<TeleportEventArgs> handler = m_Teleport;
935 if (handler != null)
936 handler(this, e);
937 }
938  
939 /// <summary>Thread sync lock object</summary>
940 private readonly object m_TeleportLock = new object();
941 /// <summary>Raised when an agent has requested a teleport to another location, or when responding to a lure. Raised multiple times
942 /// for each teleport indicating the progress of the request</summary>
943 public event EventHandler<TeleportEventArgs> TeleportProgress
944 {
945 add { lock (m_TeleportLock) { m_Teleport += value; } }
946 remove { lock (m_TeleportLock) { m_Teleport += value; } }
947 }
948  
949 /// <summary>The event subscribers. null if no subcribers</summary>
950 private EventHandler<AgentDataReplyEventArgs> m_AgentData;
951  
952 /// <summary>Raises the AgentDataReply event</summary>
953 /// <param name="e">A AgentDataReplyEventArgs object containing the
954 /// data returned from the data server</param>
955 protected virtual void OnAgentData(AgentDataReplyEventArgs e)
956 {
957 EventHandler<AgentDataReplyEventArgs> handler = m_AgentData;
958 if (handler != null)
959 handler(this, e);
960 }
961  
962 /// <summary>Thread sync lock object</summary>
963 private readonly object m_AgentDataLock = new object();
964  
965 /// <summary>Raised when a simulator sends agent specific information for our avatar.</summary>
966 public event EventHandler<AgentDataReplyEventArgs> AgentDataReply
967 {
968 add { lock (m_AgentDataLock) { m_AgentData += value; } }
969 remove { lock (m_AgentDataLock) { m_AgentData -= value; } }
970 }
971  
972 /// <summary>The event subscribers. null if no subcribers</summary>
973 private EventHandler<AnimationsChangedEventArgs> m_AnimationsChanged;
974  
975 /// <summary>Raises the AnimationsChanged event</summary>
976 /// <param name="e">A AnimationsChangedEventArgs object containing the
977 /// data returned from the data server</param>
978 protected virtual void OnAnimationsChanged(AnimationsChangedEventArgs e)
979 {
980 EventHandler<AnimationsChangedEventArgs> handler = m_AnimationsChanged;
981 if (handler != null)
982 handler(this, e);
983 }
984  
985 /// <summary>Thread sync lock object</summary>
986 private readonly object m_AnimationsChangedLock = new object();
987  
988 /// <summary>Raised when our agents animation playlist changes</summary>
989 public event EventHandler<AnimationsChangedEventArgs> AnimationsChanged
990 {
991 add { lock (m_AnimationsChangedLock) { m_AnimationsChanged += value; } }
992 remove { lock (m_AnimationsChangedLock) { m_AnimationsChanged -= value; } }
993 }
994  
995 /// <summary>The event subscribers. null if no subcribers</summary>
996 private EventHandler<MeanCollisionEventArgs> m_MeanCollision;
997  
998 /// <summary>Raises the MeanCollision event</summary>
999 /// <param name="e">A MeanCollisionEventArgs object containing the
1000 /// data returned from the data server</param>
1001 protected virtual void OnMeanCollision(MeanCollisionEventArgs e)
1002 {
1003 EventHandler<MeanCollisionEventArgs> handler = m_MeanCollision;
1004 if (handler != null)
1005 handler(this, e);
1006 }
1007  
1008 /// <summary>Thread sync lock object</summary>
1009 private readonly object m_MeanCollisionLock = new object();
1010  
1011 /// <summary>Raised when an object or avatar forcefully collides with our agent</summary>
1012 public event EventHandler<MeanCollisionEventArgs> MeanCollision
1013 {
1014 add { lock (m_MeanCollisionLock) { m_MeanCollision += value; } }
1015 remove { lock (m_MeanCollisionLock) { m_MeanCollision -= value; } }
1016 }
1017  
1018 /// <summary>The event subscribers. null if no subcribers</summary>
1019 private EventHandler<RegionCrossedEventArgs> m_RegionCrossed;
1020  
1021 /// <summary>Raises the RegionCrossed event</summary>
1022 /// <param name="e">A RegionCrossedEventArgs object containing the
1023 /// data returned from the data server</param>
1024 protected virtual void OnRegionCrossed(RegionCrossedEventArgs e)
1025 {
1026 EventHandler<RegionCrossedEventArgs> handler = m_RegionCrossed;
1027 if (handler != null)
1028 handler(this, e);
1029 }
1030  
1031 /// <summary>Thread sync lock object</summary>
1032 private readonly object m_RegionCrossedLock = new object();
1033  
1034 /// <summary>Raised when our agent crosses a region border into another region</summary>
1035 public event EventHandler<RegionCrossedEventArgs> RegionCrossed
1036 {
1037 add { lock (m_RegionCrossedLock) { m_RegionCrossed += value; } }
1038 remove { lock (m_RegionCrossedLock) { m_RegionCrossed -= value; } }
1039 }
1040  
1041 /// <summary>The event subscribers. null if no subcribers</summary>
1042 private EventHandler<GroupChatJoinedEventArgs> m_GroupChatJoined;
1043  
1044 /// <summary>Raises the GroupChatJoined event</summary>
1045 /// <param name="e">A GroupChatJoinedEventArgs object containing the
1046 /// data returned from the data server</param>
1047 protected virtual void OnGroupChatJoined(GroupChatJoinedEventArgs e)
1048 {
1049 EventHandler<GroupChatJoinedEventArgs> handler = m_GroupChatJoined;
1050 if (handler != null)
1051 handler(this, e);
1052 }
1053  
1054 /// <summary>Thread sync lock object</summary>
1055 private readonly object m_GroupChatJoinedLock = new object();
1056  
1057 /// <summary>Raised when our agent succeeds or fails to join a group chat session</summary>
1058 public event EventHandler<GroupChatJoinedEventArgs> GroupChatJoined
1059 {
1060 add { lock (m_GroupChatJoinedLock) { m_GroupChatJoined += value; } }
1061 remove { lock (m_GroupChatJoinedLock) { m_GroupChatJoined -= value; } }
1062 }
1063  
1064 /// <summary>The event subscribers. null if no subcribers</summary>
1065 private EventHandler<AlertMessageEventArgs> m_AlertMessage;
1066  
1067 /// <summary>Raises the AlertMessage event</summary>
1068 /// <param name="e">A AlertMessageEventArgs object containing the
1069 /// data returned from the data server</param>
1070 protected virtual void OnAlertMessage(AlertMessageEventArgs e)
1071 {
1072 EventHandler<AlertMessageEventArgs> handler = m_AlertMessage;
1073 if (handler != null)
1074 handler(this, e);
1075 }
1076  
1077 /// <summary>Thread sync lock object</summary>
1078 private readonly object m_AlertMessageLock = new object();
1079  
1080 /// <summary>Raised when a simulator sends an urgent message usually indication the recent failure of
1081 /// another action we have attempted to take such as an attempt to enter a parcel where we are denied access</summary>
1082 public event EventHandler<AlertMessageEventArgs> AlertMessage
1083 {
1084 add { lock (m_AlertMessageLock) { m_AlertMessage += value; } }
1085 remove { lock (m_AlertMessageLock) { m_AlertMessage -= value; } }
1086 }
1087  
1088 /// <summary>The event subscribers. null if no subcribers</summary>
1089 private EventHandler<ScriptControlEventArgs> m_ScriptControl;
1090  
1091 /// <summary>Raises the ScriptControlChange event</summary>
1092 /// <param name="e">A ScriptControlEventArgs object containing the
1093 /// data returned from the data server</param>
1094 protected virtual void OnScriptControlChange(ScriptControlEventArgs e)
1095 {
1096 EventHandler<ScriptControlEventArgs> handler = m_ScriptControl;
1097 if (handler != null)
1098 handler(this, e);
1099 }
1100  
1101 /// <summary>Thread sync lock object</summary>
1102 private readonly object m_ScriptControlLock = new object();
1103  
1104 /// <summary>Raised when a script attempts to take or release specified controls for our agent</summary>
1105 public event EventHandler<ScriptControlEventArgs> ScriptControlChange
1106 {
1107 add { lock (m_ScriptControlLock) { m_ScriptControl += value; } }
1108 remove { lock (m_ScriptControlLock) { m_ScriptControl -= value; } }
1109 }
1110  
1111 /// <summary>The event subscribers. null if no subcribers</summary>
1112 private EventHandler<CameraConstraintEventArgs> m_CameraConstraint;
1113  
1114 /// <summary>Raises the CameraConstraint event</summary>
1115 /// <param name="e">A CameraConstraintEventArgs object containing the
1116 /// data returned from the data server</param>
1117 protected virtual void OnCameraConstraint(CameraConstraintEventArgs e)
1118 {
1119 EventHandler<CameraConstraintEventArgs> handler = m_CameraConstraint;
1120 if (handler != null)
1121 handler(this, e);
1122 }
1123  
1124 /// <summary>Thread sync lock object</summary>
1125 private readonly object m_CameraConstraintLock = new object();
1126  
1127 /// <summary>Raised when the simulator detects our agent is trying to view something
1128 /// beyond its limits</summary>
1129 public event EventHandler<CameraConstraintEventArgs> CameraConstraint
1130 {
1131 add { lock (m_CameraConstraintLock) { m_CameraConstraint += value; } }
1132 remove { lock (m_CameraConstraintLock) { m_CameraConstraint -= value; } }
1133 }
1134  
1135 /// <summary>The event subscribers. null if no subcribers</summary>
1136 private EventHandler<ScriptSensorReplyEventArgs> m_ScriptSensorReply;
1137  
1138 /// <summary>Raises the ScriptSensorReply event</summary>
1139 /// <param name="e">A ScriptSensorReplyEventArgs object containing the
1140 /// data returned from the data server</param>
1141 protected virtual void OnScriptSensorReply(ScriptSensorReplyEventArgs e)
1142 {
1143 EventHandler<ScriptSensorReplyEventArgs> handler = m_ScriptSensorReply;
1144 if (handler != null)
1145 handler(this, e);
1146 }
1147  
1148 /// <summary>Thread sync lock object</summary>
1149 private readonly object m_ScriptSensorReplyLock = new object();
1150  
1151 /// <summary>Raised when a script sensor reply is received from a simulator</summary>
1152 public event EventHandler<ScriptSensorReplyEventArgs> ScriptSensorReply
1153 {
1154 add { lock (m_ScriptSensorReplyLock) { m_ScriptSensorReply += value; } }
1155 remove { lock (m_ScriptSensorReplyLock) { m_ScriptSensorReply -= value; } }
1156 }
1157  
1158 /// <summary>The event subscribers. null if no subcribers</summary>
1159 private EventHandler<AvatarSitResponseEventArgs> m_AvatarSitResponse;
1160  
1161 /// <summary>Raises the AvatarSitResponse event</summary>
1162 /// <param name="e">A AvatarSitResponseEventArgs object containing the
1163 /// data returned from the data server</param>
1164 protected virtual void OnAvatarSitResponse(AvatarSitResponseEventArgs e)
1165 {
1166 EventHandler<AvatarSitResponseEventArgs> handler = m_AvatarSitResponse;
1167 if (handler != null)
1168 handler(this, e);
1169 }
1170  
1171 /// <summary>Thread sync lock object</summary>
1172 private readonly object m_AvatarSitResponseLock = new object();
1173  
1174 /// <summary>Raised in response to a <see cref="RequestSit"/> request</summary>
1175 public event EventHandler<AvatarSitResponseEventArgs> AvatarSitResponse
1176 {
1177 add { lock (m_AvatarSitResponseLock) { m_AvatarSitResponse += value; } }
1178 remove { lock (m_AvatarSitResponseLock) { m_AvatarSitResponse -= value; } }
1179 }
1180  
1181 /// <summary>The event subscribers. null if no subcribers</summary>
1182 private EventHandler<ChatSessionMemberAddedEventArgs> m_ChatSessionMemberAdded;
1183  
1184 /// <summary>Raises the ChatSessionMemberAdded event</summary>
1185 /// <param name="e">A ChatSessionMemberAddedEventArgs object containing the
1186 /// data returned from the data server</param>
1187 protected virtual void OnChatSessionMemberAdded(ChatSessionMemberAddedEventArgs e)
1188 {
1189 EventHandler<ChatSessionMemberAddedEventArgs> handler = m_ChatSessionMemberAdded;
1190 if (handler != null)
1191 handler(this, e);
1192 }
1193  
1194 /// <summary>Thread sync lock object</summary>
1195 private readonly object m_ChatSessionMemberAddedLock = new object();
1196  
1197 /// <summary>Raised when an avatar enters a group chat session we are participating in</summary>
1198 public event EventHandler<ChatSessionMemberAddedEventArgs> ChatSessionMemberAdded
1199 {
1200 add { lock (m_ChatSessionMemberAddedLock) { m_ChatSessionMemberAdded += value; } }
1201 remove { lock (m_ChatSessionMemberAddedLock) { m_ChatSessionMemberAdded -= value; } }
1202 }
1203  
1204 /// <summary>The event subscribers. null if no subcribers</summary>
1205 private EventHandler<ChatSessionMemberLeftEventArgs> m_ChatSessionMemberLeft;
1206  
1207 /// <summary>Raises the ChatSessionMemberLeft event</summary>
1208 /// <param name="e">A ChatSessionMemberLeftEventArgs object containing the
1209 /// data returned from the data server</param>
1210 protected virtual void OnChatSessionMemberLeft(ChatSessionMemberLeftEventArgs e)
1211 {
1212 EventHandler<ChatSessionMemberLeftEventArgs> handler = m_ChatSessionMemberLeft;
1213 if (handler != null)
1214 handler(this, e);
1215 }
1216  
1217 /// <summary>Thread sync lock object</summary>
1218 private readonly object m_ChatSessionMemberLeftLock = new object();
1219  
1220 /// <summary>Raised when an agent exits a group chat session we are participating in</summary>
1221 public event EventHandler<ChatSessionMemberLeftEventArgs> ChatSessionMemberLeft
1222 {
1223 add { lock (m_ChatSessionMemberLeftLock) { m_ChatSessionMemberLeft += value; } }
1224 remove { lock (m_ChatSessionMemberLeftLock) { m_ChatSessionMemberLeft -= value; } }
1225 }
1226  
1227 /// <summary>The event subscribers, null of no subscribers</summary>
1228 private EventHandler<SetDisplayNameReplyEventArgs> m_SetDisplayNameReply;
1229  
1230 ///<summary>Raises the SetDisplayNameReply Event</summary>
1231 /// <param name="e">A SetDisplayNameReplyEventArgs object containing
1232 /// the data sent from the simulator</param>
1233 protected virtual void OnSetDisplayNameReply(SetDisplayNameReplyEventArgs e)
1234 {
1235 EventHandler<SetDisplayNameReplyEventArgs> handler = m_SetDisplayNameReply;
1236 if (handler != null)
1237 handler(this, e);
1238 }
1239  
1240 /// <summary>Thread sync lock object</summary>
1241 private readonly object m_SetDisplayNameReplyLock = new object();
1242  
1243 /// <summary>Raised when the simulator sends us data containing
1244 /// the details of display name change</summary>
1245 public event EventHandler<SetDisplayNameReplyEventArgs> SetDisplayNameReply
1246 {
1247 add { lock (m_SetDisplayNameReplyLock) { m_SetDisplayNameReply += value; } }
1248 remove { lock (m_SetDisplayNameReplyLock) { m_SetDisplayNameReply -= value; } }
1249 }
1250  
1251 /// <summary>The event subscribers. null if no subcribers</summary>
1252 private EventHandler<EventArgs> m_MuteListUpdated;
1253  
1254 /// <summary>Raises the MuteListUpdated event</summary>
1255 /// <param name="e">A EventArgs object containing the
1256 /// data returned from the data server</param>
1257 protected virtual void OnMuteListUpdated(EventArgs e)
1258 {
1259 EventHandler<EventArgs> handler = m_MuteListUpdated;
1260 if (handler != null)
1261 handler(this, e);
1262 }
1263  
1264 /// <summary>Thread sync lock object</summary>
1265 private readonly object m_MuteListUpdatedLock = new object();
1266  
1267 /// <summary>Raised when a scripted object or agent within range sends a public message</summary>
1268 public event EventHandler<EventArgs> MuteListUpdated
1269 {
1270 add { lock (m_MuteListUpdatedLock) { m_MuteListUpdated += value; } }
1271 remove { lock (m_MuteListUpdatedLock) { m_MuteListUpdated -= value; } }
1272 }
1273 #endregion Callbacks
1274  
1275 /// <summary>Reference to the GridClient instance</summary>
1276 private readonly GridClient Client;
1277 /// <summary>Used for movement and camera tracking</summary>
1278 public readonly AgentMovement Movement;
1279 /// <summary>Currently playing animations for the agent. Can be used to
1280 /// check the current movement status such as walking, hovering, aiming,
1281 /// etc. by checking against system animations found in the Animations class</summary>
1282 public InternalDictionary<UUID, int> SignaledAnimations = new InternalDictionary<UUID, int>();
1283 /// <summary>Dictionary containing current Group Chat sessions and members</summary>
1284 public InternalDictionary<UUID, List<ChatSessionMember>> GroupChatSessions = new InternalDictionary<UUID, List<ChatSessionMember>>();
1285 /// <summary>Dictionary containing mute list keyead on mute name and key</summary>
1286 public InternalDictionary<string, MuteEntry> MuteList = new InternalDictionary<string, MuteEntry>();
1287  
1288 #region Properties
1289  
1290 /// <summary>Your (client) avatars <see cref="UUID"/></summary>
1291 /// <remarks>"client", "agent", and "avatar" all represent the same thing</remarks>
1292 public UUID AgentID { get { return id; } }
1293 /// <summary>Temporary <seealso cref="UUID"/> assigned to this session, used for
1294 /// verifying our identity in packets</summary>
1295 public UUID SessionID { get { return sessionID; } }
1296 /// <summary>Shared secret <seealso cref="UUID"/> that is never sent over the wire</summary>
1297 public UUID SecureSessionID { get { return secureSessionID; } }
1298 /// <summary>Your (client) avatar ID, local to the current region/sim</summary>
1299 public uint LocalID { get { return localID; } }
1300 /// <summary>Where the avatar started at login. Can be "last", "home"
1301 /// or a login <seealso cref="T:OpenMetaverse.URI"/></summary>
1302 public string StartLocation { get { return startLocation; } }
1303 /// <summary>The access level of this agent, usually M, PG or A</summary>
1304 public string AgentAccess { get { return agentAccess; } }
1305 /// <summary>The CollisionPlane of Agent</summary>
1306 public Vector4 CollisionPlane { get { return collisionPlane; } }
1307 /// <summary>An <seealso cref="Vector3"/> representing the velocity of our agent</summary>
1308 public Vector3 Velocity { get { return velocity; } }
1309 /// <summary>An <seealso cref="Vector3"/> representing the acceleration of our agent</summary>
1310 public Vector3 Acceleration { get { return acceleration; } }
1311 /// <summary>A <seealso cref="Vector3"/> which specifies the angular speed, and axis about which an Avatar is rotating.</summary>
1312 public Vector3 AngularVelocity { get { return angularVelocity; } }
1313 /// <summary>Position avatar client will goto when login to 'home' or during
1314 /// teleport request to 'home' region.</summary>
1315 public Vector3 HomePosition { get { return homePosition; } }
1316 /// <summary>LookAt point saved/restored with HomePosition</summary>
1317 public Vector3 HomeLookAt { get { return homeLookAt; } }
1318 /// <summary>Avatar First Name (i.e. Philip)</summary>
1319 public string FirstName { get { return firstName; } }
1320 /// <summary>Avatar Last Name (i.e. Linden)</summary>
1321 public string LastName { get { return lastName; } }
1322 /// <summary>LookAt point received with the login response message</summary>
1323 public Vector3 LookAt { get { return lookAt; } }
1324 /// <summary>Avatar Full Name (i.e. Philip Linden)</summary>
1325 public string Name
1326 {
1327 get
1328 {
1329 // This is a fairly common request, so assume the name doesn't
1330 // change mid-session and cache the result
1331 if (fullName == null || fullName.Length < 2)
1332 fullName = String.Format("{0} {1}", firstName, lastName);
1333 return fullName;
1334 }
1335 }
1336 /// <summary>Gets the health of the agent</summary>
1337 public float Health { get { return health; } }
1338 /// <summary>Gets the current balance of the agent</summary>
1339 public int Balance { get { return balance; } }
1340 /// <summary>Gets the local ID of the prim the agent is sitting on,
1341 /// zero if the avatar is not currently sitting</summary>
1342 public uint SittingOn { get { return sittingOn; } }
1343 /// <summary>Gets the <seealso cref="UUID"/> of the agents active group.</summary>
1344 public UUID ActiveGroup { get { return activeGroup; } }
1345 /// <summary>Gets the Agents powers in the currently active group</summary>
1346 public GroupPowers ActiveGroupPowers { get { return activeGroupPowers; } }
1347 /// <summary>Current status message for teleporting</summary>
1348 public string TeleportMessage { get { return teleportMessage; } }
1349 /// <summary>Current position of the agent as a relative offset from
1350 /// the simulator, or the parent object if we are sitting on something</summary>
1351 public Vector3 RelativePosition { get { return relativePosition; } set { relativePosition = value; } }
1352 /// <summary>Current rotation of the agent as a relative rotation from
1353 /// the simulator, or the parent object if we are sitting on something</summary>
1354 public Quaternion RelativeRotation { get { return relativeRotation; } set { relativeRotation = value; } }
1355 /// <summary>Current position of the agent in the simulator</summary>
1356 public Vector3 SimPosition
1357 {
1358 get
1359 {
1360 // simple case, agent not seated
1361 if (sittingOn == 0)
1362 {
1363 return relativePosition;
1364 }
1365  
1366 // a bit more complicatated, agent sitting on a prim
1367 Primitive p = null;
1368 Vector3 fullPosition = relativePosition;
1369  
1370 if (Client.Network.CurrentSim.ObjectsPrimitives.TryGetValue(sittingOn, out p))
1371 {
1372 fullPosition = p.Position + relativePosition * p.Rotation;
1373 }
1374  
1375 // go up the hiearchy trying to find the root prim
1376 while (p != null && p.ParentID != 0)
1377 {
1378 Avatar av;
1379 if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(p.ParentID, out av))
1380 {
1381 p = av;
1382 fullPosition += p.Position;
1383 }
1384 else
1385 {
1386 if (Client.Network.CurrentSim.ObjectsPrimitives.TryGetValue(p.ParentID, out p))
1387 {
1388 fullPosition += p.Position;
1389 }
1390 }
1391 }
1392  
1393 if (p != null) // we found the root prim
1394 {
1395 return fullPosition;
1396 }
1397  
1398 // Didn't find the seat's root prim, try returning coarse loaction
1399 if (Client.Network.CurrentSim.avatarPositions.TryGetValue(AgentID, out fullPosition))
1400 {
1401 return fullPosition;
1402 }
1403  
1404 Logger.Log("Failed to determine agents sim position", Helpers.LogLevel.Warning, Client);
1405 return relativePosition;
1406 }
1407 }
1408 /// <summary>
1409 /// A <seealso cref="Quaternion"/> representing the agents current rotation
1410 /// </summary>
1411 public Quaternion SimRotation
1412 {
1413 get
1414 {
1415 if (sittingOn != 0)
1416 {
1417 Primitive parent;
1418 if (Client.Network.CurrentSim != null && Client.Network.CurrentSim.ObjectsPrimitives.TryGetValue(sittingOn, out parent))
1419 {
1420 return relativeRotation * parent.Rotation;
1421 }
1422 else
1423 {
1424 Logger.Log("Currently sitting on object " + sittingOn + " which is not tracked, SimRotation will be inaccurate",
1425 Helpers.LogLevel.Warning, Client);
1426 return relativeRotation;
1427 }
1428 }
1429 else
1430 {
1431 return relativeRotation;
1432 }
1433 }
1434 }
1435 /// <summary>Returns the global grid position of the avatar</summary>
1436 public Vector3d GlobalPosition
1437 {
1438 get
1439 {
1440 if (Client.Network.CurrentSim != null)
1441 {
1442 uint globalX, globalY;
1443 Utils.LongToUInts(Client.Network.CurrentSim.Handle, out globalX, out globalY);
1444 Vector3 pos = SimPosition;
1445  
1446 return new Vector3d(
1447 (double)globalX + (double)pos.X,
1448 (double)globalY + (double)pos.Y,
1449 (double)pos.Z);
1450 }
1451 else
1452 return Vector3d.Zero;
1453 }
1454 }
1455  
1456 /// <summary>Various abilities and preferences sent by the grid</summary>
1457 public AgentStateUpdateMessage AgentStateStatus;
1458  
1459 #endregion Properties
1460  
1461 internal uint localID;
1462 internal Vector3 relativePosition;
1463 internal Quaternion relativeRotation = Quaternion.Identity;
1464 internal Vector4 collisionPlane;
1465 internal Vector3 velocity;
1466 internal Vector3 acceleration;
1467 internal Vector3 angularVelocity;
1468 internal uint sittingOn;
1469 internal int lastInterpolation;
1470  
1471 #region Private Members
1472  
1473 private UUID id;
1474 private UUID sessionID;
1475 private UUID secureSessionID;
1476 private string startLocation = String.Empty;
1477 private string agentAccess = String.Empty;
1478 private Vector3 homePosition;
1479 private Vector3 homeLookAt;
1480 private Vector3 lookAt;
1481 private string firstName = String.Empty;
1482 private string lastName = String.Empty;
1483 private string fullName;
1484 private string teleportMessage = String.Empty;
1485 private TeleportStatus teleportStat = TeleportStatus.None;
1486 private ManualResetEvent teleportEvent = new ManualResetEvent(false);
1487 private uint heightWidthGenCounter;
1488 private float health;
1489 private int balance;
1490 private UUID activeGroup;
1491 private GroupPowers activeGroupPowers;
1492 private Dictionary<UUID, AssetGesture> gestureCache = new Dictionary<UUID, AssetGesture>();
1493 #endregion Private Members
1494  
1495 /// <summary>
1496 /// Constructor, setup callbacks for packets related to our avatar
1497 /// </summary>
1498 /// <param name="client">A reference to the <seealso cref="T:OpenMetaverse.GridClient"/> Class</param>
1499 public AgentManager(GridClient client)
1500 {
1501 Client = client;
1502  
1503 Movement = new AgentMovement(Client);
1504  
1505 Client.Network.Disconnected += Network_OnDisconnected;
1506  
1507 // Teleport callbacks
1508 Client.Network.RegisterCallback(PacketType.TeleportStart, TeleportHandler);
1509 Client.Network.RegisterCallback(PacketType.TeleportProgress, TeleportHandler);
1510 Client.Network.RegisterCallback(PacketType.TeleportFailed, TeleportHandler);
1511 Client.Network.RegisterCallback(PacketType.TeleportCancel, TeleportHandler);
1512 Client.Network.RegisterCallback(PacketType.TeleportLocal, TeleportHandler);
1513 // these come in via the EventQueue
1514 Client.Network.RegisterEventCallback("TeleportFailed", new Caps.EventQueueCallback(TeleportFailedEventHandler));
1515 Client.Network.RegisterEventCallback("TeleportFinish", new Caps.EventQueueCallback(TeleportFinishEventHandler));
1516  
1517 // Instant message callback
1518 Client.Network.RegisterCallback(PacketType.ImprovedInstantMessage, InstantMessageHandler);
1519 // Chat callback
1520 Client.Network.RegisterCallback(PacketType.ChatFromSimulator, ChatHandler);
1521 // Script dialog callback
1522 Client.Network.RegisterCallback(PacketType.ScriptDialog, ScriptDialogHandler);
1523 // Script question callback
1524 Client.Network.RegisterCallback(PacketType.ScriptQuestion, ScriptQuestionHandler);
1525 // Script URL callback
1526 Client.Network.RegisterCallback(PacketType.LoadURL, LoadURLHandler);
1527 // Movement complete callback
1528 Client.Network.RegisterCallback(PacketType.AgentMovementComplete, MovementCompleteHandler);
1529 // Health callback
1530 Client.Network.RegisterCallback(PacketType.HealthMessage, HealthHandler);
1531 // Money callback
1532 Client.Network.RegisterCallback(PacketType.MoneyBalanceReply, MoneyBalanceReplyHandler);
1533 //Agent update callback
1534 Client.Network.RegisterCallback(PacketType.AgentDataUpdate, AgentDataUpdateHandler);
1535 // Animation callback
1536 Client.Network.RegisterCallback(PacketType.AvatarAnimation, AvatarAnimationHandler, false);
1537 // Object colliding into our agent callback
1538 Client.Network.RegisterCallback(PacketType.MeanCollisionAlert, MeanCollisionAlertHandler);
1539 // Region Crossing
1540 Client.Network.RegisterCallback(PacketType.CrossedRegion, CrossedRegionHandler);
1541 Client.Network.RegisterEventCallback("CrossedRegion", new Caps.EventQueueCallback(CrossedRegionEventHandler));
1542 // CAPS callbacks
1543 Client.Network.RegisterEventCallback("EstablishAgentCommunication", new Caps.EventQueueCallback(EstablishAgentCommunicationEventHandler));
1544 Client.Network.RegisterEventCallback("SetDisplayNameReply", new Caps.EventQueueCallback(SetDisplayNameReplyEventHandler));
1545 Client.Network.RegisterEventCallback("AgentStateUpdate", new Caps.EventQueueCallback(AgentStateUpdateEventHandler));
1546 // Incoming Group Chat
1547 Client.Network.RegisterEventCallback("ChatterBoxInvitation", new Caps.EventQueueCallback(ChatterBoxInvitationEventHandler));
1548 // Outgoing Group Chat Reply
1549 Client.Network.RegisterEventCallback("ChatterBoxSessionEventReply", new Caps.EventQueueCallback(ChatterBoxSessionEventReplyEventHandler));
1550 Client.Network.RegisterEventCallback("ChatterBoxSessionStartReply", new Caps.EventQueueCallback(ChatterBoxSessionStartReplyEventHandler));
1551 Client.Network.RegisterEventCallback("ChatterBoxSessionAgentListUpdates", new Caps.EventQueueCallback(ChatterBoxSessionAgentListUpdatesEventHandler));
1552 // Login
1553 Client.Network.RegisterLoginResponseCallback(new NetworkManager.LoginResponseCallback(Network_OnLoginResponse));
1554 // Alert Messages
1555 Client.Network.RegisterCallback(PacketType.AlertMessage, AlertMessageHandler);
1556 // script control change messages, ie: when an in-world LSL script wants to take control of your agent.
1557 Client.Network.RegisterCallback(PacketType.ScriptControlChange, ScriptControlChangeHandler);
1558 // Camera Constraint (probably needs to move to AgentManagerCamera TODO:
1559 Client.Network.RegisterCallback(PacketType.CameraConstraint, CameraConstraintHandler);
1560 Client.Network.RegisterCallback(PacketType.ScriptSensorReply, ScriptSensorReplyHandler);
1561 Client.Network.RegisterCallback(PacketType.AvatarSitResponse, AvatarSitResponseHandler);
1562 // Process mute list update message
1563 Client.Network.RegisterCallback(PacketType.MuteListUpdate, MuteListUpdateHander);
1564 }
1565  
1566 #region Chat and instant messages
1567  
1568 /// <summary>
1569 /// Send a text message from the Agent to the Simulator
1570 /// </summary>
1571 /// <param name="message">A <see cref="string"/> containing the message</param>
1572 /// <param name="channel">The channel to send the message on, 0 is the public channel. Channels above 0
1573 /// can be used however only scripts listening on the specified channel will see the message</param>
1574 /// <param name="type">Denotes the type of message being sent, shout, whisper, etc.</param>
1575 public void Chat(string message, int channel, ChatType type)
1576 {
1577 ChatFromViewerPacket chat = new ChatFromViewerPacket();
1578 chat.AgentData.AgentID = this.id;
1579 chat.AgentData.SessionID = Client.Self.SessionID;
1580 chat.ChatData.Channel = channel;
1581 chat.ChatData.Message = Utils.StringToBytes(message);
1582 chat.ChatData.Type = (byte)type;
1583  
1584 Client.Network.SendPacket(chat);
1585 }
1586  
1587 /// <summary>
1588 /// Request any instant messages sent while the client was offline to be resent.
1589 /// </summary>
1590 public void RetrieveInstantMessages()
1591 {
1592 RetrieveInstantMessagesPacket p = new RetrieveInstantMessagesPacket();
1593 p.AgentData.AgentID = Client.Self.AgentID;
1594 p.AgentData.SessionID = Client.Self.SessionID;
1595 Client.Network.SendPacket(p);
1596 }
1597  
1598 /// <summary>
1599 /// Send an Instant Message to another Avatar
1600 /// </summary>
1601 /// <param name="target">The recipients <see cref="UUID"/></param>
1602 /// <param name="message">A <see cref="string"/> containing the message to send</param>
1603 public void InstantMessage(UUID target, string message)
1604 {
1605 InstantMessage(Name, target, message, AgentID.Equals(target) ? AgentID : target ^ AgentID,
1606 InstantMessageDialog.MessageFromAgent, InstantMessageOnline.Offline, this.SimPosition,
1607 UUID.Zero, Utils.EmptyBytes);
1608 }
1609  
1610 /// <summary>
1611 /// Send an Instant Message to an existing group chat or conference chat
1612 /// </summary>
1613 /// <param name="target">The recipients <see cref="UUID"/></param>
1614 /// <param name="message">A <see cref="string"/> containing the message to send</param>
1615 /// <param name="imSessionID">IM session ID (to differentiate between IM windows)</param>
1616 public void InstantMessage(UUID target, string message, UUID imSessionID)
1617 {
1618 InstantMessage(Name, target, message, imSessionID,
1619 InstantMessageDialog.MessageFromAgent, InstantMessageOnline.Offline, this.SimPosition,
1620 UUID.Zero, Utils.EmptyBytes);
1621 }
1622  
1623 /// <summary>
1624 /// Send an Instant Message
1625 /// </summary>
1626 /// <param name="fromName">The name this IM will show up as being from</param>
1627 /// <param name="target">Key of Avatar</param>
1628 /// <param name="message">Text message being sent</param>
1629 /// <param name="imSessionID">IM session ID (to differentiate between IM windows)</param>
1630 /// <param name="conferenceIDs">IDs of sessions for a conference</param>
1631 public void InstantMessage(string fromName, UUID target, string message, UUID imSessionID,
1632 UUID[] conferenceIDs)
1633 {
1634 byte[] binaryBucket;
1635  
1636 if (conferenceIDs != null && conferenceIDs.Length > 0)
1637 {
1638 binaryBucket = new byte[16 * conferenceIDs.Length];
1639 for (int i = 0; i < conferenceIDs.Length; ++i)
1640 Buffer.BlockCopy(conferenceIDs[i].GetBytes(), 0, binaryBucket, i * 16, 16);
1641 }
1642 else
1643 {
1644 binaryBucket = Utils.EmptyBytes;
1645 }
1646  
1647 InstantMessage(fromName, target, message, imSessionID, InstantMessageDialog.MessageFromAgent,
1648 InstantMessageOnline.Offline, Vector3.Zero, UUID.Zero, binaryBucket);
1649 }
1650  
1651 /// <summary>
1652 /// Send an Instant Message
1653 /// </summary>
1654 /// <param name="fromName">The name this IM will show up as being from</param>
1655 /// <param name="target">Key of Avatar</param>
1656 /// <param name="message">Text message being sent</param>
1657 /// <param name="imSessionID">IM session ID (to differentiate between IM windows)</param>
1658 /// <param name="dialog">Type of instant message to send</param>
1659 /// <param name="offline">Whether to IM offline avatars as well</param>
1660 /// <param name="position">Senders Position</param>
1661 /// <param name="regionID">RegionID Sender is In</param>
1662 /// <param name="binaryBucket">Packed binary data that is specific to
1663 /// the dialog type</param>
1664 public void InstantMessage(string fromName, UUID target, string message, UUID imSessionID,
1665 InstantMessageDialog dialog, InstantMessageOnline offline, Vector3 position, UUID regionID,
1666 byte[] binaryBucket)
1667 {
1668 if (target != UUID.Zero)
1669 {
1670 ImprovedInstantMessagePacket im = new ImprovedInstantMessagePacket();
1671  
1672 if (imSessionID.Equals(UUID.Zero) || imSessionID.Equals(AgentID))
1673 imSessionID = AgentID.Equals(target) ? AgentID : target ^ AgentID;
1674  
1675 im.AgentData.AgentID = Client.Self.AgentID;
1676 im.AgentData.SessionID = Client.Self.SessionID;
1677  
1678 im.MessageBlock.Dialog = (byte)dialog;
1679 im.MessageBlock.FromAgentName = Utils.StringToBytes(fromName);
1680 im.MessageBlock.FromGroup = false;
1681 im.MessageBlock.ID = imSessionID;
1682 im.MessageBlock.Message = Utils.StringToBytes(message);
1683 im.MessageBlock.Offline = (byte)offline;
1684 im.MessageBlock.ToAgentID = target;
1685  
1686 if (binaryBucket != null)
1687 im.MessageBlock.BinaryBucket = binaryBucket;
1688 else
1689 im.MessageBlock.BinaryBucket = Utils.EmptyBytes;
1690  
1691 // These fields are mandatory, even if we don't have valid values for them
1692 im.MessageBlock.Position = Vector3.Zero;
1693 //TODO: Allow region id to be correctly set by caller or fetched from Client.*
1694 im.MessageBlock.RegionID = regionID;
1695  
1696 // Send the message
1697 Client.Network.SendPacket(im);
1698 }
1699 else
1700 {
1701 Logger.Log(String.Format("Suppressing instant message \"{0}\" to UUID.Zero", message),
1702 Helpers.LogLevel.Error, Client);
1703 }
1704 }
1705  
1706 /// <summary>
1707 /// Send an Instant Message to a group
1708 /// </summary>
1709 /// <param name="groupID"><seealso cref="UUID"/> of the group to send message to</param>
1710 /// <param name="message">Text Message being sent.</param>
1711 public void InstantMessageGroup(UUID groupID, string message)
1712 {
1713 InstantMessageGroup(Name, groupID, message);
1714 }
1715  
1716 /// <summary>
1717 /// Send an Instant Message to a group the agent is a member of
1718 /// </summary>
1719 /// <param name="fromName">The name this IM will show up as being from</param>
1720 /// <param name="groupID"><seealso cref="UUID"/> of the group to send message to</param>
1721 /// <param name="message">Text message being sent</param>
1722 public void InstantMessageGroup(string fromName, UUID groupID, string message)
1723 {
1724 lock (GroupChatSessions.Dictionary)
1725 if (GroupChatSessions.ContainsKey(groupID))
1726 {
1727 ImprovedInstantMessagePacket im = new ImprovedInstantMessagePacket();
1728  
1729 im.AgentData.AgentID = Client.Self.AgentID;
1730 im.AgentData.SessionID = Client.Self.SessionID;
1731 im.MessageBlock.Dialog = (byte)InstantMessageDialog.SessionSend;
1732 im.MessageBlock.FromAgentName = Utils.StringToBytes(fromName);
1733 im.MessageBlock.FromGroup = false;
1734 im.MessageBlock.Message = Utils.StringToBytes(message);
1735 im.MessageBlock.Offline = 0;
1736 im.MessageBlock.ID = groupID;
1737 im.MessageBlock.ToAgentID = groupID;
1738 im.MessageBlock.Position = Vector3.Zero;
1739 im.MessageBlock.RegionID = UUID.Zero;
1740 im.MessageBlock.BinaryBucket = Utils.StringToBytes("\0");
1741  
1742 Client.Network.SendPacket(im);
1743 }
1744 else
1745 {
1746 Logger.Log("No Active group chat session appears to exist, use RequestJoinGroupChat() to join one",
1747 Helpers.LogLevel.Error, Client);
1748 }
1749 }
1750  
1751 /// <summary>
1752 /// Send a request to join a group chat session
1753 /// </summary>
1754 /// <param name="groupID"><seealso cref="UUID"/> of Group to leave</param>
1755 public void RequestJoinGroupChat(UUID groupID)
1756 {
1757 ImprovedInstantMessagePacket im = new ImprovedInstantMessagePacket();
1758  
1759 im.AgentData.AgentID = Client.Self.AgentID;
1760 im.AgentData.SessionID = Client.Self.SessionID;
1761 im.MessageBlock.Dialog = (byte)InstantMessageDialog.SessionGroupStart;
1762 im.MessageBlock.FromAgentName = Utils.StringToBytes(Client.Self.Name);
1763 im.MessageBlock.FromGroup = false;
1764 im.MessageBlock.Message = Utils.EmptyBytes;
1765 im.MessageBlock.ParentEstateID = 0;
1766 im.MessageBlock.Offline = 0;
1767 im.MessageBlock.ID = groupID;
1768 im.MessageBlock.ToAgentID = groupID;
1769 im.MessageBlock.BinaryBucket = Utils.EmptyBytes;
1770 im.MessageBlock.Position = Client.Self.SimPosition;
1771 im.MessageBlock.RegionID = UUID.Zero;
1772  
1773 Client.Network.SendPacket(im);
1774 }
1775  
1776 /// <summary>
1777 /// Exit a group chat session. This will stop further Group chat messages
1778 /// from being sent until session is rejoined.
1779 /// </summary>
1780 /// <param name="groupID"><seealso cref="UUID"/> of Group chat session to leave</param>
1781 public void RequestLeaveGroupChat(UUID groupID)
1782 {
1783 ImprovedInstantMessagePacket im = new ImprovedInstantMessagePacket();
1784  
1785 im.AgentData.AgentID = Client.Self.AgentID;
1786 im.AgentData.SessionID = Client.Self.SessionID;
1787 im.MessageBlock.Dialog = (byte)InstantMessageDialog.SessionDrop;
1788 im.MessageBlock.FromAgentName = Utils.StringToBytes(Client.Self.Name);
1789 im.MessageBlock.FromGroup = false;
1790 im.MessageBlock.Message = Utils.EmptyBytes;
1791 im.MessageBlock.Offline = 0;
1792 im.MessageBlock.ID = groupID;
1793 im.MessageBlock.ToAgentID = groupID;
1794 im.MessageBlock.BinaryBucket = Utils.EmptyBytes;
1795 im.MessageBlock.Position = Vector3.Zero;
1796 im.MessageBlock.RegionID = UUID.Zero;
1797  
1798 Client.Network.SendPacket(im);
1799  
1800 lock (GroupChatSessions.Dictionary)
1801 if (GroupChatSessions.ContainsKey(groupID))
1802 GroupChatSessions.Remove(groupID);
1803 }
1804  
1805 /// <summary>
1806 /// Reply to script dialog questions.
1807 /// </summary>
1808 /// <param name="channel">Channel initial request came on</param>
1809 /// <param name="buttonIndex">Index of button you're "clicking"</param>
1810 /// <param name="buttonlabel">Label of button you're "clicking"</param>
1811 /// <param name="objectID"><seealso cref="UUID"/> of Object that sent the dialog request</param>
1812 /// <seealso cref="OnScriptDialog"/>
1813 public void ReplyToScriptDialog(int channel, int buttonIndex, string buttonlabel, UUID objectID)
1814 {
1815 ScriptDialogReplyPacket reply = new ScriptDialogReplyPacket();
1816  
1817 reply.AgentData.AgentID = Client.Self.AgentID;
1818 reply.AgentData.SessionID = Client.Self.SessionID;
1819  
1820 reply.Data.ButtonIndex = buttonIndex;
1821 reply.Data.ButtonLabel = Utils.StringToBytes(buttonlabel);
1822 reply.Data.ChatChannel = channel;
1823 reply.Data.ObjectID = objectID;
1824  
1825 Client.Network.SendPacket(reply);
1826 }
1827  
1828 /// <summary>
1829 /// Accept invite for to a chatterbox session
1830 /// </summary>
1831 /// <param name="session_id"><seealso cref="UUID"/> of session to accept invite to</param>
1832 public void ChatterBoxAcceptInvite(UUID session_id)
1833 {
1834 if (Client.Network.CurrentSim == null || Client.Network.CurrentSim.Caps == null)
1835 throw new Exception("ChatSessionRequest capability is not currently available");
1836  
1837 Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("ChatSessionRequest");
1838  
1839 if (url != null)
1840 {
1841 ChatSessionAcceptInvitation acceptInvite = new ChatSessionAcceptInvitation();
1842 acceptInvite.SessionID = session_id;
1843  
1844 CapsClient request = new CapsClient(url);
1845 request.BeginGetResponse(acceptInvite.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
1846  
1847 lock (GroupChatSessions.Dictionary)
1848 if (!GroupChatSessions.ContainsKey(session_id))
1849 GroupChatSessions.Add(session_id, new List<ChatSessionMember>());
1850 }
1851 else
1852 {
1853 throw new Exception("ChatSessionRequest capability is not currently available");
1854 }
1855  
1856 }
1857  
1858 /// <summary>
1859 /// Start a friends conference
1860 /// </summary>
1861 /// <param name="participants"><seealso cref="UUID"/> List of UUIDs to start a conference with</param>
1862 /// <param name="tmp_session_id">the temportary session ID returned in the <see cref="OnJoinedGroupChat"/> callback></param>
1863 public void StartIMConference(List<UUID> participants, UUID tmp_session_id)
1864 {
1865 if (Client.Network.CurrentSim == null || Client.Network.CurrentSim.Caps == null)
1866 throw new Exception("ChatSessionRequest capability is not currently available");
1867  
1868 Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("ChatSessionRequest");
1869  
1870 if (url != null)
1871 {
1872 ChatSessionRequestStartConference startConference = new ChatSessionRequestStartConference();
1873  
1874 startConference.AgentsBlock = new UUID[participants.Count];
1875 for (int i = 0; i < participants.Count; i++)
1876 startConference.AgentsBlock[i] = participants[i];
1877  
1878 startConference.SessionID = tmp_session_id;
1879  
1880 CapsClient request = new CapsClient(url);
1881 request.BeginGetResponse(startConference.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
1882 }
1883 else
1884 {
1885 throw new Exception("ChatSessionRequest capability is not currently available");
1886 }
1887 }
1888  
1889 #endregion Chat and instant messages
1890  
1891 #region Viewer Effects
1892  
1893 /// <summary>
1894 /// Start a particle stream between an agent and an object
1895 /// </summary>
1896 /// <param name="sourceAvatar"><seealso cref="UUID"/> Key of the source agent</param>
1897 /// <param name="targetObject"><seealso cref="UUID"/> Key of the target object</param>
1898 /// <param name="globalOffset"></param>
1899 /// <param name="type">The type from the <seealso cref="T:PointAtType"/> enum</param>
1900 /// <param name="effectID">A unique <seealso cref="UUID"/> for this effect</param>
1901 public void PointAtEffect(UUID sourceAvatar, UUID targetObject, Vector3d globalOffset, PointAtType type,
1902 UUID effectID)
1903 {
1904 ViewerEffectPacket effect = new ViewerEffectPacket();
1905  
1906 effect.AgentData.AgentID = Client.Self.AgentID;
1907 effect.AgentData.SessionID = Client.Self.SessionID;
1908  
1909 effect.Effect = new ViewerEffectPacket.EffectBlock[1];
1910 effect.Effect[0] = new ViewerEffectPacket.EffectBlock();
1911 effect.Effect[0].AgentID = Client.Self.AgentID;
1912 effect.Effect[0].Color = new byte[4];
1913 effect.Effect[0].Duration = (type == PointAtType.Clear) ? 0.0f : Single.MaxValue / 4.0f;
1914 effect.Effect[0].ID = effectID;
1915 effect.Effect[0].Type = (byte)EffectType.PointAt;
1916  
1917 byte[] typeData = new byte[57];
1918 if (sourceAvatar != UUID.Zero)
1919 Buffer.BlockCopy(sourceAvatar.GetBytes(), 0, typeData, 0, 16);
1920 if (targetObject != UUID.Zero)
1921 Buffer.BlockCopy(targetObject.GetBytes(), 0, typeData, 16, 16);
1922 Buffer.BlockCopy(globalOffset.GetBytes(), 0, typeData, 32, 24);
1923 typeData[56] = (byte)type;
1924  
1925 effect.Effect[0].TypeData = typeData;
1926  
1927 Client.Network.SendPacket(effect);
1928 }
1929  
1930 /// <summary>
1931 /// Start a particle stream between an agent and an object
1932 /// </summary>
1933 /// <param name="sourceAvatar"><seealso cref="UUID"/> Key of the source agent</param>
1934 /// <param name="targetObject"><seealso cref="UUID"/> Key of the target object</param>
1935 /// <param name="globalOffset">A <seealso cref="Vector3d"/> representing the beams offset from the source</param>
1936 /// <param name="type">A <seealso cref="T:PointAtType"/> which sets the avatars lookat animation</param>
1937 /// <param name="effectID"><seealso cref="UUID"/> of the Effect</param>
1938 public void LookAtEffect(UUID sourceAvatar, UUID targetObject, Vector3d globalOffset, LookAtType type,
1939 UUID effectID)
1940 {
1941 ViewerEffectPacket effect = new ViewerEffectPacket();
1942  
1943 effect.AgentData.AgentID = Client.Self.AgentID;
1944 effect.AgentData.SessionID = Client.Self.SessionID;
1945  
1946 float duration;
1947  
1948 switch (type)
1949 {
1950 case LookAtType.Clear:
1951 duration = 2.0f;
1952 break;
1953 case LookAtType.Hover:
1954 duration = 1.0f;
1955 break;
1956 case LookAtType.FreeLook:
1957 duration = 2.0f;
1958 break;
1959 case LookAtType.Idle:
1960 duration = 3.0f;
1961 break;
1962 case LookAtType.AutoListen:
1963 case LookAtType.Respond:
1964 duration = 4.0f;
1965 break;
1966 case LookAtType.None:
1967 case LookAtType.Select:
1968 case LookAtType.Focus:
1969 case LookAtType.Mouselook:
1970 duration = Single.MaxValue / 2.0f;
1971 break;
1972 default:
1973 duration = 0.0f;
1974 break;
1975 }
1976  
1977 effect.Effect = new ViewerEffectPacket.EffectBlock[1];
1978 effect.Effect[0] = new ViewerEffectPacket.EffectBlock();
1979 effect.Effect[0].AgentID = Client.Self.AgentID;
1980 effect.Effect[0].Color = new byte[4];
1981 effect.Effect[0].Duration = duration;
1982 effect.Effect[0].ID = effectID;
1983 effect.Effect[0].Type = (byte)EffectType.LookAt;
1984  
1985 byte[] typeData = new byte[57];
1986 Buffer.BlockCopy(sourceAvatar.GetBytes(), 0, typeData, 0, 16);
1987 Buffer.BlockCopy(targetObject.GetBytes(), 0, typeData, 16, 16);
1988 Buffer.BlockCopy(globalOffset.GetBytes(), 0, typeData, 32, 24);
1989 typeData[56] = (byte)type;
1990  
1991 effect.Effect[0].TypeData = typeData;
1992  
1993 Client.Network.SendPacket(effect);
1994 }
1995  
1996 /// <summary>
1997 /// Create a particle beam between an avatar and an primitive
1998 /// </summary>
1999 /// <param name="sourceAvatar">The ID of source avatar</param>
2000 /// <param name="targetObject">The ID of the target primitive</param>
2001 /// <param name="globalOffset">global offset</param>
2002 /// <param name="color">A <see cref="Color4"/> object containing the combined red, green, blue and alpha
2003 /// color values of particle beam</param>
2004 /// <param name="duration">a float representing the duration the parcicle beam will last</param>
2005 /// <param name="effectID">A Unique ID for the beam</param>
2006 /// <seealso cref="ViewerEffectPacket"/>
2007 public void BeamEffect(UUID sourceAvatar, UUID targetObject, Vector3d globalOffset, Color4 color,
2008 float duration, UUID effectID)
2009 {
2010 ViewerEffectPacket effect = new ViewerEffectPacket();
2011  
2012 effect.AgentData.AgentID = Client.Self.AgentID;
2013 effect.AgentData.SessionID = Client.Self.SessionID;
2014  
2015 effect.Effect = new ViewerEffectPacket.EffectBlock[1];
2016 effect.Effect[0] = new ViewerEffectPacket.EffectBlock();
2017 effect.Effect[0].AgentID = Client.Self.AgentID;
2018 effect.Effect[0].Color = color.GetBytes();
2019 effect.Effect[0].Duration = duration;
2020 effect.Effect[0].ID = effectID;
2021 effect.Effect[0].Type = (byte)EffectType.Beam;
2022  
2023 byte[] typeData = new byte[56];
2024 Buffer.BlockCopy(sourceAvatar.GetBytes(), 0, typeData, 0, 16);
2025 Buffer.BlockCopy(targetObject.GetBytes(), 0, typeData, 16, 16);
2026 Buffer.BlockCopy(globalOffset.GetBytes(), 0, typeData, 32, 24);
2027  
2028 effect.Effect[0].TypeData = typeData;
2029  
2030 Client.Network.SendPacket(effect);
2031 }
2032  
2033 /// <summary>
2034 /// Create a particle swirl around a target position using a <seealso cref="ViewerEffectPacket"/> packet
2035 /// </summary>
2036 /// <param name="globalOffset">global offset</param>
2037 /// <param name="color">A <see cref="Color4"/> object containing the combined red, green, blue and alpha
2038 /// color values of particle beam</param>
2039 /// <param name="duration">a float representing the duration the parcicle beam will last</param>
2040 /// <param name="effectID">A Unique ID for the beam</param>
2041 public void SphereEffect(Vector3d globalOffset, Color4 color, float duration, UUID effectID)
2042 {
2043 ViewerEffectPacket effect = new ViewerEffectPacket();
2044  
2045 effect.AgentData.AgentID = Client.Self.AgentID;
2046 effect.AgentData.SessionID = Client.Self.SessionID;
2047  
2048 effect.Effect = new ViewerEffectPacket.EffectBlock[1];
2049 effect.Effect[0] = new ViewerEffectPacket.EffectBlock();
2050 effect.Effect[0].AgentID = Client.Self.AgentID;
2051 effect.Effect[0].Color = color.GetBytes();
2052 effect.Effect[0].Duration = duration;
2053 effect.Effect[0].ID = effectID;
2054 effect.Effect[0].Type = (byte)EffectType.Sphere;
2055  
2056 byte[] typeData = new byte[56];
2057 Buffer.BlockCopy(UUID.Zero.GetBytes(), 0, typeData, 0, 16);
2058 Buffer.BlockCopy(UUID.Zero.GetBytes(), 0, typeData, 16, 16);
2059 Buffer.BlockCopy(globalOffset.GetBytes(), 0, typeData, 32, 24);
2060  
2061 effect.Effect[0].TypeData = typeData;
2062  
2063 Client.Network.SendPacket(effect);
2064 }
2065  
2066  
2067 #endregion Viewer Effects
2068  
2069 #region Movement Actions
2070  
2071 /// <summary>
2072 /// Sends a request to sit on the specified object
2073 /// </summary>
2074 /// <param name="targetID"><seealso cref="UUID"/> of the object to sit on</param>
2075 /// <param name="offset">Sit at offset</param>
2076 public void RequestSit(UUID targetID, Vector3 offset)
2077 {
2078 AgentRequestSitPacket requestSit = new AgentRequestSitPacket();
2079 requestSit.AgentData.AgentID = Client.Self.AgentID;
2080 requestSit.AgentData.SessionID = Client.Self.SessionID;
2081 requestSit.TargetObject.TargetID = targetID;
2082 requestSit.TargetObject.Offset = offset;
2083 Client.Network.SendPacket(requestSit);
2084 }
2085  
2086 /// <summary>
2087 /// Follows a call to <seealso cref="RequestSit"/> to actually sit on the object
2088 /// </summary>
2089 public void Sit()
2090 {
2091 AgentSitPacket sit = new AgentSitPacket();
2092 sit.AgentData.AgentID = Client.Self.AgentID;
2093 sit.AgentData.SessionID = Client.Self.SessionID;
2094 Client.Network.SendPacket(sit);
2095 }
2096  
2097 /// <summary>Stands up from sitting on a prim or the ground</summary>
2098 /// <returns>true of AgentUpdate was sent</returns>
2099 public bool Stand()
2100 {
2101 if (Client.Settings.SEND_AGENT_UPDATES)
2102 {
2103 Movement.SitOnGround = false;
2104 Movement.StandUp = true;
2105 Movement.SendUpdate();
2106 Movement.StandUp = false;
2107 Movement.SendUpdate();
2108 return true;
2109 }
2110 else
2111 {
2112 Logger.Log("Attempted to Stand() but agent updates are disabled", Helpers.LogLevel.Warning, Client);
2113 return false;
2114 }
2115 }
2116  
2117 /// <summary>
2118 /// Does a "ground sit" at the avatar's current position
2119 /// </summary>
2120 public void SitOnGround()
2121 {
2122 Movement.SitOnGround = true;
2123 Movement.SendUpdate(true);
2124 }
2125  
2126 /// <summary>
2127 /// Starts or stops flying
2128 /// </summary>
2129 /// <param name="start">True to start flying, false to stop flying</param>
2130 public void Fly(bool start)
2131 {
2132 if (start)
2133 Movement.Fly = true;
2134 else
2135 Movement.Fly = false;
2136  
2137 Movement.SendUpdate(true);
2138 }
2139  
2140 /// <summary>
2141 /// Starts or stops crouching
2142 /// </summary>
2143 /// <param name="crouching">True to start crouching, false to stop crouching</param>
2144 public void Crouch(bool crouching)
2145 {
2146 Movement.UpNeg = crouching;
2147 Movement.SendUpdate(true);
2148 }
2149  
2150 /// <summary>
2151 /// Starts a jump (begin holding the jump key)
2152 /// </summary>
2153 public void Jump(bool jumping)
2154 {
2155 Movement.UpPos = jumping;
2156 Movement.FastUp = jumping;
2157 Movement.SendUpdate(true);
2158 }
2159  
2160 /// <summary>
2161 /// Use the autopilot sim function to move the avatar to a new
2162 /// position. Uses double precision to get precise movements
2163 /// </summary>
2164 /// <remarks>The z value is currently not handled properly by the simulator</remarks>
2165 /// <param name="globalX">Global X coordinate to move to</param>
2166 /// <param name="globalY">Global Y coordinate to move to</param>
2167 /// <param name="z">Z coordinate to move to</param>
2168 public void AutoPilot(double globalX, double globalY, double z)
2169 {
2170 GenericMessagePacket autopilot = new GenericMessagePacket();
2171  
2172 autopilot.AgentData.AgentID = Client.Self.AgentID;
2173 autopilot.AgentData.SessionID = Client.Self.SessionID;
2174 autopilot.AgentData.TransactionID = UUID.Zero;
2175 autopilot.MethodData.Invoice = UUID.Zero;
2176 autopilot.MethodData.Method = Utils.StringToBytes("autopilot");
2177 autopilot.ParamList = new GenericMessagePacket.ParamListBlock[3];
2178 autopilot.ParamList[0] = new GenericMessagePacket.ParamListBlock();
2179 autopilot.ParamList[0].Parameter = Utils.StringToBytes(globalX.ToString());
2180 autopilot.ParamList[1] = new GenericMessagePacket.ParamListBlock();
2181 autopilot.ParamList[1].Parameter = Utils.StringToBytes(globalY.ToString());
2182 autopilot.ParamList[2] = new GenericMessagePacket.ParamListBlock();
2183 autopilot.ParamList[2].Parameter = Utils.StringToBytes(z.ToString());
2184  
2185 Client.Network.SendPacket(autopilot);
2186 }
2187  
2188 /// <summary>
2189 /// Use the autopilot sim function to move the avatar to a new position
2190 /// </summary>
2191 /// <remarks>The z value is currently not handled properly by the simulator</remarks>
2192 /// <param name="globalX">Integer value for the global X coordinate to move to</param>
2193 /// <param name="globalY">Integer value for the global Y coordinate to move to</param>
2194 /// <param name="z">Floating-point value for the Z coordinate to move to</param>
2195 public void AutoPilot(ulong globalX, ulong globalY, float z)
2196 {
2197 GenericMessagePacket autopilot = new GenericMessagePacket();
2198  
2199 autopilot.AgentData.AgentID = Client.Self.AgentID;
2200 autopilot.AgentData.SessionID = Client.Self.SessionID;
2201 autopilot.AgentData.TransactionID = UUID.Zero;
2202 autopilot.MethodData.Invoice = UUID.Zero;
2203 autopilot.MethodData.Method = Utils.StringToBytes("autopilot");
2204 autopilot.ParamList = new GenericMessagePacket.ParamListBlock[3];
2205 autopilot.ParamList[0] = new GenericMessagePacket.ParamListBlock();
2206 autopilot.ParamList[0].Parameter = Utils.StringToBytes(globalX.ToString());
2207 autopilot.ParamList[1] = new GenericMessagePacket.ParamListBlock();
2208 autopilot.ParamList[1].Parameter = Utils.StringToBytes(globalY.ToString());
2209 autopilot.ParamList[2] = new GenericMessagePacket.ParamListBlock();
2210 autopilot.ParamList[2].Parameter = Utils.StringToBytes(z.ToString());
2211  
2212 Client.Network.SendPacket(autopilot);
2213 }
2214  
2215 /// <summary>
2216 /// Use the autopilot sim function to move the avatar to a new position
2217 /// </summary>
2218 /// <remarks>The z value is currently not handled properly by the simulator</remarks>
2219 /// <param name="localX">Integer value for the local X coordinate to move to</param>
2220 /// <param name="localY">Integer value for the local Y coordinate to move to</param>
2221 /// <param name="z">Floating-point value for the Z coordinate to move to</param>
2222 public void AutoPilotLocal(int localX, int localY, float z)
2223 {
2224 uint x, y;
2225 Utils.LongToUInts(Client.Network.CurrentSim.Handle, out x, out y);
2226 AutoPilot((ulong)(x + localX), (ulong)(y + localY), z);
2227 }
2228  
2229 /// <summary>Macro to cancel autopilot sim function</summary>
2230 /// <remarks>Not certain if this is how it is really done</remarks>
2231 /// <returns>true if control flags were set and AgentUpdate was sent to the simulator</returns>
2232 public bool AutoPilotCancel()
2233 {
2234 if (Client.Settings.SEND_AGENT_UPDATES)
2235 {
2236 Movement.AtPos = true;
2237 Movement.SendUpdate();
2238 Movement.AtPos = false;
2239 Movement.SendUpdate();
2240 return true;
2241 }
2242 else
2243 {
2244 Logger.Log("Attempted to AutoPilotCancel() but agent updates are disabled", Helpers.LogLevel.Warning, Client);
2245 return false;
2246 }
2247 }
2248  
2249 #endregion Movement actions
2250  
2251 #region Touch and grab
2252  
2253 /// <summary>
2254 /// Grabs an object
2255 /// </summary>
2256 /// <param name="objectLocalID">an unsigned integer of the objects ID within the simulator</param>
2257 /// <seealso cref="Simulator.ObjectsPrimitives"/>
2258 public void Grab(uint objectLocalID)
2259 {
2260 Grab(objectLocalID, Vector3.Zero, Vector3.Zero, Vector3.Zero, 0, Vector3.Zero, Vector3.Zero, Vector3.Zero);
2261 }
2262  
2263 /// <summary>
2264 /// Overload: Grab a simulated object
2265 /// </summary>
2266 /// <param name="objectLocalID">an unsigned integer of the objects ID within the simulator</param>
2267 /// <param name="grabOffset"></param>
2268 /// <param name="uvCoord">The texture coordinates to grab</param>
2269 /// <param name="stCoord">The surface coordinates to grab</param>
2270 /// <param name="faceIndex">The face of the position to grab</param>
2271 /// <param name="position">The region coordinates of the position to grab</param>
2272 /// <param name="normal">The surface normal of the position to grab (A normal is a vector perpindicular to the surface)</param>
2273 /// <param name="binormal">The surface binormal of the position to grab (A binormal is a vector tangen to the surface
2274 /// pointing along the U direction of the tangent space</param>
2275 public void Grab(uint objectLocalID, Vector3 grabOffset, Vector3 uvCoord, Vector3 stCoord, int faceIndex, Vector3 position,
2276 Vector3 normal, Vector3 binormal)
2277 {
2278 ObjectGrabPacket grab = new ObjectGrabPacket();
2279  
2280 grab.AgentData.AgentID = Client.Self.AgentID;
2281 grab.AgentData.SessionID = Client.Self.SessionID;
2282  
2283 grab.ObjectData.LocalID = objectLocalID;
2284 grab.ObjectData.GrabOffset = grabOffset;
2285  
2286 grab.SurfaceInfo = new ObjectGrabPacket.SurfaceInfoBlock[1];
2287 grab.SurfaceInfo[0] = new ObjectGrabPacket.SurfaceInfoBlock();
2288 grab.SurfaceInfo[0].UVCoord = uvCoord;
2289 grab.SurfaceInfo[0].STCoord = stCoord;
2290 grab.SurfaceInfo[0].FaceIndex = faceIndex;
2291 grab.SurfaceInfo[0].Position = position;
2292 grab.SurfaceInfo[0].Normal = normal;
2293 grab.SurfaceInfo[0].Binormal = binormal;
2294  
2295 Client.Network.SendPacket(grab);
2296 }
2297  
2298 /// <summary>
2299 /// Drag an object
2300 /// </summary>
2301 /// <param name="objectID"><seealso cref="UUID"/> of the object to drag</param>
2302 /// <param name="grabPosition">Drag target in region coordinates</param>
2303 public void GrabUpdate(UUID objectID, Vector3 grabPosition)
2304 {
2305 GrabUpdate(objectID, grabPosition, Vector3.Zero, Vector3.Zero, Vector3.Zero, 0, Vector3.Zero, Vector3.Zero, Vector3.Zero);
2306 }
2307  
2308 /// <summary>
2309 /// Overload: Drag an object
2310 /// </summary>
2311 /// <param name="objectID"><seealso cref="UUID"/> of the object to drag</param>
2312 /// <param name="grabPosition">Drag target in region coordinates</param>
2313 /// <param name="grabOffset"></param>
2314 /// <param name="uvCoord">The texture coordinates to grab</param>
2315 /// <param name="stCoord">The surface coordinates to grab</param>
2316 /// <param name="faceIndex">The face of the position to grab</param>
2317 /// <param name="position">The region coordinates of the position to grab</param>
2318 /// <param name="normal">The surface normal of the position to grab (A normal is a vector perpindicular to the surface)</param>
2319 /// <param name="binormal">The surface binormal of the position to grab (A binormal is a vector tangen to the surface
2320 /// pointing along the U direction of the tangent space</param>
2321 public void GrabUpdate(UUID objectID, Vector3 grabPosition, Vector3 grabOffset, Vector3 uvCoord, Vector3 stCoord, int faceIndex, Vector3 position,
2322 Vector3 normal, Vector3 binormal)
2323 {
2324 ObjectGrabUpdatePacket grab = new ObjectGrabUpdatePacket();
2325 grab.AgentData.AgentID = Client.Self.AgentID;
2326 grab.AgentData.SessionID = Client.Self.SessionID;
2327  
2328 grab.ObjectData.ObjectID = objectID;
2329 grab.ObjectData.GrabOffsetInitial = grabOffset;
2330 grab.ObjectData.GrabPosition = grabPosition;
2331 grab.ObjectData.TimeSinceLast = 0;
2332  
2333 grab.SurfaceInfo = new ObjectGrabUpdatePacket.SurfaceInfoBlock[1];
2334 grab.SurfaceInfo[0] = new ObjectGrabUpdatePacket.SurfaceInfoBlock();
2335 grab.SurfaceInfo[0].UVCoord = uvCoord;
2336 grab.SurfaceInfo[0].STCoord = stCoord;
2337 grab.SurfaceInfo[0].FaceIndex = faceIndex;
2338 grab.SurfaceInfo[0].Position = position;
2339 grab.SurfaceInfo[0].Normal = normal;
2340 grab.SurfaceInfo[0].Binormal = binormal;
2341  
2342 Client.Network.SendPacket(grab);
2343 }
2344  
2345 /// <summary>
2346 /// Release a grabbed object
2347 /// </summary>
2348 /// <param name="objectLocalID">The Objects Simulator Local ID</param>
2349 /// <seealso cref="Simulator.ObjectsPrimitives"/>
2350 /// <seealso cref="Grab"/>
2351 /// <seealso cref="GrabUpdate"/>
2352 public void DeGrab(uint objectLocalID)
2353 {
2354 DeGrab(objectLocalID, Vector3.Zero, Vector3.Zero, 0, Vector3.Zero, Vector3.Zero, Vector3.Zero);
2355 }
2356  
2357 /// <summary>
2358 /// Release a grabbed object
2359 /// </summary>
2360 /// <param name="objectLocalID">The Objects Simulator Local ID</param>
2361 /// <param name="uvCoord">The texture coordinates to grab</param>
2362 /// <param name="stCoord">The surface coordinates to grab</param>
2363 /// <param name="faceIndex">The face of the position to grab</param>
2364 /// <param name="position">The region coordinates of the position to grab</param>
2365 /// <param name="normal">The surface normal of the position to grab (A normal is a vector perpindicular to the surface)</param>
2366 /// <param name="binormal">The surface binormal of the position to grab (A binormal is a vector tangen to the surface
2367 /// pointing along the U direction of the tangent space</param>
2368 public void DeGrab(uint objectLocalID, Vector3 uvCoord, Vector3 stCoord, int faceIndex, Vector3 position,
2369 Vector3 normal, Vector3 binormal)
2370 {
2371 ObjectDeGrabPacket degrab = new ObjectDeGrabPacket();
2372 degrab.AgentData.AgentID = Client.Self.AgentID;
2373 degrab.AgentData.SessionID = Client.Self.SessionID;
2374  
2375 degrab.ObjectData.LocalID = objectLocalID;
2376  
2377 degrab.SurfaceInfo = new ObjectDeGrabPacket.SurfaceInfoBlock[1];
2378 degrab.SurfaceInfo[0] = new ObjectDeGrabPacket.SurfaceInfoBlock();
2379 degrab.SurfaceInfo[0].UVCoord = uvCoord;
2380 degrab.SurfaceInfo[0].STCoord = stCoord;
2381 degrab.SurfaceInfo[0].FaceIndex = faceIndex;
2382 degrab.SurfaceInfo[0].Position = position;
2383 degrab.SurfaceInfo[0].Normal = normal;
2384 degrab.SurfaceInfo[0].Binormal = binormal;
2385  
2386 Client.Network.SendPacket(degrab);
2387 }
2388  
2389 /// <summary>
2390 /// Touches an object
2391 /// </summary>
2392 /// <param name="objectLocalID">an unsigned integer of the objects ID within the simulator</param>
2393 /// <seealso cref="Simulator.ObjectsPrimitives"/>
2394 public void Touch(uint objectLocalID)
2395 {
2396 Client.Self.Grab(objectLocalID);
2397 Client.Self.DeGrab(objectLocalID);
2398 }
2399  
2400 #endregion Touch and grab
2401  
2402 #region Money
2403  
2404 /// <summary>
2405 /// Request the current L$ balance
2406 /// </summary>
2407 public void RequestBalance()
2408 {
2409 MoneyBalanceRequestPacket money = new MoneyBalanceRequestPacket();
2410 money.AgentData.AgentID = Client.Self.AgentID;
2411 money.AgentData.SessionID = Client.Self.SessionID;
2412 money.MoneyData.TransactionID = UUID.Zero;
2413  
2414 Client.Network.SendPacket(money);
2415 }
2416  
2417 /// <summary>
2418 /// Give Money to destination Avatar
2419 /// </summary>
2420 /// <param name="target">UUID of the Target Avatar</param>
2421 /// <param name="amount">Amount in L$</param>
2422 public void GiveAvatarMoney(UUID target, int amount)
2423 {
2424 GiveMoney(target, amount, String.Empty, MoneyTransactionType.Gift, TransactionFlags.None);
2425 }
2426  
2427 /// <summary>
2428 /// Give Money to destination Avatar
2429 /// </summary>
2430 /// <param name="target">UUID of the Target Avatar</param>
2431 /// <param name="amount">Amount in L$</param>
2432 /// <param name="description">Description that will show up in the
2433 /// recipients transaction history</param>
2434 public void GiveAvatarMoney(UUID target, int amount, string description)
2435 {
2436 GiveMoney(target, amount, description, MoneyTransactionType.Gift, TransactionFlags.None);
2437 }
2438  
2439 /// <summary>
2440 /// Give L$ to an object
2441 /// </summary>
2442 /// <param name="target">object <seealso cref="UUID"/> to give money to</param>
2443 /// <param name="amount">amount of L$ to give</param>
2444 /// <param name="objectName">name of object</param>
2445 public void GiveObjectMoney(UUID target, int amount, string objectName)
2446 {
2447 GiveMoney(target, amount, objectName, MoneyTransactionType.PayObject, TransactionFlags.None);
2448 }
2449  
2450 /// <summary>
2451 /// Give L$ to a group
2452 /// </summary>
2453 /// <param name="target">group <seealso cref="UUID"/> to give money to</param>
2454 /// <param name="amount">amount of L$ to give</param>
2455 public void GiveGroupMoney(UUID target, int amount)
2456 {
2457 GiveMoney(target, amount, String.Empty, MoneyTransactionType.Gift, TransactionFlags.DestGroup);
2458 }
2459  
2460 /// <summary>
2461 /// Give L$ to a group
2462 /// </summary>
2463 /// <param name="target">group <seealso cref="UUID"/> to give money to</param>
2464 /// <param name="amount">amount of L$ to give</param>
2465 /// <param name="description">description of transaction</param>
2466 public void GiveGroupMoney(UUID target, int amount, string description)
2467 {
2468 GiveMoney(target, amount, description, MoneyTransactionType.Gift, TransactionFlags.DestGroup);
2469 }
2470  
2471 /// <summary>
2472 /// Pay texture/animation upload fee
2473 /// </summary>
2474 public void PayUploadFee()
2475 {
2476 GiveMoney(UUID.Zero, Client.Settings.UPLOAD_COST, String.Empty, MoneyTransactionType.UploadCharge,
2477 TransactionFlags.None);
2478 }
2479  
2480 /// <summary>
2481 /// Pay texture/animation upload fee
2482 /// </summary>
2483 /// <param name="description">description of the transaction</param>
2484 public void PayUploadFee(string description)
2485 {
2486 GiveMoney(UUID.Zero, Client.Settings.UPLOAD_COST, description, MoneyTransactionType.UploadCharge,
2487 TransactionFlags.None);
2488 }
2489  
2490 /// <summary>
2491 /// Give Money to destination Object or Avatar
2492 /// </summary>
2493 /// <param name="target">UUID of the Target Object/Avatar</param>
2494 /// <param name="amount">Amount in L$</param>
2495 /// <param name="description">Reason (Optional normally)</param>
2496 /// <param name="type">The type of transaction</param>
2497 /// <param name="flags">Transaction flags, mostly for identifying group
2498 /// transactions</param>
2499 public void GiveMoney(UUID target, int amount, string description, MoneyTransactionType type, TransactionFlags flags)
2500 {
2501 MoneyTransferRequestPacket money = new MoneyTransferRequestPacket();
2502 money.AgentData.AgentID = this.id;
2503 money.AgentData.SessionID = Client.Self.SessionID;
2504 money.MoneyData.Description = Utils.StringToBytes(description);
2505 money.MoneyData.DestID = target;
2506 money.MoneyData.SourceID = this.id;
2507 money.MoneyData.TransactionType = (int)type;
2508 money.MoneyData.AggregatePermInventory = 0; // This is weird, apparently always set to zero though
2509 money.MoneyData.AggregatePermNextOwner = 0; // This is weird, apparently always set to zero though
2510 money.MoneyData.Flags = (byte)flags;
2511 money.MoneyData.Amount = amount;
2512  
2513 Client.Network.SendPacket(money);
2514 }
2515  
2516 #endregion Money
2517  
2518 #region Gestures
2519 /// <summary>
2520 /// Plays a gesture
2521 /// </summary>
2522 /// <param name="gestureID">Asset <seealso cref="UUID"/> of the gesture</param>
2523 public void PlayGesture(UUID gestureID)
2524 {
2525 Thread t = new Thread(new ThreadStart(delegate()
2526 {
2527 // First fetch the guesture
2528 AssetGesture gesture = null;
2529  
2530 if (gestureCache.ContainsKey(gestureID))
2531 {
2532 gesture = gestureCache[gestureID];
2533 }
2534 else
2535 {
2536 AutoResetEvent gotAsset = new AutoResetEvent(false);
2537  
2538 Client.Assets.RequestAsset(gestureID, AssetType.Gesture, true,
2539 delegate(AssetDownload transfer, Asset asset)
2540 {
2541 if (transfer.Success)
2542 {
2543 gesture = (AssetGesture)asset;
2544 }
2545  
2546 gotAsset.Set();
2547 }
2548 );
2549  
2550 gotAsset.WaitOne(30 * 1000, false);
2551  
2552 if (gesture != null && gesture.Decode())
2553 {
2554 lock (gestureCache)
2555 {
2556 if (!gestureCache.ContainsKey(gestureID))
2557 {
2558 gestureCache[gestureID] = gesture;
2559 }
2560 }
2561 }
2562 }
2563  
2564 // We got it, now we play it
2565 if (gesture != null)
2566 {
2567 for (int i = 0; i < gesture.Sequence.Count; i++)
2568 {
2569 GestureStep step = gesture.Sequence[i];
2570  
2571 switch (step.GestureStepType)
2572 {
2573 case GestureStepType.Chat:
2574 Chat(((GestureStepChat)step).Text, 0, ChatType.Normal);
2575 break;
2576  
2577 case GestureStepType.Animation:
2578 GestureStepAnimation anim = (GestureStepAnimation)step;
2579  
2580 if (anim.AnimationStart)
2581 {
2582 if (SignaledAnimations.ContainsKey(anim.ID))
2583 {
2584 AnimationStop(anim.ID, true);
2585 }
2586 AnimationStart(anim.ID, true);
2587 }
2588 else
2589 {
2590 AnimationStop(anim.ID, true);
2591 }
2592 break;
2593  
2594 case GestureStepType.Sound:
2595 Client.Sound.PlaySound(((GestureStepSound)step).ID);
2596 break;
2597  
2598 case GestureStepType.Wait:
2599 GestureStepWait wait = (GestureStepWait)step;
2600 if (wait.WaitForTime)
2601 {
2602 Thread.Sleep((int)(1000f * wait.WaitTime));
2603 }
2604 if (wait.WaitForAnimation)
2605 {
2606 // TODO: implement waiting for all animations to end that were triggered
2607 // during playing of this guesture sequence
2608 }
2609 break;
2610 }
2611 }
2612 }
2613 }));
2614  
2615 t.IsBackground = true;
2616 t.Name = "Gesture thread: " + gestureID;
2617 t.Start();
2618 }
2619  
2620 /// <summary>
2621 /// Mark gesture active
2622 /// </summary>
2623 /// <param name="invID">Inventory <seealso cref="UUID"/> of the gesture</param>
2624 /// <param name="assetID">Asset <seealso cref="UUID"/> of the gesture</param>
2625 public void ActivateGesture(UUID invID, UUID assetID)
2626 {
2627 ActivateGesturesPacket p = new ActivateGesturesPacket();
2628  
2629 p.AgentData.AgentID = AgentID;
2630 p.AgentData.SessionID = SessionID;
2631 p.AgentData.Flags = 0x00;
2632  
2633 ActivateGesturesPacket.DataBlock b = new ActivateGesturesPacket.DataBlock();
2634 b.ItemID = invID;
2635 b.AssetID = assetID;
2636 b.GestureFlags = 0x00;
2637  
2638 p.Data = new ActivateGesturesPacket.DataBlock[1];
2639 p.Data[0] = b;
2640  
2641 Client.Network.SendPacket(p);
2642  
2643 }
2644  
2645 /// <summary>
2646 /// Mark gesture inactive
2647 /// </summary>
2648 /// <param name="invID">Inventory <seealso cref="UUID"/> of the gesture</param>
2649 public void DeactivateGesture(UUID invID)
2650 {
2651 DeactivateGesturesPacket p = new DeactivateGesturesPacket();
2652  
2653 p.AgentData.AgentID = AgentID;
2654 p.AgentData.SessionID = SessionID;
2655 p.AgentData.Flags = 0x00;
2656  
2657 DeactivateGesturesPacket.DataBlock b = new DeactivateGesturesPacket.DataBlock();
2658 b.ItemID = invID;
2659 b.GestureFlags = 0x00;
2660  
2661 p.Data = new DeactivateGesturesPacket.DataBlock[1];
2662 p.Data[0] = b;
2663  
2664 Client.Network.SendPacket(p);
2665 }
2666 #endregion
2667  
2668 #region Animations
2669  
2670 /// <summary>
2671 /// Send an AgentAnimation packet that toggles a single animation on
2672 /// </summary>
2673 /// <param name="animation">The <seealso cref="UUID"/> of the animation to start playing</param>
2674 /// <param name="reliable">Whether to ensure delivery of this packet or not</param>
2675 public void AnimationStart(UUID animation, bool reliable)
2676 {
2677 Dictionary<UUID, bool> animations = new Dictionary<UUID, bool>();
2678 animations[animation] = true;
2679  
2680 Animate(animations, reliable);
2681 }
2682  
2683 /// <summary>
2684 /// Send an AgentAnimation packet that toggles a single animation off
2685 /// </summary>
2686 /// <param name="animation">The <seealso cref="UUID"/> of a
2687 /// currently playing animation to stop playing</param>
2688 /// <param name="reliable">Whether to ensure delivery of this packet or not</param>
2689 public void AnimationStop(UUID animation, bool reliable)
2690 {
2691 Dictionary<UUID, bool> animations = new Dictionary<UUID, bool>();
2692 animations[animation] = false;
2693  
2694 Animate(animations, reliable);
2695 }
2696  
2697 /// <summary>
2698 /// Send an AgentAnimation packet that will toggle animations on or off
2699 /// </summary>
2700 /// <param name="animations">A list of animation <seealso cref="UUID"/>s, and whether to
2701 /// turn that animation on or off</param>
2702 /// <param name="reliable">Whether to ensure delivery of this packet or not</param>
2703 public void Animate(Dictionary<UUID, bool> animations, bool reliable)
2704 {
2705 AgentAnimationPacket animate = new AgentAnimationPacket();
2706 animate.Header.Reliable = reliable;
2707  
2708 animate.AgentData.AgentID = Client.Self.AgentID;
2709 animate.AgentData.SessionID = Client.Self.SessionID;
2710 animate.AnimationList = new AgentAnimationPacket.AnimationListBlock[animations.Count];
2711 int i = 0;
2712  
2713 foreach (KeyValuePair<UUID, bool> animation in animations)
2714 {
2715 animate.AnimationList[i] = new AgentAnimationPacket.AnimationListBlock();
2716 animate.AnimationList[i].AnimID = animation.Key;
2717 animate.AnimationList[i].StartAnim = animation.Value;
2718  
2719 i++;
2720 }
2721  
2722 // TODO: Implement support for this
2723 animate.PhysicalAvatarEventList = new AgentAnimationPacket.PhysicalAvatarEventListBlock[0];
2724  
2725 Client.Network.SendPacket(animate);
2726 }
2727  
2728 #endregion Animations
2729  
2730 #region Teleporting
2731  
2732 /// <summary>
2733 /// Teleports agent to their stored home location
2734 /// </summary>
2735 /// <returns>true on successful teleport to home location</returns>
2736 public bool GoHome()
2737 {
2738 return Teleport(UUID.Zero);
2739 }
2740  
2741 /// <summary>
2742 /// Teleport agent to a landmark
2743 /// </summary>
2744 /// <param name="landmark"><seealso cref="UUID"/> of the landmark to teleport agent to</param>
2745 /// <returns>true on success, false on failure</returns>
2746 public bool Teleport(UUID landmark)
2747 {
2748 teleportStat = TeleportStatus.None;
2749 teleportEvent.Reset();
2750 TeleportLandmarkRequestPacket p = new TeleportLandmarkRequestPacket();
2751 p.Info = new TeleportLandmarkRequestPacket.InfoBlock();
2752 p.Info.AgentID = Client.Self.AgentID;
2753 p.Info.SessionID = Client.Self.SessionID;
2754 p.Info.LandmarkID = landmark;
2755 Client.Network.SendPacket(p);
2756  
2757 teleportEvent.WaitOne(Client.Settings.TELEPORT_TIMEOUT, false);
2758  
2759 if (teleportStat == TeleportStatus.None ||
2760 teleportStat == TeleportStatus.Start ||
2761 teleportStat == TeleportStatus.Progress)
2762 {
2763 teleportMessage = "Teleport timed out.";
2764 teleportStat = TeleportStatus.Failed;
2765 }
2766  
2767 return (teleportStat == TeleportStatus.Finished);
2768 }
2769  
2770 /// <summary>
2771 /// Attempt to look up a simulator name and teleport to the discovered
2772 /// destination
2773 /// </summary>
2774 /// <param name="simName">Region name to look up</param>
2775 /// <param name="position">Position to teleport to</param>
2776 /// <returns>True if the lookup and teleport were successful, otherwise
2777 /// false</returns>
2778 public bool Teleport(string simName, Vector3 position)
2779 {
2780 return Teleport(simName, position, new Vector3(0, 1.0f, 0));
2781 }
2782  
2783 /// <summary>
2784 /// Attempt to look up a simulator name and teleport to the discovered
2785 /// destination
2786 /// </summary>
2787 /// <param name="simName">Region name to look up</param>
2788 /// <param name="position">Position to teleport to</param>
2789 /// <param name="lookAt">Target to look at</param>
2790 /// <returns>True if the lookup and teleport were successful, otherwise
2791 /// false</returns>
2792 public bool Teleport(string simName, Vector3 position, Vector3 lookAt)
2793 {
2794 if (Client.Network.CurrentSim == null)
2795 return false;
2796  
2797 teleportStat = TeleportStatus.None;
2798  
2799 if (simName != Client.Network.CurrentSim.Name)
2800 {
2801 // Teleporting to a foreign sim
2802 GridRegion region;
2803  
2804 if (Client.Grid.GetGridRegion(simName, GridLayerType.Objects, out region))
2805 {
2806 return Teleport(region.RegionHandle, position, lookAt);
2807 }
2808 else
2809 {
2810 teleportMessage = "Unable to resolve name: " + simName;
2811 teleportStat = TeleportStatus.Failed;
2812 return false;
2813 }
2814 }
2815 else
2816 {
2817 // Teleporting to the sim we're already in
2818 return Teleport(Client.Network.CurrentSim.Handle, position, lookAt);
2819 }
2820 }
2821  
2822 /// <summary>
2823 /// Teleport agent to another region
2824 /// </summary>
2825 /// <param name="regionHandle">handle of region to teleport agent to</param>
2826 /// <param name="position"><seealso cref="Vector3"/> position in destination sim to teleport to</param>
2827 /// <returns>true on success, false on failure</returns>
2828 /// <remarks>This call is blocking</remarks>
2829 public bool Teleport(ulong regionHandle, Vector3 position)
2830 {
2831 return Teleport(regionHandle, position, new Vector3(0.0f, 1.0f, 0.0f));
2832 }
2833  
2834 /// <summary>
2835 /// Teleport agent to another region
2836 /// </summary>
2837 /// <param name="regionHandle">handle of region to teleport agent to</param>
2838 /// <param name="position"><seealso cref="Vector3"/> position in destination sim to teleport to</param>
2839 /// <param name="lookAt"><seealso cref="Vector3"/> direction in destination sim agent will look at</param>
2840 /// <returns>true on success, false on failure</returns>
2841 /// <remarks>This call is blocking</remarks>
2842 public bool Teleport(ulong regionHandle, Vector3 position, Vector3 lookAt)
2843 {
2844 if (Client.Network.CurrentSim == null ||
2845 Client.Network.CurrentSim.Caps == null ||
2846 !Client.Network.CurrentSim.Caps.IsEventQueueRunning)
2847 {
2848 // Wait a bit to see if the event queue comes online
2849 AutoResetEvent queueEvent = new AutoResetEvent(false);
2850 EventHandler<EventQueueRunningEventArgs> queueCallback =
2851 delegate(object sender, EventQueueRunningEventArgs e)
2852 {
2853 if (e.Simulator == Client.Network.CurrentSim)
2854 queueEvent.Set();
2855 };
2856  
2857 Client.Network.EventQueueRunning += queueCallback;
2858 queueEvent.WaitOne(10 * 1000, false);
2859 Client.Network.EventQueueRunning -= queueCallback;
2860 }
2861  
2862 teleportStat = TeleportStatus.None;
2863 teleportEvent.Reset();
2864  
2865 RequestTeleport(regionHandle, position, lookAt);
2866  
2867 teleportEvent.WaitOne(Client.Settings.TELEPORT_TIMEOUT, false);
2868  
2869 if (teleportStat == TeleportStatus.None ||
2870 teleportStat == TeleportStatus.Start ||
2871 teleportStat == TeleportStatus.Progress)
2872 {
2873 teleportMessage = "Teleport timed out.";
2874 teleportStat = TeleportStatus.Failed;
2875 }
2876  
2877 return (teleportStat == TeleportStatus.Finished);
2878 }
2879  
2880 /// <summary>
2881 /// Request teleport to a another simulator
2882 /// </summary>
2883 /// <param name="regionHandle">handle of region to teleport agent to</param>
2884 /// <param name="position"><seealso cref="Vector3"/> position in destination sim to teleport to</param>
2885 public void RequestTeleport(ulong regionHandle, Vector3 position)
2886 {
2887 RequestTeleport(regionHandle, position, new Vector3(0.0f, 1.0f, 0.0f));
2888 }
2889  
2890 /// <summary>
2891 /// Request teleport to a another simulator
2892 /// </summary>
2893 /// <param name="regionHandle">handle of region to teleport agent to</param>
2894 /// <param name="position"><seealso cref="Vector3"/> position in destination sim to teleport to</param>
2895 /// <param name="lookAt"><seealso cref="Vector3"/> direction in destination sim agent will look at</param>
2896 public void RequestTeleport(ulong regionHandle, Vector3 position, Vector3 lookAt)
2897 {
2898 if (Client.Network.CurrentSim != null &&
2899 Client.Network.CurrentSim.Caps != null &&
2900 Client.Network.CurrentSim.Caps.IsEventQueueRunning)
2901 {
2902 TeleportLocationRequestPacket teleport = new TeleportLocationRequestPacket();
2903 teleport.AgentData.AgentID = Client.Self.AgentID;
2904 teleport.AgentData.SessionID = Client.Self.SessionID;
2905 teleport.Info.LookAt = lookAt;
2906 teleport.Info.Position = position;
2907 teleport.Info.RegionHandle = regionHandle;
2908  
2909 Logger.Log("Requesting teleport to region handle " + regionHandle.ToString(), Helpers.LogLevel.Info, Client);
2910  
2911 Client.Network.SendPacket(teleport);
2912 }
2913 else
2914 {
2915 teleportMessage = "CAPS event queue is not running";
2916 teleportEvent.Set();
2917 teleportStat = TeleportStatus.Failed;
2918 }
2919 }
2920  
2921 /// <summary>
2922 /// Teleport agent to a landmark
2923 /// </summary>
2924 /// <param name="landmark"><seealso cref="UUID"/> of the landmark to teleport agent to</param>
2925 public void RequestTeleport(UUID landmark)
2926 {
2927 TeleportLandmarkRequestPacket p = new TeleportLandmarkRequestPacket();
2928 p.Info = new TeleportLandmarkRequestPacket.InfoBlock();
2929 p.Info.AgentID = Client.Self.AgentID;
2930 p.Info.SessionID = Client.Self.SessionID;
2931 p.Info.LandmarkID = landmark;
2932 Client.Network.SendPacket(p);
2933 }
2934  
2935 /// <summary>
2936 /// Send a teleport lure to another avatar with default "Join me in ..." invitation message
2937 /// </summary>
2938 /// <param name="targetID">target avatars <seealso cref="UUID"/> to lure</param>
2939 public void SendTeleportLure(UUID targetID)
2940 {
2941 SendTeleportLure(targetID, "Join me in " + Client.Network.CurrentSim.Name + "!");
2942 }
2943  
2944 /// <summary>
2945 /// Send a teleport lure to another avatar with custom invitation message
2946 /// </summary>
2947 /// <param name="targetID">target avatars <seealso cref="UUID"/> to lure</param>
2948 /// <param name="message">custom message to send with invitation</param>
2949 public void SendTeleportLure(UUID targetID, string message)
2950 {
2951 StartLurePacket p = new StartLurePacket();
2952 p.AgentData.AgentID = Client.Self.id;
2953 p.AgentData.SessionID = Client.Self.SessionID;
2954 p.Info.LureType = 0;
2955 p.Info.Message = Utils.StringToBytes(message);
2956 p.TargetData = new StartLurePacket.TargetDataBlock[] { new StartLurePacket.TargetDataBlock() };
2957 p.TargetData[0].TargetID = targetID;
2958 Client.Network.SendPacket(p);
2959 }
2960  
2961 /// <summary>
2962 /// Respond to a teleport lure by either accepting it and initiating
2963 /// the teleport, or denying it
2964 /// </summary>
2965 /// <param name="requesterID"><seealso cref="UUID"/> of the avatar sending the lure</param>
2966 /// <param name="sessionID">IM session <seealso cref="UUID"/> of the incoming lure request</param>
2967 /// <param name="accept">true to accept the lure, false to decline it</param>
2968 public void TeleportLureRespond(UUID requesterID, UUID sessionID, bool accept)
2969 {
2970 if (accept)
2971 {
2972 TeleportLureRequestPacket lure = new TeleportLureRequestPacket();
2973  
2974 lure.Info.AgentID = Client.Self.AgentID;
2975 lure.Info.SessionID = Client.Self.SessionID;
2976 lure.Info.LureID = sessionID;
2977 lure.Info.TeleportFlags = (uint)TeleportFlags.ViaLure;
2978  
2979 Client.Network.SendPacket(lure);
2980 }
2981 else
2982 {
2983 InstantMessage(Name, requesterID, String.Empty, sessionID,
2984 accept ? InstantMessageDialog.AcceptTeleport : InstantMessageDialog.DenyTeleport,
2985 InstantMessageOnline.Offline, this.SimPosition, UUID.Zero, Utils.EmptyBytes);
2986 }
2987 }
2988  
2989 #endregion Teleporting
2990  
2991 #region Misc
2992  
2993 /// <summary>
2994 /// Update agent profile
2995 /// </summary>
2996 /// <param name="profile"><seealso cref="OpenMetaverse.Avatar.AvatarProperties"/> struct containing updated
2997 /// profile information</param>
2998 public void UpdateProfile(Avatar.AvatarProperties profile)
2999 {
3000 AvatarPropertiesUpdatePacket apup = new AvatarPropertiesUpdatePacket();
3001 apup.AgentData.AgentID = id;
3002 apup.AgentData.SessionID = sessionID;
3003 apup.PropertiesData.AboutText = Utils.StringToBytes(profile.AboutText);
3004 apup.PropertiesData.AllowPublish = profile.AllowPublish;
3005 apup.PropertiesData.FLAboutText = Utils.StringToBytes(profile.FirstLifeText);
3006 apup.PropertiesData.FLImageID = profile.FirstLifeImage;
3007 apup.PropertiesData.ImageID = profile.ProfileImage;
3008 apup.PropertiesData.MaturePublish = profile.MaturePublish;
3009 apup.PropertiesData.ProfileURL = Utils.StringToBytes(profile.ProfileURL);
3010  
3011 Client.Network.SendPacket(apup);
3012 }
3013  
3014 /// <summary>
3015 /// Update agents profile interests
3016 /// </summary>
3017 /// <param name="interests">selection of interests from <seealso cref="T:OpenMetaverse.Avatar.Interests"/> struct</param>
3018 public void UpdateInterests(Avatar.Interests interests)
3019 {
3020 AvatarInterestsUpdatePacket aiup = new AvatarInterestsUpdatePacket();
3021 aiup.AgentData.AgentID = id;
3022 aiup.AgentData.SessionID = sessionID;
3023 aiup.PropertiesData.LanguagesText = Utils.StringToBytes(interests.LanguagesText);
3024 aiup.PropertiesData.SkillsMask = interests.SkillsMask;
3025 aiup.PropertiesData.SkillsText = Utils.StringToBytes(interests.SkillsText);
3026 aiup.PropertiesData.WantToMask = interests.WantToMask;
3027 aiup.PropertiesData.WantToText = Utils.StringToBytes(interests.WantToText);
3028  
3029 Client.Network.SendPacket(aiup);
3030 }
3031  
3032 /// <summary>
3033 /// Set the height and the width of the client window. This is used
3034 /// by the server to build a virtual camera frustum for our avatar
3035 /// </summary>
3036 /// <param name="height">New height of the viewer window</param>
3037 /// <param name="width">New width of the viewer window</param>
3038 public void SetHeightWidth(ushort height, ushort width)
3039 {
3040 AgentHeightWidthPacket heightwidth = new AgentHeightWidthPacket();
3041 heightwidth.AgentData.AgentID = Client.Self.AgentID;
3042 heightwidth.AgentData.SessionID = Client.Self.SessionID;
3043 heightwidth.AgentData.CircuitCode = Client.Network.CircuitCode;
3044 heightwidth.HeightWidthBlock.Height = height;
3045 heightwidth.HeightWidthBlock.Width = width;
3046 heightwidth.HeightWidthBlock.GenCounter = heightWidthGenCounter++;
3047  
3048 Client.Network.SendPacket(heightwidth);
3049 }
3050  
3051 /// <summary>
3052 /// Request the list of muted objects and avatars for this agent
3053 /// </summary>
3054 public void RequestMuteList()
3055 {
3056 MuteListRequestPacket mute = new MuteListRequestPacket();
3057 mute.AgentData.AgentID = Client.Self.AgentID;
3058 mute.AgentData.SessionID = Client.Self.SessionID;
3059 mute.MuteData.MuteCRC = 0;
3060  
3061 Client.Network.SendPacket(mute);
3062 }
3063  
3064 /// <summary>
3065 /// Mute an object, resident, etc.
3066 /// </summary>
3067 /// <param name="type">Mute type</param>
3068 /// <param name="id">Mute UUID</param>
3069 /// <param name="name">Mute name</param>
3070 public void UpdateMuteListEntry(MuteType type, UUID id, string name)
3071 {
3072 UpdateMuteListEntry(type, id, name, MuteFlags.Default);
3073 }
3074  
3075 /// <summary>
3076 /// Mute an object, resident, etc.
3077 /// </summary>
3078 /// <param name="type">Mute type</param>
3079 /// <param name="id">Mute UUID</param>
3080 /// <param name="name">Mute name</param>
3081 /// <param name="flags">Mute flags</param>
3082 public void UpdateMuteListEntry(MuteType type, UUID id, string name, MuteFlags flags)
3083 {
3084 UpdateMuteListEntryPacket p = new UpdateMuteListEntryPacket();
3085 p.AgentData.AgentID = Client.Self.AgentID;
3086 p.AgentData.SessionID = Client.Self.SessionID;
3087  
3088 p.MuteData.MuteType = (int)type;
3089 p.MuteData.MuteID = id;
3090 p.MuteData.MuteName = Utils.StringToBytes(name);
3091 p.MuteData.MuteFlags = (uint)flags;
3092  
3093 Client.Network.SendPacket(p);
3094  
3095 MuteEntry me = new MuteEntry();
3096 me.Type = type;
3097 me.ID = id;
3098 me.Name = name;
3099 me.Flags = flags;
3100 lock (MuteList.Dictionary)
3101 {
3102 MuteList[string.Format("{0}|{1}", me.ID, me.Name)] = me;
3103 }
3104 OnMuteListUpdated(EventArgs.Empty);
3105  
3106 }
3107  
3108 /// <summary>
3109 /// Unmute an object, resident, etc.
3110 /// </summary>
3111 /// <param name="id">Mute UUID</param>
3112 /// <param name="name">Mute name</param>
3113 public void RemoveMuteListEntry(UUID id, string name)
3114 {
3115 RemoveMuteListEntryPacket p = new RemoveMuteListEntryPacket();
3116 p.AgentData.AgentID = Client.Self.AgentID;
3117 p.AgentData.SessionID = Client.Self.SessionID;
3118  
3119 p.MuteData.MuteID = id;
3120 p.MuteData.MuteName = Utils.StringToBytes(name);
3121  
3122 Client.Network.SendPacket(p);
3123  
3124 string listKey = string.Format("{0}|{1}", id, name);
3125 if (MuteList.ContainsKey(listKey))
3126 {
3127 lock (MuteList.Dictionary)
3128 {
3129 MuteList.Remove(listKey);
3130 }
3131 OnMuteListUpdated(EventArgs.Empty);
3132 }
3133 }
3134  
3135 /// <summary>
3136 /// Sets home location to agents current position
3137 /// </summary>
3138 /// <remarks>will fire an AlertMessage (<seealso cref="E:OpenMetaverse.AgentManager.OnAlertMessage"/>) with
3139 /// success or failure message</remarks>
3140 public void SetHome()
3141 {
3142 SetStartLocationRequestPacket s = new SetStartLocationRequestPacket();
3143 s.AgentData = new SetStartLocationRequestPacket.AgentDataBlock();
3144 s.AgentData.AgentID = Client.Self.AgentID;
3145 s.AgentData.SessionID = Client.Self.SessionID;
3146 s.StartLocationData = new SetStartLocationRequestPacket.StartLocationDataBlock();
3147 s.StartLocationData.LocationPos = Client.Self.SimPosition;
3148 s.StartLocationData.LocationID = 1;
3149 s.StartLocationData.SimName = Utils.StringToBytes(String.Empty);
3150 s.StartLocationData.LocationLookAt = Movement.Camera.AtAxis;
3151 Client.Network.SendPacket(s);
3152 }
3153  
3154 /// <summary>
3155 /// Move an agent in to a simulator. This packet is the last packet
3156 /// needed to complete the transition in to a new simulator
3157 /// </summary>
3158 /// <param name="simulator"><seealso cref="T:OpenMetaverse.Simulator"/> Object</param>
3159 public void CompleteAgentMovement(Simulator simulator)
3160 {
3161 CompleteAgentMovementPacket move = new CompleteAgentMovementPacket();
3162  
3163 move.AgentData.AgentID = Client.Self.AgentID;
3164 move.AgentData.SessionID = Client.Self.SessionID;
3165 move.AgentData.CircuitCode = Client.Network.CircuitCode;
3166  
3167 Client.Network.SendPacket(move, simulator);
3168 }
3169  
3170 /// <summary>
3171 /// Reply to script permissions request
3172 /// </summary>
3173 /// <param name="simulator"><seealso cref="T:OpenMetaverse.Simulator"/> Object</param>
3174 /// <param name="itemID"><seealso cref="UUID"/> of the itemID requesting permissions</param>
3175 /// <param name="taskID"><seealso cref="UUID"/> of the taskID requesting permissions</param>
3176 /// <param name="permissions"><seealso cref="OpenMetaverse.ScriptPermission"/> list of permissions to allow</param>
3177 public void ScriptQuestionReply(Simulator simulator, UUID itemID, UUID taskID, ScriptPermission permissions)
3178 {
3179 ScriptAnswerYesPacket yes = new ScriptAnswerYesPacket();
3180 yes.AgentData.AgentID = Client.Self.AgentID;
3181 yes.AgentData.SessionID = Client.Self.SessionID;
3182 yes.Data.ItemID = itemID;
3183 yes.Data.TaskID = taskID;
3184 yes.Data.Questions = (int)permissions;
3185  
3186 Client.Network.SendPacket(yes, simulator);
3187 }
3188  
3189 /// <summary>
3190 /// Respond to a group invitation by either accepting or denying it
3191 /// </summary>
3192 /// <param name="groupID">UUID of the group (sent in the AgentID field of the invite message)</param>
3193 /// <param name="imSessionID">IM Session ID from the group invitation message</param>
3194 /// <param name="accept">Accept the group invitation or deny it</param>
3195 public void GroupInviteRespond(UUID groupID, UUID imSessionID, bool accept)
3196 {
3197 InstantMessage(Name, groupID, String.Empty, imSessionID,
3198 accept ? InstantMessageDialog.GroupInvitationAccept : InstantMessageDialog.GroupInvitationDecline,
3199 InstantMessageOnline.Offline, Vector3.Zero, UUID.Zero, Utils.EmptyBytes);
3200 }
3201  
3202 /// <summary>
3203 /// Requests script detection of objects and avatars
3204 /// </summary>
3205 /// <param name="name">name of the object/avatar to search for</param>
3206 /// <param name="searchID">UUID of the object or avatar to search for</param>
3207 /// <param name="type">Type of search from ScriptSensorTypeFlags</param>
3208 /// <param name="range">range of scan (96 max?)</param>
3209 /// <param name="arc">the arc in radians to search within</param>
3210 /// <param name="requestID">an user generated ID to correlate replies with</param>
3211 /// <param name="sim">Simulator to perform search in</param>
3212 public void RequestScriptSensor(string name, UUID searchID, ScriptSensorTypeFlags type, float range, float arc, UUID requestID, Simulator sim)
3213 {
3214 ScriptSensorRequestPacket request = new ScriptSensorRequestPacket();
3215 request.Requester.Arc = arc;
3216 request.Requester.Range = range;
3217 request.Requester.RegionHandle = sim.Handle;
3218 request.Requester.RequestID = requestID;
3219 request.Requester.SearchDir = Quaternion.Identity; // TODO: this needs to be tested
3220 request.Requester.SearchID = searchID;
3221 request.Requester.SearchName = Utils.StringToBytes(name);
3222 request.Requester.SearchPos = Vector3.Zero;
3223 request.Requester.SearchRegions = 0; // TODO: ?
3224 request.Requester.SourceID = Client.Self.AgentID;
3225 request.Requester.Type = (int)type;
3226  
3227 Client.Network.SendPacket(request, sim);
3228 }
3229  
3230 /// <summary>
3231 /// Create or update profile pick
3232 /// </summary>
3233 /// <param name="pickID">UUID of the pick to update, or random UUID to create a new pick</param>
3234 /// <param name="topPick">Is this a top pick? (typically false)</param>
3235 /// <param name="parcelID">UUID of the parcel (UUID.Zero for the current parcel)</param>
3236 /// <param name="name">Name of the pick</param>
3237 /// <param name="globalPosition">Global position of the pick landmark</param>
3238 /// <param name="textureID">UUID of the image displayed with the pick</param>
3239 /// <param name="description">Long description of the pick</param>
3240 public void PickInfoUpdate(UUID pickID, bool topPick, UUID parcelID, string name, Vector3d globalPosition, UUID textureID, string description)
3241 {
3242 PickInfoUpdatePacket pick = new PickInfoUpdatePacket();
3243 pick.AgentData.AgentID = Client.Self.AgentID;
3244 pick.AgentData.SessionID = Client.Self.SessionID;
3245 pick.Data.PickID = pickID;
3246 pick.Data.Desc = Utils.StringToBytes(description);
3247 pick.Data.CreatorID = Client.Self.AgentID;
3248 pick.Data.TopPick = topPick;
3249 pick.Data.ParcelID = parcelID;
3250 pick.Data.Name = Utils.StringToBytes(name);
3251 pick.Data.SnapshotID = textureID;
3252 pick.Data.PosGlobal = globalPosition;
3253 pick.Data.SortOrder = 0;
3254 pick.Data.Enabled = false;
3255  
3256 Client.Network.SendPacket(pick);
3257 }
3258  
3259 /// <summary>
3260 /// Delete profile pick
3261 /// </summary>
3262 /// <param name="pickID">UUID of the pick to delete</param>
3263 public void PickDelete(UUID pickID)
3264 {
3265 PickDeletePacket delete = new PickDeletePacket();
3266 delete.AgentData.AgentID = Client.Self.AgentID;
3267 delete.AgentData.SessionID = Client.Self.sessionID;
3268 delete.Data.PickID = pickID;
3269  
3270 Client.Network.SendPacket(delete);
3271 }
3272  
3273 /// <summary>
3274 /// Create or update profile Classified
3275 /// </summary>
3276 /// <param name="classifiedID">UUID of the classified to update, or random UUID to create a new classified</param>
3277 /// <param name="category">Defines what catagory the classified is in</param>
3278 /// <param name="snapshotID">UUID of the image displayed with the classified</param>
3279 /// <param name="price">Price that the classified will cost to place for a week</param>
3280 /// <param name="position">Global position of the classified landmark</param>
3281 /// <param name="name">Name of the classified</param>
3282 /// <param name="desc">Long description of the classified</param>
3283 /// <param name="autoRenew">if true, auto renew classified after expiration</param>
3284 public void UpdateClassifiedInfo(UUID classifiedID, DirectoryManager.ClassifiedCategories category,
3285 UUID snapshotID, int price, Vector3d position, string name, string desc, bool autoRenew)
3286 {
3287 ClassifiedInfoUpdatePacket classified = new ClassifiedInfoUpdatePacket();
3288 classified.AgentData.AgentID = Client.Self.AgentID;
3289 classified.AgentData.SessionID = Client.Self.SessionID;
3290  
3291 classified.Data.ClassifiedID = classifiedID;
3292 classified.Data.Category = (uint)category;
3293  
3294 classified.Data.ParcelID = UUID.Zero;
3295 // TODO: verify/fix ^
3296 classified.Data.ParentEstate = 0;
3297 // TODO: verify/fix ^
3298  
3299 classified.Data.SnapshotID = snapshotID;
3300 classified.Data.PosGlobal = position;
3301  
3302 classified.Data.ClassifiedFlags = autoRenew ? (byte)32 : (byte)0;
3303 // TODO: verify/fix ^
3304  
3305 classified.Data.PriceForListing = price;
3306 classified.Data.Name = Utils.StringToBytes(name);
3307 classified.Data.Desc = Utils.StringToBytes(desc);
3308 Client.Network.SendPacket(classified);
3309 }
3310  
3311 /// <summary>
3312 /// Create or update profile Classified
3313 /// </summary>
3314 /// <param name="classifiedID">UUID of the classified to update, or random UUID to create a new classified</param>
3315 /// <param name="category">Defines what catagory the classified is in</param>
3316 /// <param name="snapshotID">UUID of the image displayed with the classified</param>
3317 /// <param name="price">Price that the classified will cost to place for a week</param>
3318 /// <param name="name">Name of the classified</param>
3319 /// <param name="desc">Long description of the classified</param>
3320 /// <param name="autoRenew">if true, auto renew classified after expiration</param>
3321 public void UpdateClassifiedInfo(UUID classifiedID, DirectoryManager.ClassifiedCategories category, UUID snapshotID, int price, string name, string desc, bool autoRenew)
3322 {
3323 UpdateClassifiedInfo(classifiedID, category, snapshotID, price, Client.Self.GlobalPosition, name, desc, autoRenew);
3324 }
3325  
3326 /// <summary>
3327 /// Delete a classified ad
3328 /// </summary>
3329 /// <param name="classifiedID">The classified ads ID</param>
3330 public void DeleteClassfied(UUID classifiedID)
3331 {
3332 ClassifiedDeletePacket classified = new ClassifiedDeletePacket();
3333 classified.AgentData.AgentID = Client.Self.AgentID;
3334 classified.AgentData.SessionID = Client.Self.SessionID;
3335  
3336 classified.Data.ClassifiedID = classifiedID;
3337 Client.Network.SendPacket(classified);
3338 }
3339  
3340 /// <summary>
3341 /// Fetches resource usage by agents attachmetns
3342 /// </summary>
3343 /// <param name="callback">Called when the requested information is collected</param>
3344 public void GetAttachmentResources(AttachmentResourcesCallback callback)
3345 {
3346 try
3347 {
3348 Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("AttachmentResources");
3349 CapsClient request = new CapsClient(url);
3350  
3351 request.OnComplete += delegate(CapsClient client, OSD result, Exception error)
3352 {
3353 try
3354 {
3355 if (result == null || error != null)
3356 {
3357 callback(false, null);
3358 }
3359 AttachmentResourcesMessage info = AttachmentResourcesMessage.FromOSD(result);
3360 callback(true, info);
3361  
3362 }
3363 catch (Exception ex)
3364 {
3365 Logger.Log("Failed fetching AttachmentResources", Helpers.LogLevel.Error, Client, ex);
3366 callback(false, null);
3367 }
3368 };
3369  
3370 request.BeginGetResponse(Client.Settings.CAPS_TIMEOUT);
3371 }
3372 catch (Exception ex)
3373 {
3374 Logger.Log("Failed fetching AttachmentResources", Helpers.LogLevel.Error, Client, ex);
3375 callback(false, null);
3376 }
3377 }
3378  
3379 /// <summary>
3380 /// Initates request to set a new display name
3381 /// </summary>
3382 /// <param name="oldName">Previous display name</param>
3383 /// <param name="newName">Desired new display name</param>
3384 public void SetDisplayName(string oldName, string newName)
3385 {
3386 Uri uri;
3387  
3388 if (Client.Network.CurrentSim == null ||
3389 Client.Network.CurrentSim.Caps == null ||
3390 (uri = Client.Network.CurrentSim.Caps.CapabilityURI("SetDisplayName")) == null)
3391 {
3392 Logger.Log("Unable to invoke SetDisplyName capability at this time", Helpers.LogLevel.Warning, Client);
3393 return;
3394 }
3395  
3396 SetDisplayNameMessage msg = new SetDisplayNameMessage();
3397 msg.OldDisplayName = oldName;
3398 msg.NewDisplayName = newName;
3399  
3400 CapsClient cap = new CapsClient(uri);
3401 cap.BeginGetResponse(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
3402 }
3403  
3404 /// <summary>
3405 /// Tells the sim what UI language is used, and if it's ok to share that with scripts
3406 /// </summary>
3407 /// <param name="language">Two letter language code</param>
3408 /// <param name="isPublic">Share language info with scripts</param>
3409 public void UpdateAgentLanguage(string language, bool isPublic)
3410 {
3411 try
3412 {
3413 UpdateAgentLanguageMessage msg = new UpdateAgentLanguageMessage();
3414 msg.Language = language;
3415 msg.LanguagePublic = isPublic;
3416  
3417 Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("UpdateAgentLanguage");
3418 if (url != null)
3419 {
3420 CapsClient request = new CapsClient(url);
3421 request.BeginGetResponse(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
3422 }
3423 }
3424 catch (Exception ex)
3425 {
3426 Logger.Log("Failes to update agent language", Helpers.LogLevel.Error, Client, ex);
3427 }
3428 }
3429  
3430 public delegate void AgentAccessCallback(AgentAccessEventArgs e);
3431  
3432 /// <summary>
3433 /// Sets agents maturity access level
3434 /// </summary>
3435 /// <param name="access">PG, M or A</param>
3436 public void SetAgentAccess(string access)
3437 {
3438 SetAgentAccess(access, null);
3439 }
3440  
3441 /// <summary>
3442 /// Sets agents maturity access level
3443 /// </summary>
3444 /// <param name="access">PG, M or A</param>
3445 /// <param name="callback">Callback function</param>
3446 public void SetAgentAccess(string access, AgentAccessCallback callback)
3447 {
3448 if (Client == null || !Client.Network.Connected || Client.Network.CurrentSim.Caps == null) return;
3449  
3450 Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("UpdateAgentInformation");
3451  
3452 if (url == null) return;
3453  
3454 CapsClient request = new CapsClient(url);
3455  
3456 request.OnComplete += (client, result, error) =>
3457 {
3458 bool success = true;
3459  
3460 if (error == null && result is OSDMap)
3461 {
3462 var map = ((OSDMap)result)["access_prefs"];
3463 agentAccess = ((OSDMap)map)["max"];
3464 Logger.Log("Max maturity access set to " + agentAccess, Helpers.LogLevel.Info, Client );
3465 }
3466 else if (error == null)
3467 {
3468 Logger.Log("Max maturity unchanged at " + agentAccess, Helpers.LogLevel.Info, Client);
3469 }
3470 else
3471 {
3472 Logger.Log("Failed setting max maturity access.", Helpers.LogLevel.Warning, Client);
3473 success = false;
3474 }
3475  
3476 if (callback != null)
3477 {
3478 try { callback(new AgentAccessEventArgs(success, agentAccess)); }
3479 catch { }
3480 }
3481  
3482 };
3483 OSDMap req = new OSDMap();
3484 OSDMap prefs = new OSDMap();
3485 prefs["max"] = access;
3486 req["access_prefs"] = prefs;
3487  
3488 request.BeginGetResponse(req, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
3489 }
3490 #endregion Misc
3491  
3492 #region Packet Handlers
3493  
3494 /// <summary>
3495 /// Take an incoming ImprovedInstantMessage packet, auto-parse, and if
3496 /// OnInstantMessage is defined call that with the appropriate arguments
3497 /// </summary>
3498 /// <param name="sender">The sender</param>
3499 /// <param name="e">The EventArgs object containing the packet data</param>
3500 protected void InstantMessageHandler(object sender, PacketReceivedEventArgs e)
3501 {
3502 Packet packet = e.Packet;
3503 Simulator simulator = e.Simulator;
3504  
3505 if (packet.Type == PacketType.ImprovedInstantMessage)
3506 {
3507 ImprovedInstantMessagePacket im = (ImprovedInstantMessagePacket)packet;
3508  
3509 if (m_InstantMessage != null)
3510 {
3511 InstantMessage message;
3512 message.FromAgentID = im.AgentData.AgentID;
3513 message.FromAgentName = Utils.BytesToString(im.MessageBlock.FromAgentName);
3514 message.ToAgentID = im.MessageBlock.ToAgentID;
3515 message.ParentEstateID = im.MessageBlock.ParentEstateID;
3516 message.RegionID = im.MessageBlock.RegionID;
3517 message.Position = im.MessageBlock.Position;
3518 message.Dialog = (InstantMessageDialog)im.MessageBlock.Dialog;
3519 message.GroupIM = im.MessageBlock.FromGroup;
3520 message.IMSessionID = im.MessageBlock.ID;
3521 message.Timestamp = new DateTime(im.MessageBlock.Timestamp);
3522 message.Message = Utils.BytesToString(im.MessageBlock.Message);
3523 message.Offline = (InstantMessageOnline)im.MessageBlock.Offline;
3524 message.BinaryBucket = im.MessageBlock.BinaryBucket;
3525  
3526 OnInstantMessage(new InstantMessageEventArgs(message, simulator));
3527 }
3528 }
3529 }
3530  
3531 /// <summary>
3532 /// Take an incoming Chat packet, auto-parse, and if OnChat is defined call
3533 /// that with the appropriate arguments.
3534 /// </summary>
3535 /// <param name="sender">The sender</param>
3536 /// <param name="e">The EventArgs object containing the packet data</param>
3537 protected void ChatHandler(object sender, PacketReceivedEventArgs e)
3538 {
3539 if (m_Chat != null)
3540 {
3541 Packet packet = e.Packet;
3542  
3543 ChatFromSimulatorPacket chat = (ChatFromSimulatorPacket)packet;
3544  
3545 OnChat(new ChatEventArgs(e.Simulator, Utils.BytesToString(chat.ChatData.Message),
3546 (ChatAudibleLevel)chat.ChatData.Audible,
3547 (ChatType)chat.ChatData.ChatType,
3548 (ChatSourceType)chat.ChatData.SourceType,
3549 Utils.BytesToString(chat.ChatData.FromName),
3550 chat.ChatData.SourceID,
3551 chat.ChatData.OwnerID,
3552 chat.ChatData.Position));
3553 }
3554 }
3555  
3556 /// <summary>
3557 /// Used for parsing llDialogs
3558 /// </summary>
3559 /// <param name="sender">The sender</param>
3560 /// <param name="e">The EventArgs object containing the packet data</param>
3561 protected void ScriptDialogHandler(object sender, PacketReceivedEventArgs e)
3562 {
3563 if (m_ScriptDialog != null)
3564 {
3565 Packet packet = e.Packet;
3566  
3567 ScriptDialogPacket dialog = (ScriptDialogPacket)packet;
3568 List<string> buttons = new List<string>();
3569  
3570 foreach (ScriptDialogPacket.ButtonsBlock button in dialog.Buttons)
3571 {
3572 buttons.Add(Utils.BytesToString(button.ButtonLabel));
3573 }
3574  
3575 UUID ownerID = UUID.Zero;
3576  
3577 if (dialog.OwnerData != null && dialog.OwnerData.Length > 0)
3578 {
3579 ownerID = dialog.OwnerData[0].OwnerID;
3580 }
3581  
3582 OnScriptDialog(new ScriptDialogEventArgs(Utils.BytesToString(dialog.Data.Message),
3583 Utils.BytesToString(dialog.Data.ObjectName),
3584 dialog.Data.ImageID,
3585 dialog.Data.ObjectID,
3586 Utils.BytesToString(dialog.Data.FirstName),
3587 Utils.BytesToString(dialog.Data.LastName),
3588 dialog.Data.ChatChannel,
3589 buttons,
3590 ownerID));
3591 }
3592 }
3593  
3594 /// <summary>
3595 /// Used for parsing llRequestPermissions dialogs
3596 /// </summary>
3597 /// <param name="sender">The sender</param>
3598 /// <param name="e">The EventArgs object containing the packet data</param>
3599 protected void ScriptQuestionHandler(object sender, PacketReceivedEventArgs e)
3600 {
3601 if (m_ScriptQuestion != null)
3602 {
3603 Packet packet = e.Packet;
3604 Simulator simulator = e.Simulator;
3605  
3606 ScriptQuestionPacket question = (ScriptQuestionPacket)packet;
3607  
3608 OnScriptQuestion(new ScriptQuestionEventArgs(simulator,
3609 question.Data.TaskID,
3610 question.Data.ItemID,
3611 Utils.BytesToString(question.Data.ObjectName),
3612 Utils.BytesToString(question.Data.ObjectOwner),
3613 (ScriptPermission)question.Data.Questions));
3614 }
3615 }
3616  
3617 /// <summary>
3618 /// Handles Script Control changes when Script with permissions releases or takes a control
3619 /// </summary>
3620 /// <param name="sender">The sender</param>
3621 /// <param name="e">The EventArgs object containing the packet data</param>
3622 private void ScriptControlChangeHandler(object sender, PacketReceivedEventArgs e)
3623 {
3624 if (m_ScriptControl != null)
3625 {
3626 Packet packet = e.Packet;
3627  
3628 ScriptControlChangePacket change = (ScriptControlChangePacket)packet;
3629 for (int i = 0; i < change.Data.Length; i++)
3630 {
3631 OnScriptControlChange(new ScriptControlEventArgs((ScriptControlChange)change.Data[i].Controls,
3632 change.Data[i].PassToAgent,
3633 change.Data[i].TakeControls));
3634 }
3635 }
3636 }
3637  
3638 /// <summary>
3639 /// Used for parsing llLoadURL Dialogs
3640 /// </summary>
3641 /// <param name="sender">The sender</param>
3642 /// <param name="e">The EventArgs object containing the packet data</param>
3643 protected void LoadURLHandler(object sender, PacketReceivedEventArgs e)
3644 {
3645  
3646 if (m_LoadURL != null)
3647 {
3648 Packet packet = e.Packet;
3649  
3650 LoadURLPacket loadURL = (LoadURLPacket)packet;
3651  
3652 OnLoadURL(new LoadUrlEventArgs(
3653 Utils.BytesToString(loadURL.Data.ObjectName),
3654 loadURL.Data.ObjectID,
3655 loadURL.Data.OwnerID,
3656 loadURL.Data.OwnerIsGroup,
3657 Utils.BytesToString(loadURL.Data.Message),
3658 Utils.BytesToString(loadURL.Data.URL)
3659 ));
3660 }
3661 }
3662  
3663 /// <summary>
3664 /// Update client's Position, LookAt and region handle from incoming packet
3665 /// </summary>
3666 /// <param name="sender">The sender</param>
3667 /// <param name="e">The EventArgs object containing the packet data</param>
3668 /// <remarks>This occurs when after an avatar moves into a new sim</remarks>
3669 private void MovementCompleteHandler(object sender, PacketReceivedEventArgs e)
3670 {
3671 Packet packet = e.Packet;
3672 Simulator simulator = e.Simulator;
3673  
3674 AgentMovementCompletePacket movement = (AgentMovementCompletePacket)packet;
3675  
3676 relativePosition = movement.Data.Position;
3677 Movement.Camera.LookDirection(movement.Data.LookAt);
3678 simulator.Handle = movement.Data.RegionHandle;
3679 simulator.SimVersion = Utils.BytesToString(movement.SimData.ChannelVersion);
3680 simulator.AgentMovementComplete = true;
3681 }
3682  
3683 /// <summary>Process an incoming packet and raise the appropriate events</summary>
3684 /// <param name="sender">The sender</param>
3685 /// <param name="e">The EventArgs object containing the packet data</param>
3686 protected void HealthHandler(object sender, PacketReceivedEventArgs e)
3687 {
3688 Packet packet = e.Packet;
3689 health = ((HealthMessagePacket)packet).HealthData.Health;
3690 }
3691  
3692 /// <summary>Process an incoming packet and raise the appropriate events</summary>
3693 /// <param name="sender">The sender</param>
3694 /// <param name="e">The EventArgs object containing the packet data</param>
3695 protected void AgentDataUpdateHandler(object sender, PacketReceivedEventArgs e)
3696 {
3697 Packet packet = e.Packet;
3698 Simulator simulator = e.Simulator;
3699  
3700 AgentDataUpdatePacket p = (AgentDataUpdatePacket)packet;
3701  
3702 if (p.AgentData.AgentID == simulator.Client.Self.AgentID)
3703 {
3704 firstName = Utils.BytesToString(p.AgentData.FirstName);
3705 lastName = Utils.BytesToString(p.AgentData.LastName);
3706 activeGroup = p.AgentData.ActiveGroupID;
3707 activeGroupPowers = (GroupPowers)p.AgentData.GroupPowers;
3708  
3709 if (m_AgentData != null)
3710 {
3711 string groupTitle = Utils.BytesToString(p.AgentData.GroupTitle);
3712 string groupName = Utils.BytesToString(p.AgentData.GroupName);
3713  
3714 OnAgentData(new AgentDataReplyEventArgs(firstName, lastName, activeGroup, groupTitle, activeGroupPowers, groupName));
3715 }
3716 }
3717 else
3718 {
3719 Logger.Log("Got an AgentDataUpdate packet for avatar " + p.AgentData.AgentID.ToString() +
3720 " instead of " + Client.Self.AgentID.ToString() + ", this shouldn't happen", Helpers.LogLevel.Error, Client);
3721 }
3722 }
3723  
3724 /// <summary>Process an incoming packet and raise the appropriate events</summary>
3725 /// <param name="sender">The sender</param>
3726 /// <param name="e">The EventArgs object containing the packet data</param>
3727 protected void MoneyBalanceReplyHandler(object sender, PacketReceivedEventArgs e)
3728 {
3729 Packet packet = e.Packet;
3730  
3731 if (packet.Type == PacketType.MoneyBalanceReply)
3732 {
3733 MoneyBalanceReplyPacket reply = (MoneyBalanceReplyPacket)packet;
3734 this.balance = reply.MoneyData.MoneyBalance;
3735  
3736 if (m_MoneyBalance != null)
3737 {
3738 TransactionInfo transactionInfo = new TransactionInfo();
3739 transactionInfo.TransactionType = reply.TransactionInfo.TransactionType;
3740 transactionInfo.SourceID = reply.TransactionInfo.SourceID;
3741 transactionInfo.IsSourceGroup = reply.TransactionInfo.IsSourceGroup;
3742 transactionInfo.DestID = reply.TransactionInfo.DestID;
3743 transactionInfo.IsDestGroup = reply.TransactionInfo.IsDestGroup;
3744 transactionInfo.Amount = reply.TransactionInfo.Amount;
3745 transactionInfo.ItemDescription = Utils.BytesToString(reply.TransactionInfo.ItemDescription);
3746  
3747 OnMoneyBalanceReply(new MoneyBalanceReplyEventArgs(reply.MoneyData.TransactionID,
3748 reply.MoneyData.TransactionSuccess,
3749 reply.MoneyData.MoneyBalance,
3750 reply.MoneyData.SquareMetersCredit,
3751 reply.MoneyData.SquareMetersCommitted,
3752 Utils.BytesToString(reply.MoneyData.Description),
3753 transactionInfo));
3754 }
3755 }
3756  
3757 if (m_Balance != null)
3758 {
3759 OnBalance(new BalanceEventArgs(balance));
3760 }
3761 }
3762  
3763 /// <summary>
3764 /// EQ Message fired with the result of SetDisplayName request
3765 /// </summary>
3766 /// <param name="capsKey">The message key</param>
3767 /// <param name="message">the IMessage object containing the deserialized data sent from the simulator</param>
3768 /// <param name="simulator">The <see cref="Simulator"/> which originated the packet</param>
3769 protected void SetDisplayNameReplyEventHandler(string capsKey, IMessage message, Simulator simulator)
3770 {
3771 if (m_SetDisplayNameReply != null)
3772 {
3773 SetDisplayNameReplyMessage msg = (SetDisplayNameReplyMessage)message;
3774 OnSetDisplayNameReply(new SetDisplayNameReplyEventArgs(msg.Status, msg.Reason, msg.DisplayName));
3775 }
3776 }
3777  
3778 protected void AgentStateUpdateEventHandler(string capsKey, IMessage message, Simulator simulator)
3779 {
3780 if (message is AgentStateUpdateMessage)
3781 {
3782 AgentStateStatus = (AgentStateUpdateMessage)message;
3783 }
3784 }
3785  
3786 protected void EstablishAgentCommunicationEventHandler(string capsKey, IMessage message, Simulator simulator)
3787 {
3788 EstablishAgentCommunicationMessage msg = (EstablishAgentCommunicationMessage)message;
3789  
3790 if (Client.Settings.MULTIPLE_SIMS)
3791 {
3792  
3793 IPEndPoint endPoint = new IPEndPoint(msg.Address, msg.Port);
3794 Simulator sim = Client.Network.FindSimulator(endPoint);
3795  
3796 if (sim == null)
3797 {
3798 Logger.Log("Got EstablishAgentCommunication for unknown sim " + msg.Address + ":" + msg.Port,
3799 Helpers.LogLevel.Error, Client);
3800  
3801 // FIXME: Should we use this opportunity to connect to the simulator?
3802 }
3803 else
3804 {
3805 Logger.Log("Got EstablishAgentCommunication for " + sim.ToString(),
3806 Helpers.LogLevel.Info, Client);
3807  
3808 sim.SetSeedCaps(msg.SeedCapability.ToString());
3809 }
3810 }
3811 }
3812  
3813 /// <summary>
3814 /// Process TeleportFailed message sent via EventQueue, informs agent its last teleport has failed and why.
3815 /// </summary>
3816 /// <param name="messageKey">The Message Key</param>
3817 /// <param name="message">An IMessage object Deserialized from the recieved message event</param>
3818 /// <param name="simulator">The simulator originating the event message</param>
3819 public void TeleportFailedEventHandler(string messageKey, IMessage message, Simulator simulator)
3820 {
3821 TeleportFailedMessage msg = (TeleportFailedMessage)message;
3822  
3823 TeleportFailedPacket failedPacket = new TeleportFailedPacket();
3824 failedPacket.Info.AgentID = msg.AgentID;
3825 failedPacket.Info.Reason = Utils.StringToBytes(msg.Reason);
3826  
3827 TeleportHandler(this, new PacketReceivedEventArgs(failedPacket, simulator));
3828 }
3829  
3830 /// <summary>
3831 /// Process TeleportFinish from Event Queue and pass it onto our TeleportHandler
3832 /// </summary>
3833 /// <param name="capsKey">The message system key for this event</param>
3834 /// <param name="message">IMessage object containing decoded data from OSD</param>
3835 /// <param name="simulator">The simulator originating the event message</param>
3836 private void TeleportFinishEventHandler(string capsKey, IMessage message, Simulator simulator)
3837 {
3838 TeleportFinishMessage msg = (TeleportFinishMessage)message;
3839  
3840 TeleportFinishPacket p = new TeleportFinishPacket();
3841 p.Info.AgentID = msg.AgentID;
3842 p.Info.LocationID = (uint)msg.LocationID;
3843 p.Info.RegionHandle = msg.RegionHandle;
3844 p.Info.SeedCapability = Utils.StringToBytes(msg.SeedCapability.ToString()); // FIXME: Check This
3845 p.Info.SimAccess = (byte)msg.SimAccess;
3846 p.Info.SimIP = Utils.IPToUInt(msg.IP);
3847 p.Info.SimPort = (ushort)msg.Port;
3848 p.Info.TeleportFlags = (uint)msg.Flags;
3849  
3850 // pass the packet onto the teleport handler
3851 TeleportHandler(this, new PacketReceivedEventArgs(p, simulator));
3852 }
3853  
3854 /// <summary>Process an incoming packet and raise the appropriate events</summary>
3855 /// <param name="sender">The sender</param>
3856 /// <param name="e">The EventArgs object containing the packet data</param>
3857 protected void TeleportHandler(object sender, PacketReceivedEventArgs e)
3858 {
3859 Packet packet = e.Packet;
3860 Simulator simulator = e.Simulator;
3861  
3862 bool finished = false;
3863 TeleportFlags flags = TeleportFlags.Default;
3864  
3865 if (packet.Type == PacketType.TeleportStart)
3866 {
3867 TeleportStartPacket start = (TeleportStartPacket)packet;
3868  
3869 teleportMessage = "Teleport started";
3870 flags = (TeleportFlags)start.Info.TeleportFlags;
3871 teleportStat = TeleportStatus.Start;
3872  
3873 Logger.DebugLog("TeleportStart received, Flags: " + flags.ToString(), Client);
3874 }
3875 else if (packet.Type == PacketType.TeleportProgress)
3876 {
3877 TeleportProgressPacket progress = (TeleportProgressPacket)packet;
3878  
3879 teleportMessage = Utils.BytesToString(progress.Info.Message);
3880 flags = (TeleportFlags)progress.Info.TeleportFlags;
3881 teleportStat = TeleportStatus.Progress;
3882  
3883 Logger.DebugLog("TeleportProgress received, Message: " + teleportMessage + ", Flags: " + flags.ToString(), Client);
3884 }
3885 else if (packet.Type == PacketType.TeleportFailed)
3886 {
3887 TeleportFailedPacket failed = (TeleportFailedPacket)packet;
3888  
3889 teleportMessage = Utils.BytesToString(failed.Info.Reason);
3890 teleportStat = TeleportStatus.Failed;
3891 finished = true;
3892  
3893 Logger.DebugLog("TeleportFailed received, Reason: " + teleportMessage, Client);
3894 }
3895 else if (packet.Type == PacketType.TeleportFinish)
3896 {
3897 TeleportFinishPacket finish = (TeleportFinishPacket)packet;
3898  
3899 flags = (TeleportFlags)finish.Info.TeleportFlags;
3900 string seedcaps = Utils.BytesToString(finish.Info.SeedCapability);
3901 finished = true;
3902  
3903 Logger.DebugLog("TeleportFinish received, Flags: " + flags.ToString(), Client);
3904  
3905 // Connect to the new sim
3906 Client.Network.CurrentSim.AgentMovementComplete = false; // we're not there anymore
3907 Simulator newSimulator = Client.Network.Connect(new IPAddress(finish.Info.SimIP),
3908 finish.Info.SimPort, finish.Info.RegionHandle, true, seedcaps);
3909  
3910 if (newSimulator != null)
3911 {
3912 teleportMessage = "Teleport finished";
3913 teleportStat = TeleportStatus.Finished;
3914  
3915 Logger.Log("Moved to new sim " + newSimulator.ToString(), Helpers.LogLevel.Info, Client);
3916 }
3917 else
3918 {
3919 teleportMessage = "Failed to connect to the new sim after a teleport";
3920 teleportStat = TeleportStatus.Failed;
3921  
3922 // We're going to get disconnected now
3923 Logger.Log(teleportMessage, Helpers.LogLevel.Error, Client);
3924 }
3925 }
3926 else if (packet.Type == PacketType.TeleportCancel)
3927 {
3928 //TeleportCancelPacket cancel = (TeleportCancelPacket)packet;
3929  
3930 teleportMessage = "Cancelled";
3931 teleportStat = TeleportStatus.Cancelled;
3932 finished = true;
3933  
3934 Logger.DebugLog("TeleportCancel received from " + simulator.ToString(), Client);
3935 }
3936 else if (packet.Type == PacketType.TeleportLocal)
3937 {
3938 TeleportLocalPacket local = (TeleportLocalPacket)packet;
3939  
3940 teleportMessage = "Teleport finished";
3941 flags = (TeleportFlags)local.Info.TeleportFlags;
3942 teleportStat = TeleportStatus.Finished;
3943 relativePosition = local.Info.Position;
3944 Movement.Camera.LookDirection(local.Info.LookAt);
3945 // This field is apparently not used for anything
3946 //local.Info.LocationID;
3947 finished = true;
3948  
3949 Logger.DebugLog("TeleportLocal received, Flags: " + flags.ToString(), Client);
3950 }
3951  
3952 if (m_Teleport != null)
3953 {
3954 OnTeleport(new TeleportEventArgs(teleportMessage, teleportStat, flags));
3955 }
3956  
3957 if (finished) teleportEvent.Set();
3958 }
3959  
3960 /// <summary>Process an incoming packet and raise the appropriate events</summary>
3961 /// <param name="sender">The sender</param>
3962 /// <param name="e">The EventArgs object containing the packet data</param>
3963 protected void AvatarAnimationHandler(object sender, PacketReceivedEventArgs e)
3964 {
3965 Packet packet = e.Packet;
3966 AvatarAnimationPacket animation = (AvatarAnimationPacket)packet;
3967  
3968 if (animation.Sender.ID == Client.Self.AgentID)
3969 {
3970 lock (SignaledAnimations.Dictionary)
3971 {
3972 // Reset the signaled animation list
3973 SignaledAnimations.Dictionary.Clear();
3974  
3975 for (int i = 0; i < animation.AnimationList.Length; i++)
3976 {
3977 UUID animID = animation.AnimationList[i].AnimID;
3978 int sequenceID = animation.AnimationList[i].AnimSequenceID;
3979  
3980 // Add this animation to the list of currently signaled animations
3981 SignaledAnimations.Dictionary[animID] = sequenceID;
3982  
3983 if (i < animation.AnimationSourceList.Length)
3984 {
3985 // FIXME: The server tells us which objects triggered our animations,
3986 // we should store this info
3987  
3988 //animation.AnimationSourceList[i].ObjectID
3989 }
3990  
3991 if (i < animation.PhysicalAvatarEventList.Length)
3992 {
3993 // FIXME: What is this?
3994 }
3995  
3996 if (Client.Settings.SEND_AGENT_UPDATES)
3997 {
3998 // We have to manually tell the server to stop playing some animations
3999 if (animID == Animations.STANDUP ||
4000 animID == Animations.PRE_JUMP ||
4001 animID == Animations.LAND ||
4002 animID == Animations.MEDIUM_LAND)
4003 {
4004 Movement.FinishAnim = true;
4005 Movement.SendUpdate(true);
4006 Movement.FinishAnim = false;
4007 }
4008 }
4009 }
4010 }
4011 }
4012  
4013 if (m_AnimationsChanged != null)
4014 {
4015 WorkPool.QueueUserWorkItem(delegate(object o)
4016 { OnAnimationsChanged(new AnimationsChangedEventArgs(this.SignaledAnimations)); });
4017 }
4018  
4019 }
4020  
4021 /// <summary>Process an incoming packet and raise the appropriate events</summary>
4022 /// <param name="sender">The sender</param>
4023 /// <param name="e">The EventArgs object containing the packet data</param>
4024 protected void MeanCollisionAlertHandler(object sender, PacketReceivedEventArgs e)
4025 {
4026 if (m_MeanCollision != null)
4027 {
4028 Packet packet = e.Packet;
4029 MeanCollisionAlertPacket collision = (MeanCollisionAlertPacket)packet;
4030  
4031 for (int i = 0; i < collision.MeanCollision.Length; i++)
4032 {
4033 MeanCollisionAlertPacket.MeanCollisionBlock block = collision.MeanCollision[i];
4034  
4035 DateTime time = Utils.UnixTimeToDateTime(block.Time);
4036 MeanCollisionType type = (MeanCollisionType)block.Type;
4037  
4038 OnMeanCollision(new MeanCollisionEventArgs(type, block.Perp, block.Victim, block.Mag, time));
4039 }
4040 }
4041 }
4042  
4043 private void Network_OnLoginResponse(bool loginSuccess, bool redirect, string message, string reason,
4044 LoginResponseData reply)
4045 {
4046 id = reply.AgentID;
4047 sessionID = reply.SessionID;
4048 secureSessionID = reply.SecureSessionID;
4049 firstName = reply.FirstName;
4050 lastName = reply.LastName;
4051 startLocation = reply.StartLocation;
4052 agentAccess = reply.AgentAccess;
4053 Movement.Camera.LookDirection(reply.LookAt);
4054 homePosition = reply.HomePosition;
4055 homeLookAt = reply.HomeLookAt;
4056 lookAt = reply.LookAt;
4057 }
4058  
4059 private void Network_OnDisconnected(object sender, DisconnectedEventArgs e)
4060 {
4061 // Null out the cached fullName since it can change after logging
4062 // in again (with a different account name or different login
4063 // server but using the same GridClient object
4064 fullName = null;
4065 }
4066  
4067 /// <summary>
4068 /// Crossed region handler for message that comes across the EventQueue. Sent to an agent
4069 /// when the agent crosses a sim border into a new region.
4070 /// </summary>
4071 /// <param name="capsKey">The message key</param>
4072 /// <param name="message">the IMessage object containing the deserialized data sent from the simulator</param>
4073 /// <param name="simulator">The <see cref="Simulator"/> which originated the packet</param>
4074 private void CrossedRegionEventHandler(string capsKey, IMessage message, Simulator simulator)
4075 {
4076 CrossedRegionMessage crossed = (CrossedRegionMessage)message;
4077  
4078 IPEndPoint endPoint = new IPEndPoint(crossed.IP, crossed.Port);
4079  
4080 Logger.DebugLog("Crossed in to new region area, attempting to connect to " + endPoint.ToString(), Client);
4081  
4082 Simulator oldSim = Client.Network.CurrentSim;
4083 Simulator newSim = Client.Network.Connect(endPoint, crossed.RegionHandle, true, crossed.SeedCapability.ToString());
4084  
4085 if (newSim != null)
4086 {
4087 Logger.Log("Finished crossing over in to region " + newSim.ToString(), Helpers.LogLevel.Info, Client);
4088 oldSim.AgentMovementComplete = false; // We're no longer there
4089 if (m_RegionCrossed != null)
4090 {
4091 OnRegionCrossed(new RegionCrossedEventArgs(oldSim, newSim));
4092 }
4093 }
4094 else
4095 {
4096 // The old simulator will (poorly) handle our movement still, so the connection isn't
4097 // completely shot yet
4098 Logger.Log("Failed to connect to new region " + endPoint.ToString() + " after crossing over",
4099 Helpers.LogLevel.Warning, Client);
4100 }
4101 }
4102  
4103 /// <summary>Process an incoming packet and raise the appropriate events</summary>
4104 /// <param name="sender">The sender</param>
4105 /// <param name="e">The EventArgs object containing the packet data</param>
4106 /// <remarks>This packet is now being sent via the EventQueue</remarks>
4107 protected void CrossedRegionHandler(object sender, PacketReceivedEventArgs e)
4108 {
4109 Packet packet = e.Packet;
4110 CrossedRegionPacket crossing = (CrossedRegionPacket)packet;
4111 string seedCap = Utils.BytesToString(crossing.RegionData.SeedCapability);
4112 IPEndPoint endPoint = new IPEndPoint(crossing.RegionData.SimIP, crossing.RegionData.SimPort);
4113  
4114 Logger.DebugLog("Crossed in to new region area, attempting to connect to " + endPoint.ToString(), Client);
4115  
4116 Simulator oldSim = Client.Network.CurrentSim;
4117 Simulator newSim = Client.Network.Connect(endPoint, crossing.RegionData.RegionHandle, true, seedCap);
4118  
4119 if (newSim != null)
4120 {
4121 Logger.Log("Finished crossing over in to region " + newSim.ToString(), Helpers.LogLevel.Info, Client);
4122  
4123 if (m_RegionCrossed != null)
4124 {
4125 OnRegionCrossed(new RegionCrossedEventArgs(oldSim, newSim));
4126 }
4127 }
4128 else
4129 {
4130 // The old simulator will (poorly) handle our movement still, so the connection isn't
4131 // completely shot yet
4132 Logger.Log("Failed to connect to new region " + endPoint.ToString() + " after crossing over",
4133 Helpers.LogLevel.Warning, Client);
4134 }
4135 }
4136  
4137 /// <summary>
4138 /// Group Chat event handler
4139 /// </summary>
4140 /// <param name="capsKey">The capability Key</param>
4141 /// <param name="message">IMessage object containing decoded data from OSD</param>
4142 /// <param name="simulator"></param>
4143 protected void ChatterBoxSessionEventReplyEventHandler(string capsKey, IMessage message, Simulator simulator)
4144 {
4145 ChatterboxSessionEventReplyMessage msg = (ChatterboxSessionEventReplyMessage)message;
4146  
4147 if (!msg.Success)
4148 {
4149 RequestJoinGroupChat(msg.SessionID);
4150 Logger.Log("Attempt to send group chat to non-existant session for group " + msg.SessionID,
4151 Helpers.LogLevel.Info, Client);
4152 }
4153 }
4154  
4155 /// <summary>
4156 /// Response from request to join a group chat
4157 /// </summary>
4158 /// <param name="capsKey"></param>
4159 /// <param name="message">IMessage object containing decoded data from OSD</param>
4160 /// <param name="simulator"></param>
4161 protected void ChatterBoxSessionStartReplyEventHandler(string capsKey, IMessage message, Simulator simulator)
4162 {
4163 ChatterBoxSessionStartReplyMessage msg = (ChatterBoxSessionStartReplyMessage)message;
4164  
4165 if (msg.Success)
4166 {
4167 lock (GroupChatSessions.Dictionary)
4168 if (!GroupChatSessions.ContainsKey(msg.SessionID))
4169 GroupChatSessions.Add(msg.SessionID, new List<ChatSessionMember>());
4170 }
4171  
4172 OnGroupChatJoined(new GroupChatJoinedEventArgs(msg.SessionID, msg.SessionName, msg.TempSessionID, msg.Success));
4173 }
4174  
4175 /// <summary>
4176 /// Someone joined or left group chat
4177 /// </summary>
4178 /// <param name="capsKey"></param>
4179 /// <param name="message">IMessage object containing decoded data from OSD</param>
4180 /// <param name="simulator"></param>
4181 private void ChatterBoxSessionAgentListUpdatesEventHandler(string capsKey, IMessage message, Simulator simulator)
4182 {
4183 ChatterBoxSessionAgentListUpdatesMessage msg = (ChatterBoxSessionAgentListUpdatesMessage)message;
4184  
4185 lock (GroupChatSessions.Dictionary)
4186 if (!GroupChatSessions.ContainsKey(msg.SessionID))
4187 GroupChatSessions.Add(msg.SessionID, new List<ChatSessionMember>());
4188  
4189 for (int i = 0; i < msg.Updates.Length; i++)
4190 {
4191 ChatSessionMember fndMbr;
4192 lock (GroupChatSessions.Dictionary)
4193 {
4194 fndMbr = GroupChatSessions[msg.SessionID].Find(delegate(ChatSessionMember member)
4195 {
4196 return member.AvatarKey == msg.Updates[i].AgentID;
4197 });
4198 }
4199  
4200 if (msg.Updates[i].Transition != null)
4201 {
4202 if (msg.Updates[i].Transition.Equals("ENTER"))
4203 {
4204 if (fndMbr.AvatarKey == UUID.Zero)
4205 {
4206 fndMbr = new ChatSessionMember();
4207 fndMbr.AvatarKey = msg.Updates[i].AgentID;
4208  
4209 lock (GroupChatSessions.Dictionary)
4210 GroupChatSessions[msg.SessionID].Add(fndMbr);
4211  
4212 if (m_ChatSessionMemberAdded != null)
4213 {
4214 OnChatSessionMemberAdded(new ChatSessionMemberAddedEventArgs(msg.SessionID, fndMbr.AvatarKey));
4215 }
4216 }
4217 }
4218 else if (msg.Updates[i].Transition.Equals("LEAVE"))
4219 {
4220 if (fndMbr.AvatarKey != UUID.Zero)
4221 lock (GroupChatSessions.Dictionary)
4222 GroupChatSessions[msg.SessionID].Remove(fndMbr);
4223  
4224 if (m_ChatSessionMemberLeft != null)
4225 {
4226 OnChatSessionMemberLeft(new ChatSessionMemberLeftEventArgs(msg.SessionID, msg.Updates[i].AgentID));
4227 }
4228 }
4229 }
4230  
4231 // handle updates
4232 ChatSessionMember update_member = GroupChatSessions.Dictionary[msg.SessionID].Find(delegate(ChatSessionMember m)
4233 {
4234 return m.AvatarKey == msg.Updates[i].AgentID;
4235 });
4236  
4237  
4238 update_member.MuteText = msg.Updates[i].MuteText;
4239 update_member.MuteVoice = msg.Updates[i].MuteVoice;
4240  
4241 update_member.CanVoiceChat = msg.Updates[i].CanVoiceChat;
4242 update_member.IsModerator = msg.Updates[i].IsModerator;
4243  
4244 // replace existing member record
4245 lock (GroupChatSessions.Dictionary)
4246 {
4247 int found = GroupChatSessions.Dictionary[msg.SessionID].FindIndex(delegate(ChatSessionMember m)
4248 {
4249 return m.AvatarKey == msg.Updates[i].AgentID;
4250 });
4251  
4252 if (found >= 0)
4253 GroupChatSessions.Dictionary[msg.SessionID][found] = update_member;
4254 }
4255 }
4256 }
4257  
4258 /// <summary>
4259 /// Handle a group chat Invitation
4260 /// </summary>
4261 /// <param name="capsKey">Caps Key</param>
4262 /// <param name="message">IMessage object containing decoded data from OSD</param>
4263 /// <param name="simulator">Originating Simulator</param>
4264 private void ChatterBoxInvitationEventHandler(string capsKey, IMessage message, Simulator simulator)
4265 {
4266 if (m_InstantMessage != null)
4267 {
4268 ChatterBoxInvitationMessage msg = (ChatterBoxInvitationMessage)message;
4269  
4270 //TODO: do something about invitations to voice group chat/friends conference
4271 //Skip for now
4272 if (msg.Voice) return;
4273  
4274 InstantMessage im = new InstantMessage();
4275  
4276 im.FromAgentID = msg.FromAgentID;
4277 im.FromAgentName = msg.FromAgentName;
4278 im.ToAgentID = msg.ToAgentID;
4279 im.ParentEstateID = (uint)msg.ParentEstateID;
4280 im.RegionID = msg.RegionID;
4281 im.Position = msg.Position;
4282 im.Dialog = msg.Dialog;
4283 im.GroupIM = msg.GroupIM;
4284 im.IMSessionID = msg.IMSessionID;
4285 im.Timestamp = msg.Timestamp;
4286 im.Message = msg.Message;
4287 im.Offline = msg.Offline;
4288 im.BinaryBucket = msg.BinaryBucket;
4289 try
4290 {
4291 ChatterBoxAcceptInvite(msg.IMSessionID);
4292 }
4293 catch (Exception ex)
4294 {
4295 Logger.Log("Failed joining IM:", Helpers.LogLevel.Warning, Client, ex);
4296 }
4297 OnInstantMessage(new InstantMessageEventArgs(im, simulator));
4298 }
4299 }
4300  
4301  
4302 /// <summary>
4303 /// Moderate a chat session
4304 /// </summary>
4305 /// <param name="sessionID">the <see cref="UUID"/> of the session to moderate, for group chats this will be the groups UUID</param>
4306 /// <param name="memberID">the <see cref="UUID"/> of the avatar to moderate</param>
4307 /// <param name="key">Either "voice" to moderate users voice, or "text" to moderate users text session</param>
4308 /// <param name="moderate">true to moderate (silence user), false to allow avatar to speak</param>
4309 public void ModerateChatSessions(UUID sessionID, UUID memberID, string key, bool moderate)
4310 {
4311 if (Client.Network.CurrentSim == null || Client.Network.CurrentSim.Caps == null)
4312 throw new Exception("ChatSessionRequest capability is not currently available");
4313  
4314 Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("ChatSessionRequest");
4315  
4316 if (url != null)
4317 {
4318 ChatSessionRequestMuteUpdate req = new ChatSessionRequestMuteUpdate();
4319  
4320 req.RequestKey = key;
4321 req.RequestValue = moderate;
4322 req.SessionID = sessionID;
4323 req.AgentID = memberID;
4324  
4325 CapsClient request = new CapsClient(url);
4326 request.BeginGetResponse(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
4327 }
4328 else
4329 {
4330 throw new Exception("ChatSessionRequest capability is not currently available");
4331 }
4332 }
4333  
4334 /// <summary>Process an incoming packet and raise the appropriate events</summary>
4335 /// <param name="sender">The sender</param>
4336 /// <param name="e">The EventArgs object containing the packet data</param>
4337 protected void AlertMessageHandler(object sender, PacketReceivedEventArgs e)
4338 {
4339 if (m_AlertMessage != null)
4340 {
4341 Packet packet = e.Packet;
4342  
4343 AlertMessagePacket alert = (AlertMessagePacket)packet;
4344  
4345 OnAlertMessage(new AlertMessageEventArgs(Utils.BytesToString(alert.AlertData.Message)));
4346 }
4347 }
4348  
4349 /// <summary>Process an incoming packet and raise the appropriate events</summary>
4350 /// <param name="sender">The sender</param>
4351 /// <param name="e">The EventArgs object containing the packet data</param>
4352 protected void CameraConstraintHandler(object sender, PacketReceivedEventArgs e)
4353 {
4354 if (m_CameraConstraint != null)
4355 {
4356 Packet packet = e.Packet;
4357  
4358 CameraConstraintPacket camera = (CameraConstraintPacket)packet;
4359 OnCameraConstraint(new CameraConstraintEventArgs(camera.CameraCollidePlane.Plane));
4360 }
4361 }
4362  
4363 /// <summary>Process an incoming packet and raise the appropriate events</summary>
4364 /// <param name="sender">The sender</param>
4365 /// <param name="e">The EventArgs object containing the packet data</param>
4366 protected void ScriptSensorReplyHandler(object sender, PacketReceivedEventArgs e)
4367 {
4368 if (m_ScriptSensorReply != null)
4369 {
4370 Packet packet = e.Packet;
4371  
4372 ScriptSensorReplyPacket reply = (ScriptSensorReplyPacket)packet;
4373  
4374 for (int i = 0; i < reply.SensedData.Length; i++)
4375 {
4376 ScriptSensorReplyPacket.SensedDataBlock block = reply.SensedData[i];
4377 ScriptSensorReplyPacket.RequesterBlock requestor = reply.Requester;
4378  
4379 OnScriptSensorReply(new ScriptSensorReplyEventArgs(requestor.SourceID, block.GroupID, Utils.BytesToString(block.Name),
4380 block.ObjectID, block.OwnerID, block.Position, block.Range, block.Rotation, (ScriptSensorTypeFlags)block.Type, block.Velocity));
4381 }
4382 }
4383  
4384 }
4385  
4386 /// <summary>Process an incoming packet and raise the appropriate events</summary>
4387 /// <param name="sender">The sender</param>
4388 /// <param name="e">The EventArgs object containing the packet data</param>
4389 protected void AvatarSitResponseHandler(object sender, PacketReceivedEventArgs e)
4390 {
4391 if (m_AvatarSitResponse != null)
4392 {
4393 Packet packet = e.Packet;
4394  
4395 AvatarSitResponsePacket sit = (AvatarSitResponsePacket)packet;
4396  
4397 OnAvatarSitResponse(new AvatarSitResponseEventArgs(sit.SitObject.ID, sit.SitTransform.AutoPilot, sit.SitTransform.CameraAtOffset,
4398 sit.SitTransform.CameraEyeOffset, sit.SitTransform.ForceMouselook, sit.SitTransform.SitPosition,
4399 sit.SitTransform.SitRotation));
4400 }
4401 }
4402  
4403 protected void MuteListUpdateHander(object sender, PacketReceivedEventArgs e)
4404 {
4405 MuteListUpdatePacket packet = (MuteListUpdatePacket)e.Packet;
4406 if (packet.MuteData.AgentID != Client.Self.AgentID)
4407 {
4408 return;
4409 }
4410  
4411 WorkPool.QueueUserWorkItem(sync =>
4412 {
4413 using (AutoResetEvent gotMuteList = new AutoResetEvent(false))
4414 {
4415 string fileName = Utils.BytesToString(packet.MuteData.Filename);
4416 string muteList = string.Empty;
4417 ulong xferID = 0;
4418 byte[] assetData = null;
4419  
4420 EventHandler<XferReceivedEventArgs> xferCallback = (object xsender, XferReceivedEventArgs xe) =>
4421 {
4422 if (xe.Xfer.XferID == xferID)
4423 {
4424 assetData = xe.Xfer.AssetData;
4425 gotMuteList.Set();
4426 }
4427 };
4428  
4429  
4430 Client.Assets.XferReceived += xferCallback;
4431 xferID = Client.Assets.RequestAssetXfer(fileName, true, false, UUID.Zero, AssetType.Unknown, true);
4432  
4433 if (gotMuteList.WaitOne(60 * 1000, false))
4434 {
4435 muteList = Utils.BytesToString(assetData);
4436  
4437 lock (MuteList.Dictionary)
4438 {
4439 MuteList.Dictionary.Clear();
4440 foreach (var line in muteList.Split('\n'))
4441 {
4442 if (line.Trim() == string.Empty) continue;
4443  
4444 try
4445 {
4446 Match m;
4447 if ((m = Regex.Match(line, @"(?<MyteType>\d+)\s+(?<Key>[a-zA-Z0-9-]+)\s+(?<Name>[^|]+)|(?<Flags>.+)", RegexOptions.CultureInvariant)).Success)
4448 {
4449 MuteEntry me = new MuteEntry();
4450 me.Type = (MuteType)int.Parse(m.Groups["MyteType"].Value);
4451 me.ID = new UUID(m.Groups["Key"].Value);
4452 me.Name = m.Groups["Name"].Value;
4453 int flags = 0;
4454 int.TryParse(m.Groups["Flags"].Value, out flags);
4455 me.Flags = (MuteFlags)flags;
4456 MuteList[string.Format("{0}|{1}", me.ID, me.Name)] = me;
4457 }
4458 else
4459 {
4460 throw new ArgumentException("Invalid mutelist entry line");
4461 }
4462 }
4463 catch (Exception ex)
4464 {
4465 Logger.Log("Failed to parse the mute list line: " + line, Helpers.LogLevel.Warning, Client, ex);
4466 }
4467 }
4468 }
4469  
4470 OnMuteListUpdated(EventArgs.Empty);
4471 }
4472 else
4473 {
4474 Logger.Log("Timed out waiting for mute list download", Helpers.LogLevel.Warning, Client);
4475 }
4476  
4477 Client.Assets.XferReceived -= xferCallback;
4478  
4479 }
4480 });
4481 }
4482  
4483 #endregion Packet Handlers
4484 }
4485  
4486 #region Event Argument Classes
4487 /// <summary>
4488 /// Class for sending info on the success of the opration
4489 /// of setting the maturity access level
4490 /// </summary>
4491 public class AgentAccessEventArgs : EventArgs
4492 {
4493 readonly string mNewLevel;
4494 readonly bool mSuccess;
4495  
4496 /// <summary>
4497 /// New maturity accesss level returned from the sim
4498 /// </summary>
4499 public string NewLevel { get { return mNewLevel; } }
4500  
4501 /// <summary>
4502 /// True if setting the new maturity access level has succedded
4503 /// </summary>
4504 public bool Success { get { return mSuccess; } }
4505  
4506 /// <summary>
4507 /// Creates new instance of the EventArgs class
4508 /// </summary>
4509 /// <param name="success">Has setting new maturty access level succeeded</param>
4510 /// <param name="newLevel">New maturity access level as returned by the simulator</param>
4511 public AgentAccessEventArgs(bool success, string newLevel)
4512 {
4513 mNewLevel = newLevel;
4514 mSuccess = success;
4515 }
4516 }
4517  
4518 /// <summary>
4519 ///
4520 /// </summary>
4521 public class ChatEventArgs : EventArgs
4522 {
4523 private readonly Simulator m_Simulator;
4524 private readonly string m_Message;
4525 private readonly ChatAudibleLevel m_AudibleLevel;
4526 private readonly ChatType m_Type;
4527 private readonly ChatSourceType m_SourceType;
4528 private readonly string m_FromName;
4529 private readonly UUID m_SourceID;
4530 private readonly UUID m_OwnerID;
4531 private readonly Vector3 m_Position;
4532  
4533 /// <summary>Get the simulator sending the message</summary>
4534 public Simulator Simulator { get { return m_Simulator; } }
4535 /// <summary>Get the message sent</summary>
4536 public string Message { get { return m_Message; } }
4537 /// <summary>Get the audible level of the message</summary>
4538 public ChatAudibleLevel AudibleLevel { get { return m_AudibleLevel; } }
4539 /// <summary>Get the type of message sent: whisper, shout, etc</summary>
4540 public ChatType Type { get { return m_Type; } }
4541 /// <summary>Get the source type of the message sender</summary>
4542 public ChatSourceType SourceType { get { return m_SourceType; } }
4543 /// <summary>Get the name of the agent or object sending the message</summary>
4544 public string FromName { get { return m_FromName; } }
4545 /// <summary>Get the ID of the agent or object sending the message</summary>
4546 public UUID SourceID { get { return m_SourceID; } }
4547 /// <summary>Get the ID of the object owner, or the agent ID sending the message</summary>
4548 public UUID OwnerID { get { return m_OwnerID; } }
4549 /// <summary>Get the position of the agent or object sending the message</summary>
4550 public Vector3 Position { get { return m_Position; } }
4551  
4552 /// <summary>
4553 /// Construct a new instance of the ChatEventArgs object
4554 /// </summary>
4555 /// <param name="simulator">Sim from which the message originates</param>
4556 /// <param name="message">The message sent</param>
4557 /// <param name="audible">The audible level of the message</param>
4558 /// <param name="type">The type of message sent: whisper, shout, etc</param>
4559 /// <param name="sourceType">The source type of the message sender</param>
4560 /// <param name="fromName">The name of the agent or object sending the message</param>
4561 /// <param name="sourceId">The ID of the agent or object sending the message</param>
4562 /// <param name="ownerid">The ID of the object owner, or the agent ID sending the message</param>
4563 /// <param name="position">The position of the agent or object sending the message</param>
4564 public ChatEventArgs(Simulator simulator, string message, ChatAudibleLevel audible, ChatType type,
4565 ChatSourceType sourceType, string fromName, UUID sourceId, UUID ownerid, Vector3 position)
4566 {
4567 this.m_Simulator = simulator;
4568 this.m_Message = message;
4569 this.m_AudibleLevel = audible;
4570 this.m_Type = type;
4571 this.m_SourceType = sourceType;
4572 this.m_FromName = fromName;
4573 this.m_SourceID = sourceId;
4574 this.m_Position = position;
4575 this.m_OwnerID = ownerid;
4576 }
4577 }
4578  
4579 /// <summary>Contains the data sent when a primitive opens a dialog with this agent</summary>
4580 public class ScriptDialogEventArgs : EventArgs
4581 {
4582 private readonly string m_Message;
4583 private readonly string m_ObjectName;
4584 private readonly UUID m_ImageID;
4585 private readonly UUID m_ObjectID;
4586 private readonly string m_FirstName;
4587 private readonly string m_LastName;
4588 private readonly int m_Channel;
4589 private readonly List<string> m_ButtonLabels;
4590 private readonly UUID m_OwnerID;
4591  
4592 /// <summary>Get the dialog message</summary>
4593 public string Message { get { return m_Message; } }
4594 /// <summary>Get the name of the object that sent the dialog request</summary>
4595 public string ObjectName { get { return m_ObjectName; } }
4596 /// <summary>Get the ID of the image to be displayed</summary>
4597 public UUID ImageID { get { return m_ImageID; } }
4598 /// <summary>Get the ID of the primitive sending the dialog</summary>
4599 public UUID ObjectID { get { return m_ObjectID; } }
4600 /// <summary>Get the first name of the senders owner</summary>
4601 public string FirstName { get { return m_FirstName; } }
4602 /// <summary>Get the last name of the senders owner</summary>
4603 public string LastName { get { return m_LastName; } }
4604 /// <summary>Get the communication channel the dialog was sent on, responses
4605 /// should also send responses on this same channel</summary>
4606 public int Channel { get { return m_Channel; } }
4607 /// <summary>Get the string labels containing the options presented in this dialog</summary>
4608 public List<string> ButtonLabels { get { return m_ButtonLabels; } }
4609 /// <summary>UUID of the scritped object owner</summary>
4610 public UUID OwnerID { get { return m_OwnerID; } }
4611  
4612 /// <summary>
4613 /// Construct a new instance of the ScriptDialogEventArgs
4614 /// </summary>
4615 /// <param name="message">The dialog message</param>
4616 /// <param name="objectName">The name of the object that sent the dialog request</param>
4617 /// <param name="imageID">The ID of the image to be displayed</param>
4618 /// <param name="objectID">The ID of the primitive sending the dialog</param>
4619 /// <param name="firstName">The first name of the senders owner</param>
4620 /// <param name="lastName">The last name of the senders owner</param>
4621 /// <param name="chatChannel">The communication channel the dialog was sent on</param>
4622 /// <param name="buttons">The string labels containing the options presented in this dialog</param>
4623 /// <param name="ownerID">UUID of the scritped object owner</param>
4624 public ScriptDialogEventArgs(string message, string objectName, UUID imageID,
4625 UUID objectID, string firstName, string lastName, int chatChannel, List<string> buttons, UUID ownerID)
4626 {
4627 this.m_Message = message;
4628 this.m_ObjectName = objectName;
4629 this.m_ImageID = imageID;
4630 this.m_ObjectID = objectID;
4631 this.m_FirstName = firstName;
4632 this.m_LastName = lastName;
4633 this.m_Channel = chatChannel;
4634 this.m_ButtonLabels = buttons;
4635 this.m_OwnerID = ownerID;
4636 }
4637 }
4638  
4639 /// <summary>Contains the data sent when a primitive requests debit or other permissions
4640 /// requesting a YES or NO answer</summary>
4641 public class ScriptQuestionEventArgs : EventArgs
4642 {
4643 private readonly Simulator m_Simulator;
4644 private readonly UUID m_TaskID;
4645 private readonly UUID m_ItemID;
4646 private readonly string m_ObjectName;
4647 private readonly string m_ObjectOwnerName;
4648 private readonly ScriptPermission m_Questions;
4649  
4650 /// <summary>Get the simulator containing the object sending the request</summary>
4651 public Simulator Simulator { get { return m_Simulator; } }
4652 /// <summary>Get the ID of the script making the request</summary>
4653 public UUID TaskID { get { return m_TaskID; } }
4654 /// <summary>Get the ID of the primitive containing the script making the request</summary>
4655 public UUID ItemID { get { return m_ItemID; } }
4656 /// <summary>Get the name of the primitive making the request</summary>
4657 public string ObjectName { get { return m_ObjectName; } }
4658 /// <summary>Get the name of the owner of the object making the request</summary>
4659 public string ObjectOwnerName { get { return m_ObjectOwnerName; } }
4660 /// <summary>Get the permissions being requested</summary>
4661 public ScriptPermission Questions { get { return m_Questions; } }
4662  
4663 /// <summary>
4664 /// Construct a new instance of the ScriptQuestionEventArgs
4665 /// </summary>
4666 /// <param name="simulator">The simulator containing the object sending the request</param>
4667 /// <param name="taskID">The ID of the script making the request</param>
4668 /// <param name="itemID">The ID of the primitive containing the script making the request</param>
4669 /// <param name="objectName">The name of the primitive making the request</param>
4670 /// <param name="objectOwner">The name of the owner of the object making the request</param>
4671 /// <param name="questions">The permissions being requested</param>
4672 public ScriptQuestionEventArgs(Simulator simulator, UUID taskID, UUID itemID, string objectName, string objectOwner, ScriptPermission questions)
4673 {
4674 this.m_Simulator = simulator;
4675 this.m_TaskID = taskID;
4676 this.m_ItemID = itemID;
4677 this.m_ObjectName = objectName;
4678 this.m_ObjectOwnerName = objectOwner;
4679 this.m_Questions = questions;
4680 }
4681  
4682 }
4683  
4684 /// <summary>Contains the data sent when a primitive sends a request
4685 /// to an agent to open the specified URL</summary>
4686 public class LoadUrlEventArgs : EventArgs
4687 {
4688 private readonly string m_ObjectName;
4689 private readonly UUID m_ObjectID;
4690 private readonly UUID m_OwnerID;
4691 private readonly bool m_OwnerIsGroup;
4692 private readonly string m_Message;
4693 private readonly string m_URL;
4694  
4695 /// <summary>Get the name of the object sending the request</summary>
4696 public string ObjectName { get { return m_ObjectName; } }
4697 /// <summary>Get the ID of the object sending the request</summary>
4698 public UUID ObjectID { get { return m_ObjectID; } }
4699 /// <summary>Get the ID of the owner of the object sending the request</summary>
4700 public UUID OwnerID { get { return m_OwnerID; } }
4701 /// <summary>True if the object is owned by a group</summary>
4702 public bool OwnerIsGroup { get { return m_OwnerIsGroup; } }
4703 /// <summary>Get the message sent with the request</summary>
4704 public string Message { get { return m_Message; } }
4705 /// <summary>Get the URL the object sent</summary>
4706 public string URL { get { return m_URL; } }
4707  
4708 /// <summary>
4709 /// Construct a new instance of the LoadUrlEventArgs
4710 /// </summary>
4711 /// <param name="objectName">The name of the object sending the request</param>
4712 /// <param name="objectID">The ID of the object sending the request</param>
4713 /// <param name="ownerID">The ID of the owner of the object sending the request</param>
4714 /// <param name="ownerIsGroup">True if the object is owned by a group</param>
4715 /// <param name="message">The message sent with the request</param>
4716 /// <param name="URL">The URL the object sent</param>
4717 public LoadUrlEventArgs(string objectName, UUID objectID, UUID ownerID, bool ownerIsGroup, string message, string URL)
4718 {
4719 this.m_ObjectName = objectName;
4720 this.m_ObjectID = objectID;
4721 this.m_OwnerID = ownerID;
4722 this.m_OwnerIsGroup = ownerIsGroup;
4723 this.m_Message = message;
4724 this.m_URL = URL;
4725 }
4726 }
4727  
4728 /// <summary>The date received from an ImprovedInstantMessage</summary>
4729 public class InstantMessageEventArgs : EventArgs
4730 {
4731 private readonly InstantMessage m_IM;
4732 private readonly Simulator m_Simulator;
4733  
4734 /// <summary>Get the InstantMessage object</summary>
4735 public InstantMessage IM { get { return m_IM; } }
4736 /// <summary>Get the simulator where the InstantMessage origniated</summary>
4737 public Simulator Simulator { get { return m_Simulator; } }
4738  
4739 /// <summary>
4740 /// Construct a new instance of the InstantMessageEventArgs object
4741 /// </summary>
4742 /// <param name="im">the InstantMessage object</param>
4743 /// <param name="simulator">the simulator where the InstantMessage origniated</param>
4744 public InstantMessageEventArgs(InstantMessage im, Simulator simulator)
4745 {
4746 this.m_IM = im;
4747 this.m_Simulator = simulator;
4748 }
4749 }
4750  
4751 /// <summary>Contains the currency balance</summary>
4752 public class BalanceEventArgs : EventArgs
4753 {
4754 private readonly int m_Balance;
4755  
4756 /// <summary>
4757 /// Get the currenct balance
4758 /// </summary>
4759 public int Balance { get { return m_Balance; } }
4760  
4761 /// <summary>
4762 /// Construct a new BalanceEventArgs object
4763 /// </summary>
4764 /// <param name="balance">The currenct balance</param>
4765 public BalanceEventArgs(int balance)
4766 {
4767 this.m_Balance = balance;
4768 }
4769 }
4770  
4771 /// <summary>Contains the transaction summary when an item is purchased,
4772 /// money is given, or land is purchased</summary>
4773 public class MoneyBalanceReplyEventArgs : EventArgs
4774 {
4775 private readonly UUID m_TransactionID;
4776 private readonly bool m_Success;
4777 private readonly int m_Balance;
4778 private readonly int m_MetersCredit;
4779 private readonly int m_MetersCommitted;
4780 private readonly string m_Description;
4781 private TransactionInfo m_TransactionInfo;
4782  
4783 /// <summary>Get the ID of the transaction</summary>
4784 public UUID TransactionID { get { return m_TransactionID; } }
4785 /// <summary>True of the transaction was successful</summary>
4786 public bool Success { get { return m_Success; } }
4787 /// <summary>Get the remaining currency balance</summary>
4788 public int Balance { get { return m_Balance; } }
4789 /// <summary>Get the meters credited</summary>
4790 public int MetersCredit { get { return m_MetersCredit; } }
4791 /// <summary>Get the meters comitted</summary>
4792 public int MetersCommitted { get { return m_MetersCommitted; } }
4793 /// <summary>Get the description of the transaction</summary>
4794 public string Description { get { return m_Description; } }
4795 /// <summary>Detailed transaction information</summary>
4796 public TransactionInfo TransactionInfo { get { return m_TransactionInfo; } }
4797 /// <summary>
4798 /// Construct a new instance of the MoneyBalanceReplyEventArgs object
4799 /// </summary>
4800 /// <param name="transactionID">The ID of the transaction</param>
4801 /// <param name="transactionSuccess">True of the transaction was successful</param>
4802 /// <param name="balance">The current currency balance</param>
4803 /// <param name="metersCredit">The meters credited</param>
4804 /// <param name="metersCommitted">The meters comitted</param>
4805 /// <param name="description">A brief description of the transaction</param>
4806 /// <param name="transactionInfo">Transaction info</param>
4807 public MoneyBalanceReplyEventArgs(UUID transactionID, bool transactionSuccess, int balance, int metersCredit, int metersCommitted, string description, TransactionInfo transactionInfo)
4808 {
4809 this.m_TransactionID = transactionID;
4810 this.m_Success = transactionSuccess;
4811 this.m_Balance = balance;
4812 this.m_MetersCredit = metersCredit;
4813 this.m_MetersCommitted = metersCommitted;
4814 this.m_Description = description;
4815 this.m_TransactionInfo = transactionInfo;
4816 }
4817 }
4818  
4819 // string message, TeleportStatus status, TeleportFlags flags
4820 public class TeleportEventArgs : EventArgs
4821 {
4822 private readonly string m_Message;
4823 private readonly TeleportStatus m_Status;
4824 private readonly TeleportFlags m_Flags;
4825  
4826 public string Message { get { return m_Message; } }
4827 public TeleportStatus Status { get { return m_Status; } }
4828 public TeleportFlags Flags { get { return m_Flags; } }
4829  
4830 public TeleportEventArgs(string message, TeleportStatus status, TeleportFlags flags)
4831 {
4832 this.m_Message = message;
4833 this.m_Status = status;
4834 this.m_Flags = flags;
4835 }
4836 }
4837  
4838 /// <summary>Data sent from the simulator containing information about your agent and active group information</summary>
4839 public class AgentDataReplyEventArgs : EventArgs
4840 {
4841 private readonly string m_FirstName;
4842 private readonly string m_LastName;
4843 private readonly UUID m_ActiveGroupID;
4844 private readonly string m_GroupTitle;
4845 private readonly GroupPowers m_GroupPowers;
4846 private readonly string m_GroupName;
4847  
4848 /// <summary>Get the agents first name</summary>
4849 public string FirstName { get { return m_FirstName; } }
4850 /// <summary>Get the agents last name</summary>
4851 public string LastName { get { return m_LastName; } }
4852 /// <summary>Get the active group ID of your agent</summary>
4853 public UUID ActiveGroupID { get { return m_ActiveGroupID; } }
4854 /// <summary>Get the active groups title of your agent</summary>
4855 public string GroupTitle { get { return m_GroupTitle; } }
4856 /// <summary>Get the combined group powers of your agent</summary>
4857 public GroupPowers GroupPowers { get { return m_GroupPowers; } }
4858 /// <summary>Get the active group name of your agent</summary>
4859 public string GroupName { get { return m_GroupName; } }
4860  
4861 /// <summary>
4862 /// Construct a new instance of the AgentDataReplyEventArgs object
4863 /// </summary>
4864 /// <param name="firstName">The agents first name</param>
4865 /// <param name="lastName">The agents last name</param>
4866 /// <param name="activeGroupID">The agents active group ID</param>
4867 /// <param name="groupTitle">The group title of the agents active group</param>
4868 /// <param name="groupPowers">The combined group powers the agent has in the active group</param>
4869 /// <param name="groupName">The name of the group the agent has currently active</param>
4870 public AgentDataReplyEventArgs(string firstName, string lastName, UUID activeGroupID,
4871 string groupTitle, GroupPowers groupPowers, string groupName)
4872 {
4873 this.m_FirstName = firstName;
4874 this.m_LastName = lastName;
4875 this.m_ActiveGroupID = activeGroupID;
4876 this.m_GroupTitle = groupTitle;
4877 this.m_GroupPowers = groupPowers;
4878 this.m_GroupName = groupName;
4879 }
4880 }
4881  
4882 /// <summary>Data sent by the simulator to indicate the active/changed animations
4883 /// applied to your agent</summary>
4884 public class AnimationsChangedEventArgs : EventArgs
4885 {
4886 private readonly InternalDictionary<UUID, int> m_Animations;
4887  
4888 /// <summary>Get the dictionary that contains the changed animations</summary>
4889 public InternalDictionary<UUID, int> Animations { get { return m_Animations; } }
4890  
4891 /// <summary>
4892 /// Construct a new instance of the AnimationsChangedEventArgs class
4893 /// </summary>
4894 /// <param name="agentAnimations">The dictionary that contains the changed animations</param>
4895 public AnimationsChangedEventArgs(InternalDictionary<UUID, int> agentAnimations)
4896 {
4897 this.m_Animations = agentAnimations;
4898 }
4899  
4900 }
4901  
4902 /// <summary>
4903 /// Data sent from a simulator indicating a collision with your agent
4904 /// </summary>
4905 public class MeanCollisionEventArgs : EventArgs
4906 {
4907 private readonly MeanCollisionType m_Type;
4908 private readonly UUID m_Aggressor;
4909 private readonly UUID m_Victim;
4910 private readonly float m_Magnitude;
4911 private readonly DateTime m_Time;
4912  
4913 /// <summary>Get the Type of collision</summary>
4914 public MeanCollisionType Type { get { return m_Type; } }
4915 /// <summary>Get the ID of the agent or object that collided with your agent</summary>
4916 public UUID Aggressor { get { return m_Aggressor; } }
4917 /// <summary>Get the ID of the agent that was attacked</summary>
4918 public UUID Victim { get { return m_Victim; } }
4919 /// <summary>A value indicating the strength of the collision</summary>
4920 public float Magnitude { get { return m_Magnitude; } }
4921 /// <summary>Get the time the collision occurred</summary>
4922 public DateTime Time { get { return m_Time; } }
4923  
4924 /// <summary>
4925 /// Construct a new instance of the MeanCollisionEventArgs class
4926 /// </summary>
4927 /// <param name="type">The type of collision that occurred</param>
4928 /// <param name="perp">The ID of the agent or object that perpetrated the agression</param>
4929 /// <param name="victim">The ID of the Victim</param>
4930 /// <param name="magnitude">The strength of the collision</param>
4931 /// <param name="time">The Time the collision occurred</param>
4932 public MeanCollisionEventArgs(MeanCollisionType type, UUID perp, UUID victim,
4933 float magnitude, DateTime time)
4934 {
4935 this.m_Type = type;
4936 this.m_Aggressor = perp;
4937 this.m_Victim = victim;
4938 this.m_Magnitude = magnitude;
4939 this.m_Time = time;
4940 }
4941 }
4942  
4943 /// <summary>Data sent to your agent when it crosses region boundaries</summary>
4944 public class RegionCrossedEventArgs : EventArgs
4945 {
4946 private readonly Simulator m_OldSimulator;
4947 private readonly Simulator m_NewSimulator;
4948  
4949 /// <summary>Get the simulator your agent just left</summary>
4950 public Simulator OldSimulator { get { return m_OldSimulator; } }
4951 /// <summary>Get the simulator your agent is now in</summary>
4952 public Simulator NewSimulator { get { return m_NewSimulator; } }
4953  
4954 /// <summary>
4955 /// Construct a new instance of the RegionCrossedEventArgs class
4956 /// </summary>
4957 /// <param name="oldSim">The simulator your agent just left</param>
4958 /// <param name="newSim">The simulator your agent is now in</param>
4959 public RegionCrossedEventArgs(Simulator oldSim, Simulator newSim)
4960 {
4961 this.m_OldSimulator = oldSim;
4962 this.m_NewSimulator = newSim;
4963 }
4964 }
4965  
4966 /// <summary>Data sent from the simulator when your agent joins a group chat session</summary>
4967 public class GroupChatJoinedEventArgs : EventArgs
4968 {
4969 private readonly UUID m_SessionID;
4970 private readonly string m_SessionName;
4971 private readonly UUID m_TmpSessionID;
4972 private readonly bool m_Success;
4973  
4974 /// <summary>Get the ID of the group chat session</summary>
4975 public UUID SessionID { get { return m_SessionID; } }
4976 /// <summary>Get the name of the session</summary>
4977 public string SessionName { get { return m_SessionName; } }
4978 /// <summary>Get the temporary session ID used for establishing new sessions</summary>
4979 public UUID TmpSessionID { get { return m_TmpSessionID; } }
4980 /// <summary>True if your agent successfully joined the session</summary>
4981 public bool Success { get { return m_Success; } }
4982  
4983 /// <summary>
4984 /// Construct a new instance of the GroupChatJoinedEventArgs class
4985 /// </summary>
4986 /// <param name="groupChatSessionID">The ID of the session</param>
4987 /// <param name="sessionName">The name of the session</param>
4988 /// <param name="tmpSessionID">A temporary session id used for establishing new sessions</param>
4989 /// <param name="success">True of your agent successfully joined the session</param>
4990 public GroupChatJoinedEventArgs(UUID groupChatSessionID, string sessionName, UUID tmpSessionID, bool success)
4991 {
4992 this.m_SessionID = groupChatSessionID;
4993 this.m_SessionName = sessionName;
4994 this.m_TmpSessionID = tmpSessionID;
4995 this.m_Success = success;
4996 }
4997 }
4998  
4999 /// <summary>Data sent by the simulator containing urgent messages</summary>
5000 public class AlertMessageEventArgs : EventArgs
5001 {
5002 private readonly string m_Message;
5003  
5004 /// <summary>Get the alert message</summary>
5005 public string Message { get { return m_Message; } }
5006  
5007 /// <summary>
5008 /// Construct a new instance of the AlertMessageEventArgs class
5009 /// </summary>
5010 /// <param name="message">The alert message</param>
5011 public AlertMessageEventArgs(string message)
5012 {
5013 this.m_Message = message;
5014 }
5015 }
5016  
5017 /// <summary>Data sent by a script requesting to take or release specified controls to your agent</summary>
5018 public class ScriptControlEventArgs : EventArgs
5019 {
5020 private readonly ScriptControlChange m_Controls;
5021 private readonly bool m_Pass;
5022 private readonly bool m_Take;
5023  
5024 /// <summary>Get the controls the script is attempting to take or release to the agent</summary>
5025 public ScriptControlChange Controls { get { return m_Controls; } }
5026 /// <summary>True if the script is passing controls back to the agent</summary>
5027 public bool Pass { get { return m_Pass; } }
5028 /// <summary>True if the script is requesting controls be released to the script</summary>
5029 public bool Take { get { return m_Take; } }
5030  
5031 /// <summary>
5032 /// Construct a new instance of the ScriptControlEventArgs class
5033 /// </summary>
5034 /// <param name="controls">The controls the script is attempting to take or release to the agent</param>
5035 /// <param name="pass">True if the script is passing controls back to the agent</param>
5036 /// <param name="take">True if the script is requesting controls be released to the script</param>
5037 public ScriptControlEventArgs(ScriptControlChange controls, bool pass, bool take)
5038 {
5039 m_Controls = controls;
5040 m_Pass = pass;
5041 m_Take = take;
5042 }
5043 }
5044  
5045 /// <summary>
5046 /// Data sent from the simulator to an agent to indicate its view limits
5047 /// </summary>
5048 public class CameraConstraintEventArgs : EventArgs
5049 {
5050 private readonly Vector4 m_CollidePlane;
5051  
5052 /// <summary>Get the collision plane</summary>
5053 public Vector4 CollidePlane { get { return m_CollidePlane; } }
5054  
5055 /// <summary>
5056 /// Construct a new instance of the CameraConstraintEventArgs class
5057 /// </summary>
5058 /// <param name="collidePlane">The collision plane</param>
5059 public CameraConstraintEventArgs(Vector4 collidePlane)
5060 {
5061 m_CollidePlane = collidePlane;
5062 }
5063 }
5064  
5065 /// <summary>
5066 /// Data containing script sensor requests which allow an agent to know the specific details
5067 /// of a primitive sending script sensor requests
5068 /// </summary>
5069 public class ScriptSensorReplyEventArgs : EventArgs
5070 {
5071 private readonly UUID m_RequestorID;
5072 private readonly UUID m_GroupID;
5073 private readonly string m_Name;
5074 private readonly UUID m_ObjectID;
5075 private readonly UUID m_OwnerID;
5076 private readonly Vector3 m_Position;
5077 private readonly float m_Range;
5078 private readonly Quaternion m_Rotation;
5079 private readonly ScriptSensorTypeFlags m_Type;
5080 private readonly Vector3 m_Velocity;
5081  
5082 /// <summary>Get the ID of the primitive sending the sensor</summary>
5083 public UUID RequestorID { get { return m_RequestorID; } }
5084 /// <summary>Get the ID of the group associated with the primitive</summary>
5085 public UUID GroupID { get { return m_GroupID; } }
5086 /// <summary>Get the name of the primitive sending the sensor</summary>
5087 public string Name { get { return m_Name; } }
5088 /// <summary>Get the ID of the primitive sending the sensor</summary>
5089 public UUID ObjectID { get { return m_ObjectID; } }
5090 /// <summary>Get the ID of the owner of the primitive sending the sensor</summary>
5091 public UUID OwnerID { get { return m_OwnerID; } }
5092 /// <summary>Get the position of the primitive sending the sensor</summary>
5093 public Vector3 Position { get { return m_Position; } }
5094 /// <summary>Get the range the primitive specified to scan</summary>
5095 public float Range { get { return m_Range; } }
5096 /// <summary>Get the rotation of the primitive sending the sensor</summary>
5097 public Quaternion Rotation { get { return m_Rotation; } }
5098 /// <summary>Get the type of sensor the primitive sent</summary>
5099 public ScriptSensorTypeFlags Type { get { return m_Type; } }
5100 /// <summary>Get the velocity of the primitive sending the sensor</summary>
5101 public Vector3 Velocity { get { return m_Velocity; } }
5102  
5103 /// <summary>
5104 /// Construct a new instance of the ScriptSensorReplyEventArgs
5105 /// </summary>
5106 /// <param name="requestorID">The ID of the primitive sending the sensor</param>
5107 /// <param name="groupID">The ID of the group associated with the primitive</param>
5108 /// <param name="name">The name of the primitive sending the sensor</param>
5109 /// <param name="objectID">The ID of the primitive sending the sensor</param>
5110 /// <param name="ownerID">The ID of the owner of the primitive sending the sensor</param>
5111 /// <param name="position">The position of the primitive sending the sensor</param>
5112 /// <param name="range">The range the primitive specified to scan</param>
5113 /// <param name="rotation">The rotation of the primitive sending the sensor</param>
5114 /// <param name="type">The type of sensor the primitive sent</param>
5115 /// <param name="velocity">The velocity of the primitive sending the sensor</param>
5116 public ScriptSensorReplyEventArgs(UUID requestorID, UUID groupID, string name,
5117 UUID objectID, UUID ownerID, Vector3 position, float range, Quaternion rotation,
5118 ScriptSensorTypeFlags type, Vector3 velocity)
5119 {
5120 this.m_RequestorID = requestorID;
5121 this.m_GroupID = groupID;
5122 this.m_Name = name;
5123 this.m_ObjectID = objectID;
5124 this.m_OwnerID = ownerID;
5125 this.m_Position = position;
5126 this.m_Range = range;
5127 this.m_Rotation = rotation;
5128 this.m_Type = type;
5129 this.m_Velocity = velocity;
5130 }
5131 }
5132  
5133 /// <summary>Contains the response data returned from the simulator in response to a <see cref="RequestSit"/></summary>
5134 public class AvatarSitResponseEventArgs : EventArgs
5135 {
5136 private readonly UUID m_ObjectID;
5137 private readonly bool m_Autopilot;
5138 private readonly Vector3 m_CameraAtOffset;
5139 private readonly Vector3 m_CameraEyeOffset;
5140 private readonly bool m_ForceMouselook;
5141 private readonly Vector3 m_SitPosition;
5142 private readonly Quaternion m_SitRotation;
5143  
5144 /// <summary>Get the ID of the primitive the agent will be sitting on</summary>
5145 public UUID ObjectID { get { return m_ObjectID; } }
5146 /// <summary>True if the simulator Autopilot functions were involved</summary>
5147 public bool Autopilot { get { return m_Autopilot; } }
5148 /// <summary>Get the camera offset of the agent when seated</summary>
5149 public Vector3 CameraAtOffset { get { return m_CameraAtOffset; } }
5150 /// <summary>Get the camera eye offset of the agent when seated</summary>
5151 public Vector3 CameraEyeOffset { get { return m_CameraEyeOffset; } }
5152 /// <summary>True of the agent will be in mouselook mode when seated</summary>
5153 public bool ForceMouselook { get { return m_ForceMouselook; } }
5154 /// <summary>Get the position of the agent when seated</summary>
5155 public Vector3 SitPosition { get { return m_SitPosition; } }
5156 /// <summary>Get the rotation of the agent when seated</summary>
5157 public Quaternion SitRotation { get { return m_SitRotation; } }
5158  
5159 /// <summary>Construct a new instance of the AvatarSitResponseEventArgs object</summary>
5160 public AvatarSitResponseEventArgs(UUID objectID, bool autoPilot, Vector3 cameraAtOffset,
5161 Vector3 cameraEyeOffset, bool forceMouselook, Vector3 sitPosition, Quaternion sitRotation)
5162 {
5163 this.m_ObjectID = objectID;
5164 this.m_Autopilot = autoPilot;
5165 this.m_CameraAtOffset = cameraAtOffset;
5166 this.m_CameraEyeOffset = cameraEyeOffset;
5167 this.m_ForceMouselook = forceMouselook;
5168 this.m_SitPosition = sitPosition;
5169 this.m_SitRotation = sitRotation;
5170 }
5171 }
5172  
5173 /// <summary>Data sent when an agent joins a chat session your agent is currently participating in</summary>
5174 public class ChatSessionMemberAddedEventArgs : EventArgs
5175 {
5176 private readonly UUID m_SessionID;
5177 private readonly UUID m_AgentID;
5178  
5179 /// <summary>Get the ID of the chat session</summary>
5180 public UUID SessionID { get { return m_SessionID; } }
5181 /// <summary>Get the ID of the agent that joined</summary>
5182 public UUID AgentID { get { return m_AgentID; } }
5183  
5184 /// <summary>
5185 /// Construct a new instance of the ChatSessionMemberAddedEventArgs object
5186 /// </summary>
5187 /// <param name="sessionID">The ID of the chat session</param>
5188 /// <param name="agentID">The ID of the agent joining</param>
5189 public ChatSessionMemberAddedEventArgs(UUID sessionID, UUID agentID)
5190 {
5191 this.m_SessionID = sessionID;
5192 this.m_AgentID = agentID;
5193 }
5194 }
5195  
5196 /// <summary>Data sent when an agent exits a chat session your agent is currently participating in</summary>
5197 public class ChatSessionMemberLeftEventArgs : EventArgs
5198 {
5199 private readonly UUID m_SessionID;
5200 private readonly UUID m_AgentID;
5201  
5202 /// <summary>Get the ID of the chat session</summary>
5203 public UUID SessionID { get { return m_SessionID; } }
5204 /// <summary>Get the ID of the agent that left</summary>
5205 public UUID AgentID { get { return m_AgentID; } }
5206  
5207 /// <summary>
5208 /// Construct a new instance of the ChatSessionMemberLeftEventArgs object
5209 /// </summary>
5210 /// <param name="sessionID">The ID of the chat session</param>
5211 /// <param name="agentID">The ID of the Agent that left</param>
5212 public ChatSessionMemberLeftEventArgs(UUID sessionID, UUID agentID)
5213 {
5214 this.m_SessionID = sessionID;
5215 this.m_AgentID = agentID;
5216 }
5217 }
5218  
5219 /// <summary>Event arguments with the result of setting display name operation</summary>
5220 public class SetDisplayNameReplyEventArgs : EventArgs
5221 {
5222 private readonly int m_Status;
5223 private readonly string m_Reason;
5224 private readonly AgentDisplayName m_DisplayName;
5225  
5226 /// <summary>Status code, 200 indicates settign display name was successful</summary>
5227 public int Status { get { return m_Status; } }
5228  
5229 /// <summary>Textual description of the status</summary>
5230 public string Reason { get { return m_Reason; } }
5231  
5232 /// <summary>Details of the newly set display name</summary>
5233 public AgentDisplayName DisplayName { get { return m_DisplayName; } }
5234  
5235 /// <summary>Default constructor</summary>
5236 public SetDisplayNameReplyEventArgs(int status, string reason, AgentDisplayName displayName)
5237 {
5238 m_Status = status;
5239 m_Reason = reason;
5240 m_DisplayName = displayName;
5241 }
5242 }
5243  
5244 #endregion
5245 }