PageRenderTime 69ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/OpenMetaverse/Modules/GroupManager.cs

https://bitbucket.org/VirtualReality/3rdparty-addon-modules
C# | 2165 lines | 1300 code | 280 blank | 585 comment | 101 complexity | 07afd5a540832efd83ff1b997a820131 MD5 | raw file

Large files files are truncated, but you can click here to view the full 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.Collections.Generic;
  28. using OpenMetaverse.Packets;
  29. using OpenMetaverse.StructuredData;
  30. using OpenMetaverse.Messages.Linden;
  31. using OpenMetaverse.Interfaces;
  32. namespace OpenMetaverse
  33. {
  34. #region Structs
  35. /// <summary>
  36. /// Avatar group management
  37. /// </summary>
  38. public struct GroupMember
  39. {
  40. /// <summary>Key of Group Member</summary>
  41. public UUID ID;
  42. /// <summary>Total land contribution</summary>
  43. public int Contribution;
  44. /// <summary>Online status information</summary>
  45. public string OnlineStatus;
  46. /// <summary>Abilities that the Group Member has</summary>
  47. public GroupPowers Powers;
  48. /// <summary>Current group title</summary>
  49. public string Title;
  50. /// <summary>Is a group owner</summary>
  51. public bool IsOwner;
  52. }
  53. /// <summary>
  54. /// Role manager for a group
  55. /// </summary>
  56. public struct GroupRole
  57. {
  58. /// <summary>Key of the group</summary>
  59. public UUID GroupID;
  60. /// <summary>Key of Role</summary>
  61. public UUID ID;
  62. /// <summary>Name of Role</summary>
  63. public string Name;
  64. /// <summary>Group Title associated with Role</summary>
  65. public string Title;
  66. /// <summary>Description of Role</summary>
  67. public string Description;
  68. /// <summary>Abilities Associated with Role</summary>
  69. public GroupPowers Powers;
  70. /// <summary>Returns the role's title</summary>
  71. /// <returns>The role's title</returns>
  72. public override string ToString()
  73. {
  74. return Name;
  75. }
  76. }
  77. /// <summary>
  78. /// Class to represent Group Title
  79. /// </summary>
  80. public struct GroupTitle
  81. {
  82. /// <summary>Key of the group</summary>
  83. public UUID GroupID;
  84. /// <summary>ID of the role title belongs to</summary>
  85. public UUID RoleID;
  86. /// <summary>Group Title</summary>
  87. public string Title;
  88. /// <summary>Whether title is Active</summary>
  89. public bool Selected;
  90. /// <summary>Returns group title</summary>
  91. public override string ToString()
  92. {
  93. return Title;
  94. }
  95. }
  96. /// <summary>
  97. /// Represents a group on the grid
  98. /// </summary>
  99. public struct Group
  100. {
  101. /// <summary>Key of Group</summary>
  102. public UUID ID;
  103. /// <summary>Key of Group Insignia</summary>
  104. public UUID InsigniaID;
  105. /// <summary>Key of Group Founder</summary>
  106. public UUID FounderID;
  107. /// <summary>Key of Group Role for Owners</summary>
  108. public UUID OwnerRole;
  109. /// <summary>Name of Group</summary>
  110. public string Name;
  111. /// <summary>Text of Group Charter</summary>
  112. public string Charter;
  113. /// <summary>Title of "everyone" role</summary>
  114. public string MemberTitle;
  115. /// <summary>Is the group open for enrolement to everyone</summary>
  116. public bool OpenEnrollment;
  117. /// <summary>Will group show up in search</summary>
  118. public bool ShowInList;
  119. /// <summary></summary>
  120. public GroupPowers Powers;
  121. /// <summary></summary>
  122. public bool AcceptNotices;
  123. /// <summary></summary>
  124. public bool AllowPublish;
  125. /// <summary>Is the group Mature</summary>
  126. public bool MaturePublish;
  127. /// <summary>Cost of group membership</summary>
  128. public int MembershipFee;
  129. /// <summary></summary>
  130. public int Money;
  131. /// <summary></summary>
  132. public int Contribution;
  133. /// <summary>The total number of current members this group has</summary>
  134. public int GroupMembershipCount;
  135. /// <summary>The number of roles this group has configured</summary>
  136. public int GroupRolesCount;
  137. /// <summary>Show this group in agent's profile</summary>
  138. public bool ListInProfile;
  139. /// <summary>Returns the name of the group</summary>
  140. /// <returns>A string containing the name of the group</returns>
  141. public override string ToString()
  142. {
  143. return Name;
  144. }
  145. }
  146. /// <summary>
  147. /// A group Vote
  148. /// </summary>
  149. public struct Vote
  150. {
  151. /// <summary>Key of Avatar who created Vote</summary>
  152. public UUID Candidate;
  153. /// <summary>Text of the Vote proposal</summary>
  154. public string VoteString;
  155. /// <summary>Total number of votes</summary>
  156. public int NumVotes;
  157. }
  158. /// <summary>
  159. /// A group proposal
  160. /// </summary>
  161. public struct GroupProposal
  162. {
  163. /// <summary>The Text of the proposal</summary>
  164. public string VoteText;
  165. /// <summary>The minimum number of members that must vote before proposal passes or failes</summary>
  166. public int Quorum;
  167. /// <summary>The required ration of yes/no votes required for vote to pass</summary>
  168. /// <remarks>The three options are Simple Majority, 2/3 Majority, and Unanimous</remarks>
  169. /// TODO: this should be an enum
  170. public float Majority;
  171. /// <summary>The duration in days votes are accepted</summary>
  172. public int Duration;
  173. }
  174. /// <summary>
  175. ///
  176. /// </summary>
  177. public struct GroupAccountSummary
  178. {
  179. /// <summary></summary>
  180. public int IntervalDays;
  181. /// <summary></summary>
  182. public int CurrentInterval;
  183. /// <summary></summary>
  184. public string StartDate;
  185. /// <summary></summary>
  186. public int Balance;
  187. /// <summary></summary>
  188. public int TotalCredits;
  189. /// <summary></summary>
  190. public int TotalDebits;
  191. /// <summary></summary>
  192. public int ObjectTaxCurrent;
  193. /// <summary></summary>
  194. public int LightTaxCurrent;
  195. /// <summary></summary>
  196. public int LandTaxCurrent;
  197. /// <summary></summary>
  198. public int GroupTaxCurrent;
  199. /// <summary></summary>
  200. public int ParcelDirFeeCurrent;
  201. /// <summary></summary>
  202. public int ObjectTaxEstimate;
  203. /// <summary></summary>
  204. public int LightTaxEstimate;
  205. /// <summary></summary>
  206. public int LandTaxEstimate;
  207. /// <summary></summary>
  208. public int GroupTaxEstimate;
  209. /// <summary></summary>
  210. public int ParcelDirFeeEstimate;
  211. /// <summary></summary>
  212. public int NonExemptMembers;
  213. /// <summary></summary>
  214. public string LastTaxDate;
  215. /// <summary></summary>
  216. public string TaxDate;
  217. }
  218. /// <summary>
  219. /// Struct representing a group notice
  220. /// </summary>
  221. public struct GroupNotice
  222. {
  223. /// <summary></summary>
  224. public string Subject;
  225. /// <summary></summary>
  226. public string Message;
  227. /// <summary></summary>
  228. public UUID AttachmentID;
  229. /// <summary></summary>
  230. public UUID OwnerID;
  231. /// <summary>
  232. ///
  233. /// </summary>
  234. /// <returns></returns>
  235. public byte[] SerializeAttachment()
  236. {
  237. if (OwnerID == UUID.Zero || AttachmentID == UUID.Zero)
  238. return Utils.EmptyBytes;
  239. OpenMetaverse.StructuredData.OSDMap att = new OpenMetaverse.StructuredData.OSDMap();
  240. att.Add("item_id", OpenMetaverse.StructuredData.OSD.FromUUID(AttachmentID));
  241. att.Add("owner_id", OpenMetaverse.StructuredData.OSD.FromUUID(OwnerID));
  242. return OpenMetaverse.StructuredData.OSDParser.SerializeLLSDXmlBytes(att);
  243. /*
  244. //I guess this is how this works, no gaurentees
  245. string lsd = "<llsd><item_id>" + AttachmentID.ToString() + "</item_id><owner_id>"
  246. + OwnerID.ToString() + "</owner_id></llsd>";
  247. return Utils.StringToBytes(lsd);
  248. */
  249. }
  250. }
  251. /// <summary>
  252. /// Struct representing a group notice list entry
  253. /// </summary>
  254. public struct GroupNoticesListEntry
  255. {
  256. /// <summary>Notice ID</summary>
  257. public UUID NoticeID;
  258. /// <summary>Creation timestamp of notice</summary>
  259. public uint Timestamp;
  260. /// <summary>Agent name who created notice</summary>
  261. public string FromName;
  262. /// <summary>Notice subject</summary>
  263. public string Subject;
  264. /// <summary>Is there an attachment?</summary>
  265. public bool HasAttachment;
  266. /// <summary>Attachment Type</summary>
  267. public AssetType AssetType;
  268. }
  269. /// <summary>
  270. /// Struct representing a member of a group chat session and their settings
  271. /// </summary>
  272. public struct ChatSessionMember
  273. {
  274. /// <summary>The <see cref="UUID"/> of the Avatar</summary>
  275. public UUID AvatarKey;
  276. /// <summary>True if user has voice chat enabled</summary>
  277. public bool CanVoiceChat;
  278. /// <summary>True of Avatar has moderator abilities</summary>
  279. public bool IsModerator;
  280. /// <summary>True if a moderator has muted this avatars chat</summary>
  281. public bool MuteText;
  282. /// <summary>True if a moderator has muted this avatars voice</summary>
  283. public bool MuteVoice;
  284. }
  285. #endregion Structs
  286. #region Enums
  287. /// <summary>
  288. /// Role update flags
  289. /// </summary>
  290. public enum GroupRoleUpdate : uint
  291. {
  292. /// <summary></summary>
  293. NoUpdate,
  294. /// <summary></summary>
  295. UpdateData,
  296. /// <summary></summary>
  297. UpdatePowers,
  298. /// <summary></summary>
  299. UpdateAll,
  300. /// <summary></summary>
  301. Create,
  302. /// <summary></summary>
  303. Delete
  304. }
  305. [Flags]
  306. public enum GroupPowers : ulong
  307. {
  308. /// <summary></summary>
  309. None = 0,
  310. // Membership
  311. /// <summary>Can send invitations to groups default role</summary>
  312. Invite = 1UL << 1,
  313. /// <summary>Can eject members from group</summary>
  314. Eject = 1UL << 2,
  315. /// <summary>Can toggle 'Open Enrollment' and change 'Signup fee'</summary>
  316. ChangeOptions = 1UL << 3,
  317. /// <summary>Member is visible in the public member list</summary>
  318. MemberVisible = 1UL << 47,
  319. // Roles
  320. /// <summary>Can create new roles</summary>
  321. CreateRole = 1UL << 4,
  322. /// <summary>Can delete existing roles</summary>
  323. DeleteRole = 1UL << 5,
  324. /// <summary>Can change Role names, titles and descriptions</summary>
  325. RoleProperties = 1UL << 6,
  326. /// <summary>Can assign other members to assigners role</summary>
  327. AssignMemberLimited = 1UL << 7,
  328. /// <summary>Can assign other members to any role</summary>
  329. AssignMember = 1UL << 8,
  330. /// <summary>Can remove members from roles</summary>
  331. RemoveMember = 1UL << 9,
  332. /// <summary>Can assign and remove abilities in roles</summary>
  333. ChangeActions = 1UL << 10,
  334. // Identity
  335. /// <summary>Can change group Charter, Insignia, 'Publish on the web' and which
  336. /// members are publicly visible in group member listings</summary>
  337. ChangeIdentity = 1UL << 11,
  338. // Parcel management
  339. /// <summary>Can buy land or deed land to group</summary>
  340. LandDeed = 1UL << 12,
  341. /// <summary>Can abandon group owned land to Governor Linden on mainland, or Estate owner for
  342. /// private estates</summary>
  343. LandRelease = 1UL << 13,
  344. /// <summary>Can set land for-sale information on group owned parcels</summary>
  345. LandSetSale = 1UL << 14,
  346. /// <summary>Can subdivide and join parcels</summary>
  347. LandDivideJoin = 1UL << 15,
  348. // Chat
  349. /// <summary>Can join group chat sessions</summary>
  350. JoinChat = 1UL << 16,
  351. /// <summary>Can use voice chat in Group Chat sessions</summary>
  352. AllowVoiceChat = 1UL << 27,
  353. /// <summary>Can moderate group chat sessions</summary>
  354. ModerateChat = 1UL << 37,
  355. // Parcel identity
  356. /// <summary>Can toggle "Show in Find Places" and set search category</summary>
  357. FindPlaces = 1UL << 17,
  358. /// <summary>Can change parcel name, description, and 'Publish on web' settings</summary>
  359. LandChangeIdentity = 1UL << 18,
  360. /// <summary>Can set the landing point and teleport routing on group land</summary>
  361. SetLandingPoint = 1UL << 19,
  362. // Parcel settings
  363. /// <summary>Can change music and media settings</summary>
  364. ChangeMedia = 1UL << 20,
  365. /// <summary>Can toggle 'Edit Terrain' option in Land settings</summary>
  366. LandEdit = 1UL << 21,
  367. /// <summary>Can toggle various About Land > Options settings</summary>
  368. LandOptions = 1UL << 22,
  369. // Parcel powers
  370. /// <summary>Can always terraform land, even if parcel settings have it turned off</summary>
  371. AllowEditLand = 1UL << 23,
  372. /// <summary>Can always fly while over group owned land</summary>
  373. AllowFly = 1UL << 24,
  374. /// <summary>Can always rez objects on group owned land</summary>
  375. AllowRez = 1UL << 25,
  376. /// <summary>Can always create landmarks for group owned parcels</summary>
  377. AllowLandmark = 1UL << 26,
  378. /// <summary>Can set home location on any group owned parcel</summary>
  379. AllowSetHome = 1UL << 28,
  380. // Parcel access
  381. /// <summary>Can modify public access settings for group owned parcels</summary>
  382. LandManageAllowed = 1UL << 29,
  383. /// <summary>Can manager parcel ban lists on group owned land</summary>
  384. LandManageBanned = 1UL << 30,
  385. /// <summary>Can manage pass list sales information</summary>
  386. LandManagePasses = 1UL << 31,
  387. /// <summary>Can eject and freeze other avatars on group owned land</summary>
  388. LandEjectAndFreeze = 1UL << 32,
  389. // Parcel content
  390. /// <summary>Can return objects set to group</summary>
  391. ReturnGroupSet = 1UL << 33,
  392. /// <summary>Can return non-group owned/set objects</summary>
  393. ReturnNonGroup = 1UL << 34,
  394. /// <summary>Can return group owned objects</summary>
  395. ReturnGroupOwned = 1UL << 48,
  396. /// <summary>Can landscape using Linden plants</summary>
  397. LandGardening = 1UL << 35,
  398. // Objects
  399. /// <summary>Can deed objects to group</summary>
  400. DeedObject = 1UL << 36,
  401. /// <summary>Can move group owned objects</summary>
  402. ObjectManipulate = 1UL << 38,
  403. /// <summary>Can set group owned objects for-sale</summary>
  404. ObjectSetForSale = 1UL << 39,
  405. /// <summary>Pay group liabilities and receive group dividends</summary>
  406. Accountable = 1UL << 40,
  407. /// <summary>List and Host group events</summary>
  408. HostEvent = 1UL << 41,
  409. // Notices and proposals
  410. /// <summary>Can send group notices</summary>
  411. SendNotices = 1UL << 42,
  412. /// <summary>Can receive group notices</summary>
  413. ReceiveNotices = 1UL << 43,
  414. /// <summary>Can create group proposals</summary>
  415. StartProposal = 1UL << 44,
  416. /// <summary>Can vote on group proposals</summary>
  417. VoteOnProposal = 1UL << 45
  418. }
  419. #endregion Enums
  420. /// <summary>
  421. /// Handles all network traffic related to reading and writing group
  422. /// information
  423. /// </summary>
  424. public class GroupManager
  425. {
  426. #region Delegates
  427. /// <summary>The event subscribers. null if no subcribers</summary>
  428. private EventHandler<CurrentGroupsEventArgs> m_CurrentGroups;
  429. /// <summary>Raises the CurrentGroups event</summary>
  430. /// <param name="e">A CurrentGroupsEventArgs object containing the
  431. /// data sent from the simulator</param>
  432. protected virtual void OnCurrentGroups(CurrentGroupsEventArgs e)
  433. {
  434. EventHandler<CurrentGroupsEventArgs> handler = m_CurrentGroups;
  435. if (handler != null)
  436. handler(this, e);
  437. }
  438. /// <summary>Thread sync lock object</summary>
  439. private readonly object m_CurrentGroupsLock = new object();
  440. /// <summary>Raised when the simulator sends us data containing
  441. /// our current group membership</summary>
  442. public event EventHandler<CurrentGroupsEventArgs> CurrentGroups
  443. {
  444. add { lock (m_CurrentGroupsLock) { m_CurrentGroups += value; } }
  445. remove { lock (m_CurrentGroupsLock) { m_CurrentGroups -= value; } }
  446. }
  447. /// <summary>The event subscribers. null if no subcribers</summary>
  448. private EventHandler<GroupNamesEventArgs> m_GroupNames;
  449. /// <summary>Raises the GroupNamesReply event</summary>
  450. /// <param name="e">A GroupNamesEventArgs object containing the
  451. /// data response from the simulator</param>
  452. protected virtual void OnGroupNamesReply(GroupNamesEventArgs e)
  453. {
  454. EventHandler<GroupNamesEventArgs> handler = m_GroupNames;
  455. if (handler != null)
  456. handler(this, e);
  457. }
  458. /// <summary>Thread sync lock object</summary>
  459. private readonly object m_GroupNamesLock = new object();
  460. /// <summary>Raised when the simulator responds to a RequestGroupName
  461. /// or RequestGroupNames request</summary>
  462. public event EventHandler<GroupNamesEventArgs> GroupNamesReply
  463. {
  464. add { lock (m_GroupNamesLock) { m_GroupNames += value; } }
  465. remove { lock (m_GroupNamesLock) { m_GroupNames -= value; } }
  466. }
  467. /// <summary>The event subscribers. null if no subcribers</summary>
  468. private EventHandler<GroupProfileEventArgs> m_GroupProfile;
  469. /// <summary>Raises the GroupProfile event</summary>
  470. /// <param name="e">An GroupProfileEventArgs object containing the
  471. /// data returned from the simulator</param>
  472. protected virtual void OnGroupProfile(GroupProfileEventArgs e)
  473. {
  474. EventHandler<GroupProfileEventArgs> handler = m_GroupProfile;
  475. if (handler != null)
  476. handler(this, e);
  477. }
  478. /// <summary>Thread sync lock object</summary>
  479. private readonly object m_GroupProfileLock = new object();
  480. /// <summary>Raised when the simulator responds to a <see cref="RequestGroupProfile"/> request</summary>
  481. public event EventHandler<GroupProfileEventArgs> GroupProfile
  482. {
  483. add { lock (m_GroupProfileLock) { m_GroupProfile += value; } }
  484. remove { lock (m_GroupProfileLock) { m_GroupProfile -= value; } }
  485. }
  486. /// <summary>The event subscribers. null if no subcribers</summary>
  487. private EventHandler<GroupMembersReplyEventArgs> m_GroupMembers;
  488. /// <summary>Raises the GroupMembers event</summary>
  489. /// <param name="e">A GroupMembersEventArgs object containing the
  490. /// data returned from the simulator</param>
  491. protected virtual void OnGroupMembersReply(GroupMembersReplyEventArgs e)
  492. {
  493. EventHandler<GroupMembersReplyEventArgs> handler = m_GroupMembers;
  494. if (handler != null)
  495. handler(this, e);
  496. }
  497. /// <summary>Thread sync lock object</summary>
  498. private readonly object m_GroupMembersLock = new object();
  499. /// <summary>Raised when the simulator responds to a <see cref="RequestGroupMembers"/> request</summary>
  500. public event EventHandler<GroupMembersReplyEventArgs> GroupMembersReply
  501. {
  502. add { lock (m_GroupMembersLock) { m_GroupMembers += value; } }
  503. remove { lock (m_GroupMembersLock) { m_GroupMembers -= value; } }
  504. }
  505. /// <summary>The event subscribers. null if no subcribers</summary>
  506. private EventHandler<GroupRolesDataReplyEventArgs> m_GroupRoles;
  507. /// <summary>Raises the GroupRolesDataReply event</summary>
  508. /// <param name="e">A GroupRolesDataReplyEventArgs object containing the
  509. /// data returned from the simulator</param>
  510. protected virtual void OnGroupRoleDataReply(GroupRolesDataReplyEventArgs e)
  511. {
  512. EventHandler<GroupRolesDataReplyEventArgs> handler = m_GroupRoles;
  513. if (handler != null)
  514. handler(this, e);
  515. }
  516. /// <summary>Thread sync lock object</summary>
  517. private readonly object m_GroupRolesLock = new object();
  518. /// <summary>Raised when the simulator responds to a <see cref="RequestGroupRoleData"/> request</summary>
  519. public event EventHandler<GroupRolesDataReplyEventArgs> GroupRoleDataReply
  520. {
  521. add { lock (m_GroupRolesLock) { m_GroupRoles += value; } }
  522. remove { lock (m_GroupRolesLock) { m_GroupRoles -= value; } }
  523. }
  524. /// <summary>The event subscribers. null if no subcribers</summary>
  525. private EventHandler<GroupRolesMembersReplyEventArgs> m_GroupRoleMembers;
  526. /// <summary>Raises the GroupRoleMembersReply event</summary>
  527. /// <param name="e">A GroupRolesRoleMembersReplyEventArgs object containing the
  528. /// data returned from the simulator</param>
  529. protected virtual void OnGroupRoleMembers(GroupRolesMembersReplyEventArgs e)
  530. {
  531. EventHandler<GroupRolesMembersReplyEventArgs> handler = m_GroupRoleMembers;
  532. if (handler != null)
  533. handler(this, e);
  534. }
  535. /// <summary>Thread sync lock object</summary>
  536. private readonly object m_GroupRolesMembersLock = new object();
  537. /// <summary>Raised when the simulator responds to a <see cref="RequestGroupRolesMembers"/> request</summary>
  538. public event EventHandler<GroupRolesMembersReplyEventArgs> GroupRoleMembersReply
  539. {
  540. add { lock (m_GroupRolesMembersLock) { m_GroupRoleMembers += value; } }
  541. remove { lock (m_GroupRolesMembersLock) { m_GroupRoleMembers -= value; } }
  542. }
  543. /// <summary>The event subscribers. null if no subcribers</summary>
  544. private EventHandler<GroupTitlesReplyEventArgs> m_GroupTitles;
  545. /// <summary>Raises the GroupTitlesReply event</summary>
  546. /// <param name="e">A GroupTitlesReplyEventArgs object containing the
  547. /// data returned from the simulator</param>
  548. protected virtual void OnGroupTitles(GroupTitlesReplyEventArgs e)
  549. {
  550. EventHandler<GroupTitlesReplyEventArgs> handler = m_GroupTitles;
  551. if (handler != null)
  552. handler(this, e);
  553. }
  554. /// <summary>Thread sync lock object</summary>
  555. private readonly object m_GroupTitlesLock = new object();
  556. /// <summary>Raised when the simulator responds to a <see cref="RequestGroupTitles"/> request</summary>
  557. public event EventHandler<GroupTitlesReplyEventArgs> GroupTitlesReply
  558. {
  559. add { lock (m_GroupTitlesLock) { m_GroupTitles += value; } }
  560. remove { lock (m_GroupTitlesLock) { m_GroupTitles -= value; } }
  561. }
  562. /// <summary>The event subscribers. null if no subcribers</summary>
  563. private EventHandler<GroupAccountSummaryReplyEventArgs> m_GroupAccountSummary;
  564. /// <summary>Raises the GroupAccountSummary event</summary>
  565. /// <param name="e">A GroupAccountSummaryReplyEventArgs object containing the
  566. /// data returned from the simulator</param>
  567. protected virtual void OnGroupAccountSummaryReply(GroupAccountSummaryReplyEventArgs e)
  568. {
  569. EventHandler<GroupAccountSummaryReplyEventArgs> handler = m_GroupAccountSummary;
  570. if (handler != null)
  571. handler(this, e);
  572. }
  573. /// <summary>Thread sync lock object</summary>
  574. private readonly object m_GroupAccountSummaryLock = new object();
  575. /// <summary>Raised when a response to a RequestGroupAccountSummary is returned
  576. /// by the simulator</summary>
  577. public event EventHandler<GroupAccountSummaryReplyEventArgs> GroupAccountSummaryReply
  578. {
  579. add { lock (m_GroupAccountSummaryLock) { m_GroupAccountSummary += value; } }
  580. remove { lock (m_GroupAccountSummaryLock) { m_GroupAccountSummary -= value; } }
  581. }
  582. /// <summary>The event subscribers. null if no subcribers</summary>
  583. private EventHandler<GroupCreatedReplyEventArgs> m_GroupCreated;
  584. /// <summary>Raises the GroupCreated event</summary>
  585. /// <param name="e">An GroupCreatedEventArgs object containing the
  586. /// data returned from the simulator</param>
  587. protected virtual void OnGroupCreatedReply(GroupCreatedReplyEventArgs e)
  588. {
  589. EventHandler<GroupCreatedReplyEventArgs> handler = m_GroupCreated;
  590. if (handler != null)
  591. handler(this, e);
  592. }
  593. /// <summary>Thread sync lock object</summary>
  594. private readonly object m_GroupCreatedLock = new object();
  595. /// <summary>Raised when a request to create a group is successful</summary>
  596. public event EventHandler<GroupCreatedReplyEventArgs> GroupCreatedReply
  597. {
  598. add { lock (m_GroupCreatedLock) { m_GroupCreated += value; } }
  599. remove { lock (m_GroupCreatedLock) { m_GroupCreated -= value; } }
  600. }
  601. /// <summary>The event subscribers. null if no subcribers</summary>
  602. private EventHandler<GroupOperationEventArgs> m_GroupJoined;
  603. /// <summary>Raises the GroupJoined event</summary>
  604. /// <param name="e">A GroupOperationEventArgs object containing the
  605. /// result of the operation returned from the simulator</param>
  606. protected virtual void OnGroupJoinedReply(GroupOperationEventArgs e)
  607. {
  608. EventHandler<GroupOperationEventArgs> handler = m_GroupJoined;
  609. if (handler != null)
  610. handler(this, e);
  611. }
  612. /// <summary>Thread sync lock object</summary>
  613. private readonly object m_GroupJoinedLock = new object();
  614. /// <summary>Raised when a request to join a group either
  615. /// fails or succeeds</summary>
  616. public event EventHandler<GroupOperationEventArgs> GroupJoinedReply
  617. {
  618. add { lock (m_GroupJoinedLock) { m_GroupJoined += value; } }
  619. remove { lock (m_GroupJoinedLock) { m_GroupJoined -= value; } }
  620. }
  621. /// <summary>The event subscribers. null if no subcribers</summary>
  622. private EventHandler<GroupOperationEventArgs> m_GroupLeft;
  623. /// <summary>Raises the GroupLeft event</summary>
  624. /// <param name="e">A GroupOperationEventArgs object containing the
  625. /// result of the operation returned from the simulator</param>
  626. protected virtual void OnGroupLeaveReply(GroupOperationEventArgs e)
  627. {
  628. EventHandler<GroupOperationEventArgs> handler = m_GroupLeft;
  629. if (handler != null)
  630. handler(this, e);
  631. }
  632. /// <summary>Thread sync lock object</summary>
  633. private readonly object m_GroupLeftLock = new object();
  634. /// <summary>Raised when a request to leave a group either
  635. /// fails or succeeds</summary>
  636. public event EventHandler<GroupOperationEventArgs> GroupLeaveReply
  637. {
  638. add { lock (m_GroupLeftLock) { m_GroupLeft += value; } }
  639. remove { lock (m_GroupLeftLock) { m_GroupLeft -= value; } }
  640. }
  641. /// <summary>The event subscribers. null if no subcribers</summary>
  642. private EventHandler<GroupDroppedEventArgs> m_GroupDropped;
  643. /// <summary>Raises the GroupDropped event</summary>
  644. /// <param name="e">An GroupDroppedEventArgs object containing the
  645. /// the group your agent left</param>
  646. protected virtual void OnGroupDropped(GroupDroppedEventArgs e)
  647. {
  648. EventHandler<GroupDroppedEventArgs> handler = m_GroupDropped;
  649. if (handler != null)
  650. handler(this, e);
  651. }
  652. /// <summary>Thread sync lock object</summary>
  653. private readonly object m_GroupDroppedLock = new object();
  654. /// <summary>Raised when A group is removed from the group server</summary>
  655. public event EventHandler<GroupDroppedEventArgs> GroupDropped
  656. {
  657. add { lock (m_GroupDroppedLock) { m_GroupDropped += value; } }
  658. remove { lock (m_GroupDroppedLock) { m_GroupDropped -= value; } }
  659. }
  660. /// <summary>The event subscribers. null if no subcribers</summary>
  661. private EventHandler<GroupOperationEventArgs> m_GroupMemberEjected;
  662. /// <summary>Raises the GroupMemberEjected event</summary>
  663. /// <param name="e">An GroupMemberEjectedEventArgs object containing the
  664. /// data returned from the simulator</param>
  665. protected virtual void OnGroupMemberEjected(GroupOperationEventArgs e)
  666. {
  667. EventHandler<GroupOperationEventArgs> handler = m_GroupMemberEjected;
  668. if (handler != null)
  669. handler(this, e);
  670. }
  671. /// <summary>Thread sync lock object</summary>
  672. private readonly object m_GroupMemberEjectedLock = new object();
  673. /// <summary>Raised when a request to eject a member from a group either
  674. /// fails or succeeds</summary>
  675. public event EventHandler<GroupOperationEventArgs> GroupMemberEjected
  676. {
  677. add { lock (m_GroupMemberEjectedLock) { m_GroupMemberEjected += value; } }
  678. remove { lock (m_GroupMemberEjectedLock) { m_GroupMemberEjected -= value; } }
  679. }
  680. /// <summary>The event subscribers. null if no subcribers</summary>
  681. private EventHandler<GroupNoticesListReplyEventArgs> m_GroupNoticesListReply;
  682. /// <summary>Raises the GroupNoticesListReply event</summary>
  683. /// <param name="e">An GroupNoticesListReplyEventArgs object containing the
  684. /// data returned from the simulator</param>
  685. protected virtual void OnGroupNoticesListReply(GroupNoticesListReplyEventArgs e)
  686. {
  687. EventHandler<GroupNoticesListReplyEventArgs> handler = m_GroupNoticesListReply;
  688. if (handler != null)
  689. handler(this, e);
  690. }
  691. /// <summary>Thread sync lock object</summary>
  692. private readonly object m_GroupNoticesListReplyLock = new object();
  693. /// <summary>Raised when the simulator sends us group notices</summary>
  694. /// <seealso cref="RequestGroupNoticesList"/>
  695. public event EventHandler<GroupNoticesListReplyEventArgs> GroupNoticesListReply
  696. {
  697. add { lock (m_GroupNoticesListReplyLock) { m_GroupNoticesListReply += value; } }
  698. remove { lock (m_GroupNoticesListReplyLock) { m_GroupNoticesListReply -= value; } }
  699. }
  700. /// <summary>The event subscribers. null if no subcribers</summary>
  701. private EventHandler<GroupInvitationEventArgs> m_GroupInvitation;
  702. /// <summary>Raises the GroupInvitation event</summary>
  703. /// <param name="e">An GroupInvitationEventArgs object containing the
  704. /// data returned from the simulator</param>
  705. protected virtual void OnGroupInvitation(GroupInvitationEventArgs e)
  706. {
  707. EventHandler<GroupInvitationEventArgs> handler = m_GroupInvitation;
  708. if (handler != null)
  709. handler(this, e);
  710. }
  711. /// <summary>Thread sync lock object</summary>
  712. private readonly object m_GroupInvitationLock = new object();
  713. /// <summary>Raised when another agent invites our avatar to join a group</summary>
  714. public event EventHandler<GroupInvitationEventArgs> GroupInvitation
  715. {
  716. add { lock (m_GroupInvitationLock) { m_GroupInvitation += value; } }
  717. remove { lock (m_GroupInvitationLock) { m_GroupInvitation -= value; } }
  718. }
  719. #endregion Delegates
  720. #region Events
  721. #endregion Events
  722. /// <summary>A reference to the current <seealso cref="GridClient"/> instance</summary>
  723. private GridClient Client;
  724. /// <summary>Currently-active group members requests</summary>
  725. private List<UUID> GroupMembersRequests;
  726. /// <summary>Currently-active group roles requests</summary>
  727. private List<UUID> GroupRolesRequests;
  728. /// <summary>Currently-active group role-member requests</summary>
  729. private List<UUID> GroupRolesMembersRequests;
  730. /// <summary>Dictionary keeping group members while request is in progress</summary>
  731. private InternalDictionary<UUID, Dictionary<UUID, GroupMember>> TempGroupMembers;
  732. /// <summary>Dictionary keeping mebmer/role mapping while request is in progress</summary>
  733. private InternalDictionary<UUID, List<KeyValuePair<UUID, UUID>>> TempGroupRolesMembers;
  734. /// <summary>Dictionary keeping GroupRole information while request is in progress</summary>
  735. private InternalDictionary<UUID, Dictionary<UUID, GroupRole>> TempGroupRoles;
  736. /// <summary>Caches group name lookups</summary>
  737. public InternalDictionary<UUID, string> GroupName2KeyCache;
  738. /// <summary>
  739. /// Construct a new instance of the GroupManager class
  740. /// </summary>
  741. /// <param name="client">A reference to the current <seealso cref="GridClient"/> instance</param>
  742. public GroupManager(GridClient client)
  743. {
  744. Client = client;
  745. TempGroupMembers = new InternalDictionary<UUID, Dictionary<UUID, GroupMember>>();
  746. GroupMembersRequests = new List<UUID>();
  747. TempGroupRoles = new InternalDictionary<UUID, Dictionary<UUID, GroupRole>>();
  748. GroupRolesRequests = new List<UUID>();
  749. TempGroupRolesMembers = new InternalDictionary<UUID, List<KeyValuePair<UUID, UUID>>>();
  750. GroupRolesMembersRequests = new List<UUID>();
  751. GroupName2KeyCache = new InternalDictionary<UUID, string>();
  752. Client.Self.IM += Self_IM;
  753. Client.Network.RegisterEventCallback("AgentGroupDataUpdate", new Caps.EventQueueCallback(AgentGroupDataUpdateMessageHandler));
  754. // deprecated in simulator v1.27
  755. Client.Network.RegisterCallback(PacketType.AgentDropGroup, AgentDropGroupHandler);
  756. Client.Network.RegisterCallback(PacketType.GroupTitlesReply, GroupTitlesReplyHandler);
  757. Client.Network.RegisterCallback(PacketType.GroupProfileReply, GroupProfileReplyHandler);
  758. Client.Network.RegisterCallback(PacketType.GroupMembersReply, GroupMembersHandler);
  759. Client.Network.RegisterCallback(PacketType.GroupRoleDataReply, GroupRoleDataReplyHandler);
  760. Client.Network.RegisterCallback(PacketType.GroupRoleMembersReply, GroupRoleMembersReplyHandler);
  761. Client.Network.RegisterCallback(PacketType.GroupActiveProposalItemReply, GroupActiveProposalItemHandler);
  762. Client.Network.RegisterCallback(PacketType.GroupVoteHistoryItemReply, GroupVoteHistoryItemHandler);
  763. Client.Network.RegisterCallback(PacketType.GroupAccountSummaryReply, GroupAccountSummaryReplyHandler);
  764. Client.Network.RegisterCallback(PacketType.CreateGroupReply, CreateGroupReplyHandler);
  765. Client.Network.RegisterCallback(PacketType.JoinGroupReply, JoinGroupReplyHandler);
  766. Client.Network.RegisterCallback(PacketType.LeaveGroupReply, LeaveGroupReplyHandler);
  767. Client.Network.RegisterCallback(PacketType.UUIDGroupNameReply, UUIDGroupNameReplyHandler);
  768. Client.Network.RegisterCallback(PacketType.EjectGroupMemberReply, EjectGroupMemberReplyHandler);
  769. Client.Network.RegisterCallback(PacketType.GroupNoticesListReply, GroupNoticesListReplyHandler);
  770. Client.Network.RegisterEventCallback("AgentDropGroup", new Caps.EventQueueCallback(AgentDropGroupMessageHandler));
  771. }
  772. void Self_IM(object sender, InstantMessageEventArgs e)
  773. {
  774. if(m_GroupInvitation != null && e.IM.Dialog == InstantMessageDialog.GroupInvitation)
  775. {
  776. GroupInvitationEventArgs args = new GroupInvitationEventArgs(e.Simulator, e.IM.FromAgentID, e.IM.FromAgentName, e.IM.Message);
  777. OnGroupInvitation(args);
  778. if (args.Accept)
  779. {
  780. Client.Self.InstantMessage("name", e.IM.FromAgentID, "message", e.IM.IMSessionID, InstantMessageDialog.GroupInvitationAccept,
  781. InstantMessageOnline.Online, Client.Self.SimPosition, UUID.Zero, Utils.EmptyBytes);
  782. }
  783. else
  784. {
  785. Client.Self.InstantMessage("name", e.IM.FromAgentID, "message", e.IM.IMSessionID, InstantMessageDialog.GroupInvitationDecline,
  786. InstantMessageOnline.Online, Client.Self.SimPosition, UUID.Zero, new byte[1] { 0 });
  787. }
  788. }
  789. }
  790. #region Public Methods
  791. /// <summary>
  792. /// Request a current list of groups the avatar is a member of.
  793. /// </summary>
  794. /// <remarks>CAPS Event Queue must be running for this to work since the results
  795. /// come across CAPS.</remarks>
  796. public void RequestCurrentGroups()
  797. {
  798. AgentDataUpdateRequestPacket request = new AgentDataUpdateRequestPacket();
  799. request.AgentData.AgentID = Client.Self.AgentID;
  800. request.AgentData.SessionID = Client.Self.SessionID;
  801. Client.Network.SendPacket(request);
  802. }
  803. /// <summary>
  804. /// Lookup name of group based on groupID
  805. /// </summary>
  806. /// <param name="groupID">groupID of group to lookup name for.</param>
  807. public void RequestGroupName(UUID groupID)
  808. {
  809. // if we already have this in the cache, return from cache instead of making a request
  810. if (GroupName2KeyCache.ContainsKey(groupID))
  811. {
  812. Dictionary<UUID, string> groupNames = new Dictionary<UUID, string>();
  813. lock (GroupName2KeyCache.Dictionary)
  814. groupNames.Add(groupID, GroupName2KeyCache.Dictionary[groupID]);
  815. if (m_GroupNames != null)
  816. {
  817. OnGroupNamesReply(new GroupNamesEventArgs(groupNames));
  818. }
  819. }
  820. else
  821. {
  822. UUIDGroupNameRequestPacket req = new UUIDGroupNameRequestPacket();
  823. UUIDGroupNameRequestPacket.UUIDNameBlockBlock[] block = new UUIDGroupNameRequestPacket.UUIDNameBlockBlock[1];
  824. block[0] = new UUIDGroupNameRequestPacket.UUIDNameBlockBlock();
  825. block[0].ID = groupID;
  826. req.UUIDNameBlock = block;
  827. Client.Network.SendPacket(req);
  828. }
  829. }
  830. /// <summary>
  831. /// Request lookup of multiple group names
  832. /// </summary>
  833. /// <param name="groupIDs">List of group IDs to request.</param>
  834. public void RequestGroupNames(List<UUID> groupIDs)
  835. {
  836. Dictionary<UUID, string> groupNames = new Dictionary<UUID, string>();
  837. lock (GroupName2KeyCache.Dictionary)
  838. {
  839. foreach (UUID groupID in groupIDs)
  840. {
  841. if (GroupName2KeyCache.ContainsKey(groupID))
  842. groupNames[groupID] = GroupName2KeyCache.Dictionary[groupID];
  843. }
  844. }
  845. if (groupIDs.Count > 0)
  846. {
  847. UUIDGroupNameRequestPacket req = new UUIDGroupNameRequestPacket();
  848. UUIDGroupNameRequestPacket.UUIDNameBlockBlock[] block = new UUIDGroupNameRequestPacket.UUIDNameBlockBlock[groupIDs.Count];
  849. for (int i = 0; i < groupIDs.Count; i++)
  850. {
  851. block[i] = new UUIDGroupNameRequestPacket.UUIDNameBlockBlock();
  852. block[i].ID = groupIDs[i];
  853. }
  854. req.UUIDNameBlock = block;
  855. Client.Network.SendPacket(req);
  856. }
  857. // fire handler from cache
  858. if (groupNames.Count > 0 && m_GroupNames != null)
  859. {
  860. OnGroupNamesReply(new GroupNamesEventArgs(groupNames));
  861. }
  862. }
  863. /// <summary>Lookup group profile data such as name, enrollment, founder, logo, etc</summary>
  864. /// <remarks>Subscribe to <code>OnGroupProfile</code> event to receive the results.</remarks>
  865. /// <param name="group">group ID (UUID)</param>
  866. public void RequestGroupProfile(UUID group)
  867. {
  868. GroupProfileRequestPacket request = new GroupProfileRequestPacket();
  869. request.AgentData.AgentID = Client.Self.AgentID;
  870. request.AgentData.SessionID = Client.Self.SessionID;
  871. request.GroupData.GroupID = group;
  872. Client.Network.SendPacket(request);
  873. }
  874. /// <summary>Request a list of group members.</summary>
  875. /// <remarks>Subscribe to <code>OnGroupMembers</code> event to receive the results.</remarks>
  876. /// <param name="group">group ID (UUID)</param>
  877. /// <returns>UUID of the request, use to index into cache</returns>
  878. public UUID RequestGroupMembers(UUID group)
  879. {
  880. UUID requestID = UUID.Random();
  881. lock (GroupMembersRequests) GroupMembersRequests.Add(requestID);
  882. GroupMembersRequestPacket request = new GroupMembersRequestPacket();
  883. request.AgentData.AgentID = Client.Self.AgentID;
  884. request.AgentData.SessionID = Client.Self.SessionID;
  885. request.GroupData.GroupID = group;
  886. request.GroupData.RequestID = requestID;
  887. Client.Network.SendPacket(request);
  888. return requestID;
  889. }
  890. /// <summary>Request group roles</summary>
  891. /// <remarks>Subscribe to <code>OnGroupRoles</code> event to receive the results.</remarks>
  892. /// <param name="group">group ID (UUID)</param>
  893. /// <returns>UUID of the request, use to index into cache</returns>
  894. public UUID RequestGroupRoles(UUID group)
  895. {
  896. UUID requestID = UUID.Random();
  897. lock (GroupRolesRequests) GroupRolesRequests.Add(requestID);
  898. GroupRoleDataRequestPacket request = new GroupRoleDataRequestPacket();
  899. request.AgentData.AgentID = Client.Self.AgentID;
  900. request.AgentData.SessionID = Client.Self.SessionID;
  901. request.GroupData.GroupID = group;
  902. request.GroupData.RequestID = requestID;
  903. Client.Network.SendPacket(request);
  904. return requestID;
  905. }
  906. /// <summary>Request members (members,role) role mapping for a group.</summary>
  907. /// <remarks>Subscribe to <code>OnGroupRolesMembers</code> event to receive the results.</remarks>
  908. /// <param name="group">group ID (UUID)</param>
  909. /// <returns>UUID of the request, use to index into cache</returns>
  910. public UUID RequestGroupRolesMembers(UUID group)
  911. {
  912. UUID requestID = UUID.Random();
  913. lock (GroupRolesRequests) GroupRolesMembersRequests.Add(requestID);
  914. GroupRoleMembersRequestPacket request = new GroupRoleMembersRequestPacket();
  915. request.AgentData.AgentID = Client.Self.AgentID;
  916. request.AgentData.SessionID = Client.Self.SessionID;
  917. request.GroupData.GroupID = group;
  918. request.GroupData.RequestID = requestID;
  919. Client.Network.SendPacket(request);
  920. return requestID;
  921. }
  922. /// <summary>Request a groups Titles</summary>
  923. /// <remarks>Subscribe to <code>OnGroupTitles</code> event to receive the results.</remarks>
  924. /// <param name="group">group ID (UUID)</param>
  925. /// <returns>UUID of the request, use to index into cache</returns>
  926. public UUID RequestGroupTitles(UUID group)
  927. {
  928. UUID requestID = UUID.Random();
  929. GroupTitlesRequestPacket request = new GroupTitlesRequestPacket();
  930. request.AgentData.AgentID = Client.Self.AgentID;
  931. request.AgentData.SessionID = Client.Self.SessionID;
  932. request.AgentData.GroupID = group;
  933. request.AgentData.RequestID = requestID;
  934. Client.Network.SendPacket(request);
  935. return requestID;
  936. }
  937. /// <summary>Begin to get the group account summary</summary>
  938. /// <remarks>Subscribe to the <code>OnGroupAccountSummary</code> event to receive the results.</remarks>
  939. /// <param name="group">group ID (UUID)</param>
  940. /// <param name="intervalDays">How long of an interval</param>
  941. /// <param name="currentInterval">Which interval (0 for current, 1 for last)</param>
  942. public void RequestGroupAccountSummary(UUID group, int intervalDays, int currentInterval)
  943. {
  944. GroupAccountSummaryRequestPacket p = new GroupAccountSummaryRequestPacket();
  945. p.AgentData.AgentID = Client.Self.AgentID;
  946. p.AgentData.SessionID = Client.Self.SessionID;
  947. p.AgentData.GroupID = group;
  948. p.MoneyData.RequestID = UUID.Random();
  949. p.MoneyData.CurrentInterval = currentInterval;
  950. p.MoneyData.IntervalDays = intervalDays;
  951. Client.Network.SendPacket(p);
  952. }
  953. /// <summary>Invites a user to a group</summary>
  954. /// <param name="group">The group to invite to</param>
  955. /// <param name="roles">A list of roles to invite a person to</param>
  956. /// <param name="personkey">Key of person to invite</param>
  957. public void Invite(UUID group, List<UUID> roles, UUID personkey)
  958. {
  959. InviteGroupRequestPacket igp = new InviteGroupRequestPacket();
  960. igp.AgentData = new InviteGroupRequestPacket.AgentDataBlock();
  961. igp.AgentData.AgentID = Client.Self.AgentID;
  962. igp.AgentData.SessionID = Client.Self.SessionID;
  963. igp.GroupData = new InviteGroupRequestPacket.GroupDataBlock();
  964. igp.GroupData.GroupID = group;
  965. igp.InviteData = new InviteGroupRequestPacket.InviteDataBlock[roles.Count];
  966. for (int i = 0; i < roles.Count; i++)
  967. {
  968. igp.InviteData[i] = new InviteGroupRequestPacket.InviteDataBlock();
  969. igp.InviteData[i].InviteeID = personkey;
  970. igp.InviteData[i].RoleID = roles[i];
  971. }
  972. Client.Network.SendPacket(igp);
  973. }
  974. /// <summary>Set a group as the current active group</summary>
  975. /// <param name="id">group ID (UUID)</param>
  976. public void ActivateGroup(UUID id)
  977. {
  978. ActivateGroupPacket activate = new ActivateGroupPacket();
  979. activate.AgentData.AgentID = Client.Self.AgentID;
  980. activate.AgentData.SessionID = Client.Self.SessionID;
  981. activate.AgentData.GroupID = id;
  982. Client.Network.SendPacket(activate);
  983. }
  984. /// <summary>Change the role that determines your active title</summary>
  985. /// <param name="group">Group ID to use</param>
  986. /// <param name="role">Role ID to change to</param>
  987. public void ActivateTitle(UUID group, UUID role)
  988. {
  989. GroupTitleUpdatePacket gtu = new GroupTitleUpdatePacket();
  990. gtu.AgentData.AgentID = Client.Self.AgentID;
  991. gtu.AgentData.SessionID = Client.Self.SessionID;
  992. gtu.AgentData.TitleRoleID = role;
  993. gtu.AgentData.GroupID = group;
  994. Client.Network.SendPacket(gtu);
  995. }
  996. /// <summary>Set this avatar's tier contribution</summary>
  997. /// <param name="group">Group ID to change tier in</param>
  998. /// <param name="contribution">amount of tier to donate</param>
  999. public void SetGroupContribution(UUID group, int contribution)
  1000. {
  1001. SetGroupContributionPacket sgp = new SetGroupContributionPacket();
  1002. sgp.AgentData.AgentID = Client.Self.AgentID;
  1003. sgp.AgentData.SessionID = Client.Self.SessionID;
  1004. sgp.Data.GroupID = group;
  1005. sgp.Data.Contribution = contribution;
  1006. Client.Network.SendPacket(sgp);
  1007. }
  1008. /// <summary>
  1009. /// Save wheather agent wants to accept group notices and list this group in their profile
  1010. /// </summary>
  1011. /// <param name="groupID">Group <see cref="UUID"/></param>
  1012. /// <param name="acceptNotices">Accept notices from this group</param>
  1013. /// <param name="listInProfile">List this group in the profile</param>
  1014. public void SetGroupAcceptNotices(UUID groupID, bool acceptNotices, bool listInProfile)
  1015. {
  1016. SetGrou

Large files files are truncated, but you can click here to view the full file