PageRenderTime 73ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/OpenMetaverse/Modules/AgentManager.cs

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