corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) 2006-2014, openmetaverse.org
3 * All rights reserved.
4 *
5 * - Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * - Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * - Neither the name of the openmetaverse.org nor the names
11 * of its contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26  
27 using System;
28 using System.Collections.Generic;
29 using OpenMetaverse.Packets;
30 using OpenMetaverse.StructuredData;
31 using OpenMetaverse.Messages.Linden;
32 using OpenMetaverse.Interfaces;
33 using OpenMetaverse.Http;
34  
35 namespace OpenMetaverse
36 {
37 #region Structs
38  
39 /// <summary>
40 /// Avatar group management
41 /// </summary>
42 public struct GroupMember
43 {
44 /// <summary>Key of Group Member</summary>
45 public UUID ID;
46 /// <summary>Total land contribution</summary>
47 public int Contribution;
48 /// <summary>Online status information</summary>
49 public string OnlineStatus;
50 /// <summary>Abilities that the Group Member has</summary>
51 public GroupPowers Powers;
52 /// <summary>Current group title</summary>
53 public string Title;
54 /// <summary>Is a group owner</summary>
55 public bool IsOwner;
56 }
57  
58 /// <summary>
59 /// Role manager for a group
60 /// </summary>
61 public struct GroupRole
62 {
63 /// <summary>Key of the group</summary>
64 public UUID GroupID;
65 /// <summary>Key of Role</summary>
66 public UUID ID;
67 /// <summary>Name of Role</summary>
68 public string Name;
69 /// <summary>Group Title associated with Role</summary>
70 public string Title;
71 /// <summary>Description of Role</summary>
72 public string Description;
73 /// <summary>Abilities Associated with Role</summary>
74 public GroupPowers Powers;
75 /// <summary>Returns the role's title</summary>
76 /// <returns>The role's title</returns>
77 public override string ToString()
78 {
79 return Name;
80 }
81 }
82  
83 /// <summary>
84 /// Class to represent Group Title
85 /// </summary>
86 public struct GroupTitle
87 {
88 /// <summary>Key of the group</summary>
89 public UUID GroupID;
90 /// <summary>ID of the role title belongs to</summary>
91 public UUID RoleID;
92 /// <summary>Group Title</summary>
93 public string Title;
94 /// <summary>Whether title is Active</summary>
95 public bool Selected;
96 /// <summary>Returns group title</summary>
97 public override string ToString()
98 {
99 return Title;
100 }
101 }
102  
103 /// <summary>
104 /// Represents a group on the grid
105 /// </summary>
106 public struct Group
107 {
108 /// <summary>Key of Group</summary>
109 public UUID ID;
110 /// <summary>Key of Group Insignia</summary>
111 public UUID InsigniaID;
112 /// <summary>Key of Group Founder</summary>
113 public UUID FounderID;
114 /// <summary>Key of Group Role for Owners</summary>
115 public UUID OwnerRole;
116 /// <summary>Name of Group</summary>
117 public string Name;
118 /// <summary>Text of Group Charter</summary>
119 public string Charter;
120 /// <summary>Title of "everyone" role</summary>
121 public string MemberTitle;
122 /// <summary>Is the group open for enrolement to everyone</summary>
123 public bool OpenEnrollment;
124 /// <summary>Will group show up in search</summary>
125 public bool ShowInList;
126 /// <summary></summary>
127 public GroupPowers Powers;
128 /// <summary></summary>
129 public bool AcceptNotices;
130 /// <summary></summary>
131 public bool AllowPublish;
132 /// <summary>Is the group Mature</summary>
133 public bool MaturePublish;
134 /// <summary>Cost of group membership</summary>
135 public int MembershipFee;
136 /// <summary></summary>
137 public int Money;
138 /// <summary></summary>
139 public int Contribution;
140 /// <summary>The total number of current members this group has</summary>
141 public int GroupMembershipCount;
142 /// <summary>The number of roles this group has configured</summary>
143 public int GroupRolesCount;
144 /// <summary>Show this group in agent's profile</summary>
145 public bool ListInProfile;
146  
147 /// <summary>Returns the name of the group</summary>
148 /// <returns>A string containing the name of the group</returns>
149 public override string ToString()
150 {
151 return Name;
152 }
153 }
154  
155 /// <summary>
156 /// A group Vote
157 /// </summary>
158 public struct Vote
159 {
160 /// <summary>Key of Avatar who created Vote</summary>
161 public UUID Candidate;
162 /// <summary>Text of the Vote proposal</summary>
163 public string VoteString;
164 /// <summary>Total number of votes</summary>
165 public int NumVotes;
166 }
167  
168 /// <summary>
169 /// A group proposal
170 /// </summary>
171 public struct GroupProposal
172 {
173 /// <summary>The Text of the proposal</summary>
174 public string VoteText;
175 /// <summary>The minimum number of members that must vote before proposal passes or failes</summary>
176 public int Quorum;
177 /// <summary>The required ration of yes/no votes required for vote to pass</summary>
178 /// <remarks>The three options are Simple Majority, 2/3 Majority, and Unanimous</remarks>
179 /// TODO: this should be an enum
180 public float Majority;
181 /// <summary>The duration in days votes are accepted</summary>
182 public int Duration;
183 }
184  
185 /// <summary>
186 ///
187 /// </summary>
188 public struct GroupAccountSummary
189 {
190 /// <summary></summary>
191 public int IntervalDays;
192 /// <summary></summary>
193 public int CurrentInterval;
194 /// <summary></summary>
195 public string StartDate;
196 /// <summary></summary>
197 public int Balance;
198 /// <summary></summary>
199 public int TotalCredits;
200 /// <summary></summary>
201 public int TotalDebits;
202 /// <summary></summary>
203 public int ObjectTaxCurrent;
204 /// <summary></summary>
205 public int LightTaxCurrent;
206 /// <summary></summary>
207 public int LandTaxCurrent;
208 /// <summary></summary>
209 public int GroupTaxCurrent;
210 /// <summary></summary>
211 public int ParcelDirFeeCurrent;
212 /// <summary></summary>
213 public int ObjectTaxEstimate;
214 /// <summary></summary>
215 public int LightTaxEstimate;
216 /// <summary></summary>
217 public int LandTaxEstimate;
218 /// <summary></summary>
219 public int GroupTaxEstimate;
220 /// <summary></summary>
221 public int ParcelDirFeeEstimate;
222 /// <summary></summary>
223 public int NonExemptMembers;
224 /// <summary></summary>
225 public string LastTaxDate;
226 /// <summary></summary>
227 public string TaxDate;
228 }
229  
230 /// <summary>
231 /// Struct representing a group notice
232 /// </summary>
233 public struct GroupNotice
234 {
235 /// <summary></summary>
236 public string Subject;
237 /// <summary></summary>
238 public string Message;
239 /// <summary></summary>
240 public UUID AttachmentID;
241 /// <summary></summary>
242 public UUID OwnerID;
243  
244 /// <summary>
245 ///
246 /// </summary>
247 /// <returns></returns>
248 public byte[] SerializeAttachment()
249 {
250 if (OwnerID == UUID.Zero || AttachmentID == UUID.Zero)
251 return Utils.EmptyBytes;
252  
253 OpenMetaverse.StructuredData.OSDMap att = new OpenMetaverse.StructuredData.OSDMap();
254 att.Add("item_id", OpenMetaverse.StructuredData.OSD.FromUUID(AttachmentID));
255 att.Add("owner_id", OpenMetaverse.StructuredData.OSD.FromUUID(OwnerID));
256  
257 return OpenMetaverse.StructuredData.OSDParser.SerializeLLSDXmlBytes(att);
258  
259 /*
260 //I guess this is how this works, no gaurentees
261 string lsd = "<llsd><item_id>" + AttachmentID.ToString() + "</item_id><owner_id>"
262 + OwnerID.ToString() + "</owner_id></llsd>";
263 return Utils.StringToBytes(lsd);
264 */
265 }
266 }
267  
268 /// <summary>
269 /// Struct representing a group notice list entry
270 /// </summary>
271 public struct GroupNoticesListEntry
272 {
273 /// <summary>Notice ID</summary>
274 public UUID NoticeID;
275 /// <summary>Creation timestamp of notice</summary>
276 public uint Timestamp;
277 /// <summary>Agent name who created notice</summary>
278 public string FromName;
279 /// <summary>Notice subject</summary>
280 public string Subject;
281 /// <summary>Is there an attachment?</summary>
282 public bool HasAttachment;
283 /// <summary>Attachment Type</summary>
284 public AssetType AssetType;
285  
286 }
287  
288 /// <summary>
289 /// Struct representing a member of a group chat session and their settings
290 /// </summary>
291 public struct ChatSessionMember
292 {
293 /// <summary>The <see cref="UUID"/> of the Avatar</summary>
294 public UUID AvatarKey;
295 /// <summary>True if user has voice chat enabled</summary>
296 public bool CanVoiceChat;
297 /// <summary>True of Avatar has moderator abilities</summary>
298 public bool IsModerator;
299 /// <summary>True if a moderator has muted this avatars chat</summary>
300 public bool MuteText;
301 /// <summary>True if a moderator has muted this avatars voice</summary>
302 public bool MuteVoice;
303 }
304  
305 #endregion Structs
306  
307 #region Enums
308  
309 /// <summary>
310 /// Role update flags
311 /// </summary>
312 public enum GroupRoleUpdate : uint
313 {
314 /// <summary></summary>
315 NoUpdate,
316 /// <summary></summary>
317 UpdateData,
318 /// <summary></summary>
319 UpdatePowers,
320 /// <summary></summary>
321 UpdateAll,
322 /// <summary></summary>
323 Create,
324 /// <summary></summary>
325 Delete
326 }
327  
328 [Flags]
329 public enum GroupPowers : ulong
330 {
331 /// <summary></summary>
332 None = 0,
333  
334 // Membership
335 /// <summary>Can send invitations to groups default role</summary>
336 Invite = 1UL << 1,
337 /// <summary>Can eject members from group</summary>
338 Eject = 1UL << 2,
339 /// <summary>Can toggle 'Open Enrollment' and change 'Signup fee'</summary>
340 ChangeOptions = 1UL << 3,
341 /// <summary>Member is visible in the public member list</summary>
342 MemberVisible = 1UL << 47,
343  
344 // Roles
345 /// <summary>Can create new roles</summary>
346 CreateRole = 1UL << 4,
347 /// <summary>Can delete existing roles</summary>
348 DeleteRole = 1UL << 5,
349 /// <summary>Can change Role names, titles and descriptions</summary>
350 RoleProperties = 1UL << 6,
351 /// <summary>Can assign other members to assigners role</summary>
352 AssignMemberLimited = 1UL << 7,
353 /// <summary>Can assign other members to any role</summary>
354 AssignMember = 1UL << 8,
355 /// <summary>Can remove members from roles</summary>
356 RemoveMember = 1UL << 9,
357 /// <summary>Can assign and remove abilities in roles</summary>
358 ChangeActions = 1UL << 10,
359  
360 // Identity
361 /// <summary>Can change group Charter, Insignia, 'Publish on the web' and which
362 /// members are publicly visible in group member listings</summary>
363 ChangeIdentity = 1UL << 11,
364  
365 // Parcel management
366 /// <summary>Can buy land or deed land to group</summary>
367 LandDeed = 1UL << 12,
368 /// <summary>Can abandon group owned land to Governor Linden on mainland, or Estate owner for
369 /// private estates</summary>
370 LandRelease = 1UL << 13,
371 /// <summary>Can set land for-sale information on group owned parcels</summary>
372 LandSetSale = 1UL << 14,
373 /// <summary>Can subdivide and join parcels</summary>
374 LandDivideJoin = 1UL << 15,
375  
376 // Parcel settings
377 /// <summary>Can change music and media settings</summary>
378 ChangeMedia = 1UL << 20,
379 /// <summary>Can toggle 'Edit Terrain' option in Land settings</summary>
380 LandEdit = 1UL << 21,
381 /// <summary>Can toggle various About Land > Options settings</summary>
382 LandOptions = 1UL << 22,
383  
384 // Parcel identity
385 /// <summary>Can toggle "Show in Find Places" and set search category</summary>
386 FindPlaces = 1UL << 17,
387 /// <summary>Can change parcel name, description, and 'Publish on web' settings</summary>
388 LandChangeIdentity = 1UL << 18,
389 /// <summary>Can set the landing point and teleport routing on group land</summary>
390 SetLandingPoint = 1UL << 19,
391  
392 // Parcel powers
393 /// <summary>Can always terraform land, even if parcel settings have it turned off</summary>
394 AllowEditLand = 1UL << 23,
395 /// <summary>Can always fly while over group owned land</summary>
396 AllowFly = 1UL << 24,
397 /// <summary>Can always rez objects on group owned land</summary>
398 AllowRez = 1UL << 25,
399 /// <summary>Can always create landmarks for group owned parcels</summary>
400 AllowLandmark = 1UL << 26,
401 /// <summary>Can set home location on any group owned parcel</summary>
402 AllowSetHome = 1UL << 28,
403 /// <summary>Allowed to hold events on group-owned land</summary>
404 HostEvent = 1UL << 41,
405  
406 // Parcel access
407 /// <summary>Can modify public access settings for group owned parcels</summary>
408 LandManageAllowed = 1UL << 29,
409 /// <summary>Can manager parcel ban lists on group owned land</summary>
410 LandManageBanned = 1UL << 30,
411 /// <summary>Can manage pass list sales information</summary>
412 LandManagePasses = 1UL << 31,
413 /// <summary>Can eject and freeze other avatars on group owned land</summary>
414 LandEjectAndFreeze = 1UL << 32,
415  
416 // Parcel content
417 /// <summary>Can return objects set to group</summary>
418 ReturnGroupSet = 1UL << 33,
419 /// <summary>Can return non-group owned/set objects</summary>
420 ReturnNonGroup = 1UL << 34,
421 /// <summary>Can return group owned objects</summary>
422 ReturnGroupOwned = 1UL << 48,
423 /// <summary>Can landscape using Linden plants</summary>
424 LandGardening = 1UL << 35,
425  
426 // Object Management
427 /// <summary>Can deed objects to group</summary>
428 DeedObject = 1UL << 36,
429 /// <summary>Can move group owned objects</summary>
430 ObjectManipulate = 1UL << 38,
431 /// <summary>Can set group owned objects for-sale</summary>
432 ObjectSetForSale = 1UL << 39,
433  
434 // Accounting
435 /// <summary>Pay group liabilities and receive group dividends</summary>
436 Accountable = 1UL << 40,
437  
438 // Notices and proposals
439 /// <summary>Can send group notices</summary>
440 SendNotices = 1UL << 42,
441 /// <summary>Can receive group notices</summary>
442 ReceiveNotices = 1UL << 43,
443 /// <summary>Can create group proposals</summary>
444 StartProposal = 1UL << 44,
445 /// <summary>Can vote on group proposals</summary>
446 VoteOnProposal = 1UL << 45,
447  
448 // Group chat moderation related
449 /// <summary>Can join group chat sessions</summary>
450 JoinChat = 1UL << 16,
451 /// <summary>Can use voice chat in Group Chat sessions</summary>
452 AllowVoiceChat = 1UL << 27,
453 /// <summary>Can moderate group chat sessions</summary>
454 ModerateChat = 1UL << 37,
455  
456 // Experiences
457 /// <summary>Has admin rights to any experiences owned by this group</summary>
458 ExperienceAdmin = 1UL << 49,
459 /// <summary>Can sign scripts for experiences owned by this group</summary>
460 ExperienceCreator = 1UL << 50,
461  
462 // Group Banning
463 /// <summary>Allows access to ban / un-ban agents from a group</summary>
464 GroupBanAccess = 1UL << 51
465 }
466  
467 /// <summary>
468 /// Ban actions available for group members
469 /// </summary>
470 public enum GroupBanAction : int
471 {
472 /// <summary> Ban agent from joining a group </summary>
473 Ban = 1,
474 /// <summary> Remove restriction on agent jointing a group </summary>
475 Unban = 2,
476 }
477  
478 #endregion Enums
479  
480 /// <summary>
481 /// Handles all network traffic related to reading and writing group
482 /// information
483 /// </summary>
484 public class GroupManager
485 {
486 #region Delegates
487  
488 /// <summary>The event subscribers. null if no subcribers</summary>
489 private EventHandler<CurrentGroupsEventArgs> m_CurrentGroups;
490  
491 /// <summary>Raises the CurrentGroups event</summary>
492 /// <param name="e">A CurrentGroupsEventArgs object containing the
493 /// data sent from the simulator</param>
494 protected virtual void OnCurrentGroups(CurrentGroupsEventArgs e)
495 {
496 EventHandler<CurrentGroupsEventArgs> handler = m_CurrentGroups;
497 if (handler != null)
498 handler(this, e);
499 }
500  
501 /// <summary>Thread sync lock object</summary>
502 private readonly object m_CurrentGroupsLock = new object();
503  
504 /// <summary>Raised when the simulator sends us data containing
505 /// our current group membership</summary>
506 public event EventHandler<CurrentGroupsEventArgs> CurrentGroups
507 {
508 add { lock (m_CurrentGroupsLock) { m_CurrentGroups += value; } }
509 remove { lock (m_CurrentGroupsLock) { m_CurrentGroups -= value; } }
510 }
511  
512 /// <summary>The event subscribers. null if no subcribers</summary>
513 private EventHandler<GroupNamesEventArgs> m_GroupNames;
514  
515 /// <summary>Raises the GroupNamesReply event</summary>
516 /// <param name="e">A GroupNamesEventArgs object containing the
517 /// data response from the simulator</param>
518 protected virtual void OnGroupNamesReply(GroupNamesEventArgs e)
519 {
520 EventHandler<GroupNamesEventArgs> handler = m_GroupNames;
521 if (handler != null)
522 handler(this, e);
523 }
524  
525 /// <summary>Thread sync lock object</summary>
526 private readonly object m_GroupNamesLock = new object();
527  
528 /// <summary>Raised when the simulator responds to a RequestGroupName
529 /// or RequestGroupNames request</summary>
530 public event EventHandler<GroupNamesEventArgs> GroupNamesReply
531 {
532 add { lock (m_GroupNamesLock) { m_GroupNames += value; } }
533 remove { lock (m_GroupNamesLock) { m_GroupNames -= value; } }
534 }
535  
536 /// <summary>The event subscribers. null if no subcribers</summary>
537 private EventHandler<GroupProfileEventArgs> m_GroupProfile;
538  
539 /// <summary>Raises the GroupProfile event</summary>
540 /// <param name="e">An GroupProfileEventArgs object containing the
541 /// data returned from the simulator</param>
542 protected virtual void OnGroupProfile(GroupProfileEventArgs e)
543 {
544 EventHandler<GroupProfileEventArgs> handler = m_GroupProfile;
545 if (handler != null)
546 handler(this, e);
547 }
548  
549 /// <summary>Thread sync lock object</summary>
550 private readonly object m_GroupProfileLock = new object();
551  
552 /// <summary>Raised when the simulator responds to a <see cref="RequestGroupProfile"/> request</summary>
553 public event EventHandler<GroupProfileEventArgs> GroupProfile
554 {
555 add { lock (m_GroupProfileLock) { m_GroupProfile += value; } }
556 remove { lock (m_GroupProfileLock) { m_GroupProfile -= value; } }
557 }
558  
559 /// <summary>The event subscribers. null if no subcribers</summary>
560 private EventHandler<GroupMembersReplyEventArgs> m_GroupMembers;
561  
562 /// <summary>Raises the GroupMembers event</summary>
563 /// <param name="e">A GroupMembersEventArgs object containing the
564 /// data returned from the simulator</param>
565 protected virtual void OnGroupMembersReply(GroupMembersReplyEventArgs e)
566 {
567 EventHandler<GroupMembersReplyEventArgs> handler = m_GroupMembers;
568 if (handler != null)
569 handler(this, e);
570 }
571  
572 /// <summary>Thread sync lock object</summary>
573 private readonly object m_GroupMembersLock = new object();
574  
575 /// <summary>Raised when the simulator responds to a <see cref="RequestGroupMembers"/> request</summary>
576 public event EventHandler<GroupMembersReplyEventArgs> GroupMembersReply
577 {
578 add { lock (m_GroupMembersLock) { m_GroupMembers += value; } }
579 remove { lock (m_GroupMembersLock) { m_GroupMembers -= value; } }
580 }
581  
582 /// <summary>The event subscribers. null if no subcribers</summary>
583 private EventHandler<GroupRolesDataReplyEventArgs> m_GroupRoles;
584  
585 /// <summary>Raises the GroupRolesDataReply event</summary>
586 /// <param name="e">A GroupRolesDataReplyEventArgs object containing the
587 /// data returned from the simulator</param>
588 protected virtual void OnGroupRoleDataReply(GroupRolesDataReplyEventArgs e)
589 {
590 EventHandler<GroupRolesDataReplyEventArgs> handler = m_GroupRoles;
591 if (handler != null)
592 handler(this, e);
593 }
594  
595 /// <summary>Thread sync lock object</summary>
596 private readonly object m_GroupRolesLock = new object();
597  
598 /// <summary>Raised when the simulator responds to a <see cref="RequestGroupRoleData"/> request</summary>
599 public event EventHandler<GroupRolesDataReplyEventArgs> GroupRoleDataReply
600 {
601 add { lock (m_GroupRolesLock) { m_GroupRoles += value; } }
602 remove { lock (m_GroupRolesLock) { m_GroupRoles -= value; } }
603 }
604  
605 /// <summary>The event subscribers. null if no subcribers</summary>
606 private EventHandler<GroupRolesMembersReplyEventArgs> m_GroupRoleMembers;
607  
608 /// <summary>Raises the GroupRoleMembersReply event</summary>
609 /// <param name="e">A GroupRolesRoleMembersReplyEventArgs object containing the
610 /// data returned from the simulator</param>
611 protected virtual void OnGroupRoleMembers(GroupRolesMembersReplyEventArgs e)
612 {
613 EventHandler<GroupRolesMembersReplyEventArgs> handler = m_GroupRoleMembers;
614 if (handler != null)
615 handler(this, e);
616 }
617  
618 /// <summary>Thread sync lock object</summary>
619 private readonly object m_GroupRolesMembersLock = new object();
620  
621 /// <summary>Raised when the simulator responds to a <see cref="RequestGroupRolesMembers"/> request</summary>
622 public event EventHandler<GroupRolesMembersReplyEventArgs> GroupRoleMembersReply
623 {
624 add { lock (m_GroupRolesMembersLock) { m_GroupRoleMembers += value; } }
625 remove { lock (m_GroupRolesMembersLock) { m_GroupRoleMembers -= value; } }
626 }
627  
628 /// <summary>The event subscribers. null if no subcribers</summary>
629 private EventHandler<GroupTitlesReplyEventArgs> m_GroupTitles;
630  
631  
632 /// <summary>Raises the GroupTitlesReply event</summary>
633 /// <param name="e">A GroupTitlesReplyEventArgs object containing the
634 /// data returned from the simulator</param>
635 protected virtual void OnGroupTitles(GroupTitlesReplyEventArgs e)
636 {
637 EventHandler<GroupTitlesReplyEventArgs> handler = m_GroupTitles;
638 if (handler != null)
639 handler(this, e);
640 }
641  
642 /// <summary>Thread sync lock object</summary>
643 private readonly object m_GroupTitlesLock = new object();
644  
645 /// <summary>Raised when the simulator responds to a <see cref="RequestGroupTitles"/> request</summary>
646 public event EventHandler<GroupTitlesReplyEventArgs> GroupTitlesReply
647 {
648 add { lock (m_GroupTitlesLock) { m_GroupTitles += value; } }
649 remove { lock (m_GroupTitlesLock) { m_GroupTitles -= value; } }
650 }
651  
652 /// <summary>The event subscribers. null if no subcribers</summary>
653 private EventHandler<GroupAccountSummaryReplyEventArgs> m_GroupAccountSummary;
654  
655 /// <summary>Raises the GroupAccountSummary event</summary>
656 /// <param name="e">A GroupAccountSummaryReplyEventArgs object containing the
657 /// data returned from the simulator</param>
658 protected virtual void OnGroupAccountSummaryReply(GroupAccountSummaryReplyEventArgs e)
659 {
660 EventHandler<GroupAccountSummaryReplyEventArgs> handler = m_GroupAccountSummary;
661 if (handler != null)
662 handler(this, e);
663 }
664  
665 /// <summary>Thread sync lock object</summary>
666 private readonly object m_GroupAccountSummaryLock = new object();
667  
668 /// <summary>Raised when a response to a RequestGroupAccountSummary is returned
669 /// by the simulator</summary>
670 public event EventHandler<GroupAccountSummaryReplyEventArgs> GroupAccountSummaryReply
671 {
672 add { lock (m_GroupAccountSummaryLock) { m_GroupAccountSummary += value; } }
673 remove { lock (m_GroupAccountSummaryLock) { m_GroupAccountSummary -= value; } }
674 }
675  
676 /// <summary>The event subscribers. null if no subcribers</summary>
677 private EventHandler<GroupCreatedReplyEventArgs> m_GroupCreated;
678  
679 /// <summary>Raises the GroupCreated event</summary>
680 /// <param name="e">An GroupCreatedEventArgs object containing the
681 /// data returned from the simulator</param>
682 protected virtual void OnGroupCreatedReply(GroupCreatedReplyEventArgs e)
683 {
684 EventHandler<GroupCreatedReplyEventArgs> handler = m_GroupCreated;
685 if (handler != null)
686 handler(this, e);
687 }
688 /// <summary>Thread sync lock object</summary>
689 private readonly object m_GroupCreatedLock = new object();
690  
691 /// <summary>Raised when a request to create a group is successful</summary>
692 public event EventHandler<GroupCreatedReplyEventArgs> GroupCreatedReply
693 {
694 add { lock (m_GroupCreatedLock) { m_GroupCreated += value; } }
695 remove { lock (m_GroupCreatedLock) { m_GroupCreated -= value; } }
696 }
697  
698 /// <summary>The event subscribers. null if no subcribers</summary>
699 private EventHandler<GroupOperationEventArgs> m_GroupJoined;
700  
701 /// <summary>Raises the GroupJoined event</summary>
702 /// <param name="e">A GroupOperationEventArgs object containing the
703 /// result of the operation returned from the simulator</param>
704 protected virtual void OnGroupJoinedReply(GroupOperationEventArgs e)
705 {
706 EventHandler<GroupOperationEventArgs> handler = m_GroupJoined;
707 if (handler != null)
708 handler(this, e);
709 }
710 /// <summary>Thread sync lock object</summary>
711 private readonly object m_GroupJoinedLock = new object();
712  
713 /// <summary>Raised when a request to join a group either
714 /// fails or succeeds</summary>
715 public event EventHandler<GroupOperationEventArgs> GroupJoinedReply
716 {
717 add { lock (m_GroupJoinedLock) { m_GroupJoined += value; } }
718 remove { lock (m_GroupJoinedLock) { m_GroupJoined -= value; } }
719 }
720  
721 /// <summary>The event subscribers. null if no subcribers</summary>
722 private EventHandler<GroupOperationEventArgs> m_GroupLeft;
723  
724 /// <summary>Raises the GroupLeft event</summary>
725 /// <param name="e">A GroupOperationEventArgs object containing the
726 /// result of the operation returned from the simulator</param>
727 protected virtual void OnGroupLeaveReply(GroupOperationEventArgs e)
728 {
729 EventHandler<GroupOperationEventArgs> handler = m_GroupLeft;
730 if (handler != null)
731 handler(this, e);
732 }
733 /// <summary>Thread sync lock object</summary>
734 private readonly object m_GroupLeftLock = new object();
735  
736 /// <summary>Raised when a request to leave a group either
737 /// fails or succeeds</summary>
738 public event EventHandler<GroupOperationEventArgs> GroupLeaveReply
739 {
740 add { lock (m_GroupLeftLock) { m_GroupLeft += value; } }
741 remove { lock (m_GroupLeftLock) { m_GroupLeft -= value; } }
742 }
743  
744 /// <summary>The event subscribers. null if no subcribers</summary>
745 private EventHandler<GroupDroppedEventArgs> m_GroupDropped;
746  
747 /// <summary>Raises the GroupDropped event</summary>
748 /// <param name="e">An GroupDroppedEventArgs object containing the
749 /// the group your agent left</param>
750 protected virtual void OnGroupDropped(GroupDroppedEventArgs e)
751 {
752 EventHandler<GroupDroppedEventArgs> handler = m_GroupDropped;
753 if (handler != null)
754 handler(this, e);
755 }
756 /// <summary>Thread sync lock object</summary>
757 private readonly object m_GroupDroppedLock = new object();
758  
759 /// <summary>Raised when A group is removed from the group server</summary>
760 public event EventHandler<GroupDroppedEventArgs> GroupDropped
761 {
762 add { lock (m_GroupDroppedLock) { m_GroupDropped += value; } }
763 remove { lock (m_GroupDroppedLock) { m_GroupDropped -= value; } }
764 }
765  
766 /// <summary>The event subscribers. null if no subcribers</summary>
767 private EventHandler<GroupOperationEventArgs> m_GroupMemberEjected;
768  
769 /// <summary>Raises the GroupMemberEjected event</summary>
770 /// <param name="e">An GroupMemberEjectedEventArgs object containing the
771 /// data returned from the simulator</param>
772 protected virtual void OnGroupMemberEjected(GroupOperationEventArgs e)
773 {
774 EventHandler<GroupOperationEventArgs> handler = m_GroupMemberEjected;
775 if (handler != null)
776 handler(this, e);
777 }
778 /// <summary>Thread sync lock object</summary>
779 private readonly object m_GroupMemberEjectedLock = new object();
780  
781 /// <summary>Raised when a request to eject a member from a group either
782 /// fails or succeeds</summary>
783 public event EventHandler<GroupOperationEventArgs> GroupMemberEjected
784 {
785 add { lock (m_GroupMemberEjectedLock) { m_GroupMemberEjected += value; } }
786 remove { lock (m_GroupMemberEjectedLock) { m_GroupMemberEjected -= value; } }
787 }
788  
789 /// <summary>The event subscribers. null if no subcribers</summary>
790 private EventHandler<GroupNoticesListReplyEventArgs> m_GroupNoticesListReply;
791  
792 /// <summary>Raises the GroupNoticesListReply event</summary>
793 /// <param name="e">An GroupNoticesListReplyEventArgs object containing the
794 /// data returned from the simulator</param>
795 protected virtual void OnGroupNoticesListReply(GroupNoticesListReplyEventArgs e)
796 {
797 EventHandler<GroupNoticesListReplyEventArgs> handler = m_GroupNoticesListReply;
798 if (handler != null)
799 handler(this, e);
800 }
801  
802 /// <summary>Thread sync lock object</summary>
803 private readonly object m_GroupNoticesListReplyLock = new object();
804  
805 /// <summary>Raised when the simulator sends us group notices</summary>
806 /// <seealso cref="RequestGroupNoticesList"/>
807 public event EventHandler<GroupNoticesListReplyEventArgs> GroupNoticesListReply
808 {
809 add { lock (m_GroupNoticesListReplyLock) { m_GroupNoticesListReply += value; } }
810 remove { lock (m_GroupNoticesListReplyLock) { m_GroupNoticesListReply -= value; } }
811 }
812  
813 /// <summary>The event subscribers. null if no subcribers</summary>
814 private EventHandler<GroupInvitationEventArgs> m_GroupInvitation;
815  
816 /// <summary>Raises the GroupInvitation event</summary>
817 /// <param name="e">An GroupInvitationEventArgs object containing the
818 /// data returned from the simulator</param>
819 protected virtual void OnGroupInvitation(GroupInvitationEventArgs e)
820 {
821 EventHandler<GroupInvitationEventArgs> handler = m_GroupInvitation;
822 if (handler != null)
823 handler(this, e);
824 }
825  
826 /// <summary>Thread sync lock object</summary>
827 private readonly object m_GroupInvitationLock = new object();
828  
829 /// <summary>Raised when another agent invites our avatar to join a group</summary>
830 public event EventHandler<GroupInvitationEventArgs> GroupInvitation
831 {
832 add { lock (m_GroupInvitationLock) { m_GroupInvitation += value; } }
833 remove { lock (m_GroupInvitationLock) { m_GroupInvitation -= value; } }
834 }
835  
836  
837  
838  
839  
840  
841 /// <summary>The event subscribers. null if no subcribers</summary>
842 private EventHandler<BannedAgentsEventArgs> m_BannedAgents;
843  
844 /// <summary>Raises the BannedAgents event</summary>
845 /// <param name="e">An BannedAgentsEventArgs object containing the
846 /// data returned from the simulator</param>
847 protected virtual void OnBannedAgents(BannedAgentsEventArgs e)
848 {
849 EventHandler<BannedAgentsEventArgs> handler = m_BannedAgents;
850 if (handler != null)
851 handler(this, e);
852 }
853  
854 /// <summary>Thread sync lock object</summary>
855 private readonly object m_BannedAgentsLock = new object();
856  
857 /// <summary>Raised when another agent invites our avatar to join a group</summary>
858 public event EventHandler<BannedAgentsEventArgs> BannedAgents
859 {
860 add { lock (m_BannedAgentsLock) { m_BannedAgents += value; } }
861 remove { lock (m_BannedAgentsLock) { m_BannedAgents -= value; } }
862 }
863  
864 #endregion Delegates
865  
866  
867 /// <summary>A reference to the current <seealso cref="GridClient"/> instance</summary>
868 private GridClient Client;
869 /// <summary>Currently-active group members requests</summary>
870 private List<UUID> GroupMembersRequests;
871 /// <summary>Currently-active group roles requests</summary>
872 private List<UUID> GroupRolesRequests;
873 /// <summary>Currently-active group role-member requests</summary>
874 private List<UUID> GroupRolesMembersRequests;
875 /// <summary>Dictionary keeping group members while request is in progress</summary>
876 private InternalDictionary<UUID, Dictionary<UUID, GroupMember>> TempGroupMembers;
877 /// <summary>Dictionary keeping mebmer/role mapping while request is in progress</summary>
878 private InternalDictionary<UUID, List<KeyValuePair<UUID, UUID>>> TempGroupRolesMembers;
879 /// <summary>Dictionary keeping GroupRole information while request is in progress</summary>
880 private InternalDictionary<UUID, Dictionary<UUID, GroupRole>> TempGroupRoles;
881 /// <summary>Caches group name lookups</summary>
882 public InternalDictionary<UUID, string> GroupName2KeyCache;
883  
884 /// <summary>
885 /// Construct a new instance of the GroupManager class
886 /// </summary>
887 /// <param name="client">A reference to the current <seealso cref="GridClient"/> instance</param>
888 public GroupManager(GridClient client)
889 {
890 Client = client;
891  
892 TempGroupMembers = new InternalDictionary<UUID, Dictionary<UUID, GroupMember>>();
893 GroupMembersRequests = new List<UUID>();
894 TempGroupRoles = new InternalDictionary<UUID, Dictionary<UUID, GroupRole>>();
895 GroupRolesRequests = new List<UUID>();
896 TempGroupRolesMembers = new InternalDictionary<UUID, List<KeyValuePair<UUID, UUID>>>();
897 GroupRolesMembersRequests = new List<UUID>();
898 GroupName2KeyCache = new InternalDictionary<UUID, string>();
899  
900 Client.Self.IM += Self_IM;
901  
902 Client.Network.RegisterEventCallback("AgentGroupDataUpdate", new Caps.EventQueueCallback(AgentGroupDataUpdateMessageHandler));
903 // deprecated in simulator v1.27
904 Client.Network.RegisterCallback(PacketType.AgentDropGroup, AgentDropGroupHandler);
905 Client.Network.RegisterCallback(PacketType.GroupTitlesReply, GroupTitlesReplyHandler);
906 Client.Network.RegisterCallback(PacketType.GroupProfileReply, GroupProfileReplyHandler);
907 Client.Network.RegisterCallback(PacketType.GroupMembersReply, GroupMembersHandler);
908 Client.Network.RegisterCallback(PacketType.GroupRoleDataReply, GroupRoleDataReplyHandler);
909 Client.Network.RegisterCallback(PacketType.GroupRoleMembersReply, GroupRoleMembersReplyHandler);
910 Client.Network.RegisterCallback(PacketType.GroupActiveProposalItemReply, GroupActiveProposalItemHandler);
911 Client.Network.RegisterCallback(PacketType.GroupVoteHistoryItemReply, GroupVoteHistoryItemHandler);
912 Client.Network.RegisterCallback(PacketType.GroupAccountSummaryReply, GroupAccountSummaryReplyHandler);
913 Client.Network.RegisterCallback(PacketType.CreateGroupReply, CreateGroupReplyHandler);
914 Client.Network.RegisterCallback(PacketType.JoinGroupReply, JoinGroupReplyHandler);
915 Client.Network.RegisterCallback(PacketType.LeaveGroupReply, LeaveGroupReplyHandler);
916 Client.Network.RegisterCallback(PacketType.UUIDGroupNameReply, UUIDGroupNameReplyHandler);
917 Client.Network.RegisterCallback(PacketType.EjectGroupMemberReply, EjectGroupMemberReplyHandler);
918 Client.Network.RegisterCallback(PacketType.GroupNoticesListReply, GroupNoticesListReplyHandler);
919  
920 Client.Network.RegisterEventCallback("AgentDropGroup", new Caps.EventQueueCallback(AgentDropGroupMessageHandler));
921 }
922  
923 void Self_IM(object sender, InstantMessageEventArgs e)
924 {
925 if (m_GroupInvitation != null && e.IM.Dialog == InstantMessageDialog.GroupInvitation)
926 {
927 GroupInvitationEventArgs args = new GroupInvitationEventArgs(e.Simulator, e.IM.FromAgentID, e.IM.FromAgentName, e.IM.Message);
928 OnGroupInvitation(args);
929  
930 if (args.Accept)
931 {
932 Client.Self.InstantMessage("name", e.IM.FromAgentID, "message", e.IM.IMSessionID, InstantMessageDialog.GroupInvitationAccept,
933 InstantMessageOnline.Online, Client.Self.SimPosition, UUID.Zero, Utils.EmptyBytes);
934 }
935 else
936 {
937 Client.Self.InstantMessage("name", e.IM.FromAgentID, "message", e.IM.IMSessionID, InstantMessageDialog.GroupInvitationDecline,
938 InstantMessageOnline.Online, Client.Self.SimPosition, UUID.Zero, new byte[1] { 0 });
939 }
940 }
941 }
942  
943  
944 #region Public Methods
945  
946 /// <summary>
947 /// Request a current list of groups the avatar is a member of.
948 /// </summary>
949 /// <remarks>CAPS Event Queue must be running for this to work since the results
950 /// come across CAPS.</remarks>
951 public void RequestCurrentGroups()
952 {
953 AgentDataUpdateRequestPacket request = new AgentDataUpdateRequestPacket();
954  
955 request.AgentData.AgentID = Client.Self.AgentID;
956 request.AgentData.SessionID = Client.Self.SessionID;
957  
958 Client.Network.SendPacket(request);
959 }
960  
961 /// <summary>
962 /// Lookup name of group based on groupID
963 /// </summary>
964 /// <param name="groupID">groupID of group to lookup name for.</param>
965 public void RequestGroupName(UUID groupID)
966 {
967 // if we already have this in the cache, return from cache instead of making a request
968 if (GroupName2KeyCache.ContainsKey(groupID))
969 {
970 Dictionary<UUID, string> groupNames = new Dictionary<UUID, string>();
971 lock (GroupName2KeyCache.Dictionary)
972 groupNames.Add(groupID, GroupName2KeyCache.Dictionary[groupID]);
973  
974 if (m_GroupNames != null)
975 {
976 OnGroupNamesReply(new GroupNamesEventArgs(groupNames));
977 }
978 }
979  
980 else
981 {
982 UUIDGroupNameRequestPacket req = new UUIDGroupNameRequestPacket();
983 UUIDGroupNameRequestPacket.UUIDNameBlockBlock[] block = new UUIDGroupNameRequestPacket.UUIDNameBlockBlock[1];
984 block[0] = new UUIDGroupNameRequestPacket.UUIDNameBlockBlock();
985 block[0].ID = groupID;
986 req.UUIDNameBlock = block;
987 Client.Network.SendPacket(req);
988 }
989 }
990  
991 /// <summary>
992 /// Request lookup of multiple group names
993 /// </summary>
994 /// <param name="groupIDs">List of group IDs to request.</param>
995 public void RequestGroupNames(List<UUID> groupIDs)
996 {
997 Dictionary<UUID, string> groupNames = new Dictionary<UUID, string>();
998 lock (GroupName2KeyCache.Dictionary)
999 {
1000 foreach (UUID groupID in groupIDs)
1001 {
1002 if (GroupName2KeyCache.ContainsKey(groupID))
1003 groupNames[groupID] = GroupName2KeyCache.Dictionary[groupID];
1004 }
1005 }
1006  
1007 if (groupIDs.Count > 0)
1008 {
1009 UUIDGroupNameRequestPacket req = new UUIDGroupNameRequestPacket();
1010 UUIDGroupNameRequestPacket.UUIDNameBlockBlock[] block = new UUIDGroupNameRequestPacket.UUIDNameBlockBlock[groupIDs.Count];
1011  
1012 for (int i = 0; i < groupIDs.Count; i++)
1013 {
1014 block[i] = new UUIDGroupNameRequestPacket.UUIDNameBlockBlock();
1015 block[i].ID = groupIDs[i];
1016 }
1017  
1018 req.UUIDNameBlock = block;
1019 Client.Network.SendPacket(req);
1020 }
1021  
1022 // fire handler from cache
1023 if (groupNames.Count > 0 && m_GroupNames != null)
1024 {
1025 OnGroupNamesReply(new GroupNamesEventArgs(groupNames));
1026 }
1027 }
1028  
1029 /// <summary>Lookup group profile data such as name, enrollment, founder, logo, etc</summary>
1030 /// <remarks>Subscribe to <code>OnGroupProfile</code> event to receive the results.</remarks>
1031 /// <param name="group">group ID (UUID)</param>
1032 public void RequestGroupProfile(UUID group)
1033 {
1034 GroupProfileRequestPacket request = new GroupProfileRequestPacket();
1035  
1036 request.AgentData.AgentID = Client.Self.AgentID;
1037 request.AgentData.SessionID = Client.Self.SessionID;
1038 request.GroupData.GroupID = group;
1039  
1040 Client.Network.SendPacket(request);
1041 }
1042  
1043 /// <summary>Request a list of group members.</summary>
1044 /// <remarks>Subscribe to <code>OnGroupMembers</code> event to receive the results.</remarks>
1045 /// <param name="group">group ID (UUID)</param>
1046 /// <returns>UUID of the request, use to index into cache</returns>
1047 public UUID RequestGroupMembers(UUID group)
1048 {
1049 UUID requestID = UUID.Random();
1050 Uri url = null;
1051  
1052 if (Client.Network.CurrentSim != null && Client.Network.CurrentSim.Caps != null &&
1053 null != (url = Client.Network.CurrentSim.Caps.CapabilityURI("GroupMemberData")))
1054 {
1055 CapsClient req = new CapsClient(url);
1056 req.OnComplete += (client, result, error) =>
1057 {
1058 if (error == null)
1059 {
1060 GroupMembersHandlerCaps(requestID, result);
1061 }
1062 };
1063  
1064 OSDMap requestData = new OSDMap(1);
1065 requestData["group_id"] = group;
1066 req.BeginGetResponse(requestData, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT * 4);
1067  
1068 return requestID;
1069 }
1070  
1071 lock (GroupMembersRequests) GroupMembersRequests.Add(requestID);
1072  
1073 GroupMembersRequestPacket request = new GroupMembersRequestPacket();
1074  
1075 request.AgentData.AgentID = Client.Self.AgentID;
1076 request.AgentData.SessionID = Client.Self.SessionID;
1077 request.GroupData.GroupID = group;
1078 request.GroupData.RequestID = requestID;
1079  
1080 Client.Network.SendPacket(request);
1081 return requestID;
1082 }
1083  
1084 /// <summary>Request group roles</summary>
1085 /// <remarks>Subscribe to <code>OnGroupRoles</code> event to receive the results.</remarks>
1086 /// <param name="group">group ID (UUID)</param>
1087 /// <returns>UUID of the request, use to index into cache</returns>
1088 public UUID RequestGroupRoles(UUID group)
1089 {
1090 UUID requestID = UUID.Random();
1091 lock (GroupRolesRequests) GroupRolesRequests.Add(requestID);
1092  
1093 GroupRoleDataRequestPacket request = new GroupRoleDataRequestPacket();
1094  
1095 request.AgentData.AgentID = Client.Self.AgentID;
1096 request.AgentData.SessionID = Client.Self.SessionID;
1097 request.GroupData.GroupID = group;
1098 request.GroupData.RequestID = requestID;
1099  
1100 Client.Network.SendPacket(request);
1101 return requestID;
1102 }
1103  
1104 /// <summary>Request members (members,role) role mapping for a group.</summary>
1105 /// <remarks>Subscribe to <code>OnGroupRolesMembers</code> event to receive the results.</remarks>
1106 /// <param name="group">group ID (UUID)</param>
1107 /// <returns>UUID of the request, use to index into cache</returns>
1108 public UUID RequestGroupRolesMembers(UUID group)
1109 {
1110 UUID requestID = UUID.Random();
1111 lock (GroupRolesRequests) GroupRolesMembersRequests.Add(requestID);
1112  
1113 GroupRoleMembersRequestPacket request = new GroupRoleMembersRequestPacket();
1114 request.AgentData.AgentID = Client.Self.AgentID;
1115 request.AgentData.SessionID = Client.Self.SessionID;
1116 request.GroupData.GroupID = group;
1117 request.GroupData.RequestID = requestID;
1118 Client.Network.SendPacket(request);
1119 return requestID;
1120 }
1121  
1122 /// <summary>Request a groups Titles</summary>
1123 /// <remarks>Subscribe to <code>OnGroupTitles</code> event to receive the results.</remarks>
1124 /// <param name="group">group ID (UUID)</param>
1125 /// <returns>UUID of the request, use to index into cache</returns>
1126 public UUID RequestGroupTitles(UUID group)
1127 {
1128 UUID requestID = UUID.Random();
1129  
1130 GroupTitlesRequestPacket request = new GroupTitlesRequestPacket();
1131  
1132 request.AgentData.AgentID = Client.Self.AgentID;
1133 request.AgentData.SessionID = Client.Self.SessionID;
1134 request.AgentData.GroupID = group;
1135 request.AgentData.RequestID = requestID;
1136  
1137 Client.Network.SendPacket(request);
1138 return requestID;
1139 }
1140  
1141 /// <summary>Begin to get the group account summary</summary>
1142 /// <remarks>Subscribe to the <code>OnGroupAccountSummary</code> event to receive the results.</remarks>
1143 /// <param name="group">group ID (UUID)</param>
1144 /// <param name="intervalDays">How long of an interval</param>
1145 /// <param name="currentInterval">Which interval (0 for current, 1 for last)</param>
1146 public void RequestGroupAccountSummary(UUID group, int intervalDays, int currentInterval)
1147 {
1148 GroupAccountSummaryRequestPacket p = new GroupAccountSummaryRequestPacket();
1149 p.AgentData.AgentID = Client.Self.AgentID;
1150 p.AgentData.SessionID = Client.Self.SessionID;
1151 p.AgentData.GroupID = group;
1152 p.MoneyData.RequestID = UUID.Random();
1153 p.MoneyData.CurrentInterval = currentInterval;
1154 p.MoneyData.IntervalDays = intervalDays;
1155 Client.Network.SendPacket(p);
1156 }
1157  
1158 /// <summary>Invites a user to a group</summary>
1159 /// <param name="group">The group to invite to</param>
1160 /// <param name="roles">A list of roles to invite a person to</param>
1161 /// <param name="personkey">Key of person to invite</param>
1162 public void Invite(UUID group, List<UUID> roles, UUID personkey)
1163 {
1164 InviteGroupRequestPacket igp = new InviteGroupRequestPacket();
1165  
1166 igp.AgentData = new InviteGroupRequestPacket.AgentDataBlock();
1167 igp.AgentData.AgentID = Client.Self.AgentID;
1168 igp.AgentData.SessionID = Client.Self.SessionID;
1169  
1170 igp.GroupData = new InviteGroupRequestPacket.GroupDataBlock();
1171 igp.GroupData.GroupID = group;
1172  
1173 igp.InviteData = new InviteGroupRequestPacket.InviteDataBlock[roles.Count];
1174  
1175 for (int i = 0; i < roles.Count; i++)
1176 {
1177 igp.InviteData[i] = new InviteGroupRequestPacket.InviteDataBlock();
1178 igp.InviteData[i].InviteeID = personkey;
1179 igp.InviteData[i].RoleID = roles[i];
1180 }
1181  
1182 Client.Network.SendPacket(igp);
1183 }
1184  
1185 /// <summary>Set a group as the current active group</summary>
1186 /// <param name="id">group ID (UUID)</param>
1187 public void ActivateGroup(UUID id)
1188 {
1189 ActivateGroupPacket activate = new ActivateGroupPacket();
1190 activate.AgentData.AgentID = Client.Self.AgentID;
1191 activate.AgentData.SessionID = Client.Self.SessionID;
1192 activate.AgentData.GroupID = id;
1193  
1194 Client.Network.SendPacket(activate);
1195 }
1196  
1197 /// <summary>Change the role that determines your active title</summary>
1198 /// <param name="group">Group ID to use</param>
1199 /// <param name="role">Role ID to change to</param>
1200 public void ActivateTitle(UUID group, UUID role)
1201 {
1202 GroupTitleUpdatePacket gtu = new GroupTitleUpdatePacket();
1203 gtu.AgentData.AgentID = Client.Self.AgentID;
1204 gtu.AgentData.SessionID = Client.Self.SessionID;
1205 gtu.AgentData.TitleRoleID = role;
1206 gtu.AgentData.GroupID = group;
1207  
1208 Client.Network.SendPacket(gtu);
1209 }
1210  
1211 /// <summary>Set this avatar's tier contribution</summary>
1212 /// <param name="group">Group ID to change tier in</param>
1213 /// <param name="contribution">amount of tier to donate</param>
1214 public void SetGroupContribution(UUID group, int contribution)
1215 {
1216 SetGroupContributionPacket sgp = new SetGroupContributionPacket();
1217 sgp.AgentData.AgentID = Client.Self.AgentID;
1218 sgp.AgentData.SessionID = Client.Self.SessionID;
1219 sgp.Data.GroupID = group;
1220 sgp.Data.Contribution = contribution;
1221  
1222 Client.Network.SendPacket(sgp);
1223 }
1224  
1225 /// <summary>
1226 /// Save wheather agent wants to accept group notices and list this group in their profile
1227 /// </summary>
1228 /// <param name="groupID">Group <see cref="UUID"/></param>
1229 /// <param name="acceptNotices">Accept notices from this group</param>
1230 /// <param name="listInProfile">List this group in the profile</param>
1231 public void SetGroupAcceptNotices(UUID groupID, bool acceptNotices, bool listInProfile)
1232 {
1233 SetGroupAcceptNoticesPacket p = new SetGroupAcceptNoticesPacket();
1234 p.AgentData.AgentID = Client.Self.AgentID;
1235 p.AgentData.SessionID = Client.Self.SessionID;
1236 p.Data.GroupID = groupID;
1237 p.Data.AcceptNotices = acceptNotices;
1238 p.NewData.ListInProfile = listInProfile;
1239  
1240 Client.Network.SendPacket(p);
1241 }
1242  
1243 /// <summary>Request to join a group</summary>
1244 /// <remarks>Subscribe to <code>OnGroupJoined</code> event for confirmation.</remarks>
1245 /// <param name="id">group ID (UUID) to join.</param>
1246 public void RequestJoinGroup(UUID id)
1247 {
1248 JoinGroupRequestPacket join = new JoinGroupRequestPacket();
1249 join.AgentData.AgentID = Client.Self.AgentID;
1250 join.AgentData.SessionID = Client.Self.SessionID;
1251  
1252 join.GroupData.GroupID = id;
1253  
1254 Client.Network.SendPacket(join);
1255 }
1256  
1257 /// <summary>
1258 /// Request to create a new group. If the group is successfully
1259 /// created, L$100 will automatically be deducted
1260 /// </summary>
1261 /// <remarks>Subscribe to <code>OnGroupCreated</code> event to receive confirmation.</remarks>
1262 /// <param name="group">Group struct containing the new group info</param>
1263 public void RequestCreateGroup(Group group)
1264 {
1265 OpenMetaverse.Packets.CreateGroupRequestPacket cgrp = new CreateGroupRequestPacket();
1266 cgrp.AgentData = new CreateGroupRequestPacket.AgentDataBlock();
1267 cgrp.AgentData.AgentID = Client.Self.AgentID;
1268 cgrp.AgentData.SessionID = Client.Self.SessionID;
1269  
1270 cgrp.GroupData = new CreateGroupRequestPacket.GroupDataBlock();
1271 cgrp.GroupData.AllowPublish = group.AllowPublish;
1272 cgrp.GroupData.Charter = Utils.StringToBytes(group.Charter);
1273 cgrp.GroupData.InsigniaID = group.InsigniaID;
1274 cgrp.GroupData.MaturePublish = group.MaturePublish;
1275 cgrp.GroupData.MembershipFee = group.MembershipFee;
1276 cgrp.GroupData.Name = Utils.StringToBytes(group.Name);
1277 cgrp.GroupData.OpenEnrollment = group.OpenEnrollment;
1278 cgrp.GroupData.ShowInList = group.ShowInList;
1279  
1280 Client.Network.SendPacket(cgrp);
1281 }
1282  
1283 /// <summary>Update a group's profile and other information</summary>
1284 /// <param name="id">Groups ID (UUID) to update.</param>
1285 /// <param name="group">Group struct to update.</param>
1286 public void UpdateGroup(UUID id, Group group)
1287 {
1288 OpenMetaverse.Packets.UpdateGroupInfoPacket cgrp = new UpdateGroupInfoPacket();
1289 cgrp.AgentData = new UpdateGroupInfoPacket.AgentDataBlock();
1290 cgrp.AgentData.AgentID = Client.Self.AgentID;
1291 cgrp.AgentData.SessionID = Client.Self.SessionID;
1292  
1293 cgrp.GroupData = new UpdateGroupInfoPacket.GroupDataBlock();
1294 cgrp.GroupData.GroupID = id;
1295 cgrp.GroupData.AllowPublish = group.AllowPublish;
1296 cgrp.GroupData.Charter = Utils.StringToBytes(group.Charter);
1297 cgrp.GroupData.InsigniaID = group.InsigniaID;
1298 cgrp.GroupData.MaturePublish = group.MaturePublish;
1299 cgrp.GroupData.MembershipFee = group.MembershipFee;
1300 cgrp.GroupData.OpenEnrollment = group.OpenEnrollment;
1301 cgrp.GroupData.ShowInList = group.ShowInList;
1302  
1303 Client.Network.SendPacket(cgrp);
1304 }
1305  
1306 /// <summary>Eject a user from a group</summary>
1307 /// <param name="group">Group ID to eject the user from</param>
1308 /// <param name="member">Avatar's key to eject</param>
1309 public void EjectUser(UUID group, UUID member)
1310 {
1311 OpenMetaverse.Packets.EjectGroupMemberRequestPacket eject = new EjectGroupMemberRequestPacket();
1312 eject.AgentData = new EjectGroupMemberRequestPacket.AgentDataBlock();
1313 eject.AgentData.AgentID = Client.Self.AgentID;
1314 eject.AgentData.SessionID = Client.Self.SessionID;
1315  
1316 eject.GroupData = new EjectGroupMemberRequestPacket.GroupDataBlock();
1317 eject.GroupData.GroupID = group;
1318  
1319 eject.EjectData = new EjectGroupMemberRequestPacket.EjectDataBlock[1];
1320 eject.EjectData[0] = new EjectGroupMemberRequestPacket.EjectDataBlock();
1321 eject.EjectData[0].EjecteeID = member;
1322  
1323 Client.Network.SendPacket(eject);
1324 }
1325  
1326 /// <summary>Update role information</summary>
1327 /// <param name="role">Modified role to be updated</param>
1328 public void UpdateRole(GroupRole role)
1329 {
1330 OpenMetaverse.Packets.GroupRoleUpdatePacket gru = new GroupRoleUpdatePacket();
1331 gru.AgentData.AgentID = Client.Self.AgentID;
1332 gru.AgentData.SessionID = Client.Self.SessionID;
1333 gru.AgentData.GroupID = role.GroupID;
1334 gru.RoleData = new GroupRoleUpdatePacket.RoleDataBlock[1];
1335 gru.RoleData[0] = new GroupRoleUpdatePacket.RoleDataBlock();
1336 gru.RoleData[0].Name = Utils.StringToBytes(role.Name);
1337 gru.RoleData[0].Description = Utils.StringToBytes(role.Description);
1338 gru.RoleData[0].Powers = (ulong)role.Powers;
1339 gru.RoleData[0].RoleID = role.ID;
1340 gru.RoleData[0].Title = Utils.StringToBytes(role.Title);
1341 gru.RoleData[0].UpdateType = (byte)GroupRoleUpdate.UpdateAll;
1342 Client.Network.SendPacket(gru);
1343 }
1344  
1345 /// <summary>Create a new group role</summary>
1346 /// <param name="group">Group ID to update</param>
1347 /// <param name="role">Role to create</param>
1348 public void CreateRole(UUID group, GroupRole role)
1349 {
1350 OpenMetaverse.Packets.GroupRoleUpdatePacket gru = new GroupRoleUpdatePacket();
1351 gru.AgentData.AgentID = Client.Self.AgentID;
1352 gru.AgentData.SessionID = Client.Self.SessionID;
1353 gru.AgentData.GroupID = group;
1354 gru.RoleData = new GroupRoleUpdatePacket.RoleDataBlock[1];
1355 gru.RoleData[0] = new GroupRoleUpdatePacket.RoleDataBlock();
1356 gru.RoleData[0].RoleID = UUID.Random();
1357 gru.RoleData[0].Name = Utils.StringToBytes(role.Name);
1358 gru.RoleData[0].Description = Utils.StringToBytes(role.Description);
1359 gru.RoleData[0].Powers = (ulong)role.Powers;
1360 gru.RoleData[0].Title = Utils.StringToBytes(role.Title);
1361 gru.RoleData[0].UpdateType = (byte)GroupRoleUpdate.Create;
1362 Client.Network.SendPacket(gru);
1363 }
1364  
1365 /// <summary>Delete a group role</summary>
1366 /// <param name="group">Group ID to update</param>
1367 /// <param name="roleID">Role to delete</param>
1368 public void DeleteRole(UUID group, UUID roleID)
1369 {
1370 OpenMetaverse.Packets.GroupRoleUpdatePacket gru = new GroupRoleUpdatePacket();
1371 gru.AgentData.AgentID = Client.Self.AgentID;
1372 gru.AgentData.SessionID = Client.Self.SessionID;
1373 gru.AgentData.GroupID = group;
1374 gru.RoleData = new GroupRoleUpdatePacket.RoleDataBlock[1];
1375 gru.RoleData[0] = new GroupRoleUpdatePacket.RoleDataBlock();
1376 gru.RoleData[0].RoleID = roleID;
1377 gru.RoleData[0].Name = Utils.StringToBytes(string.Empty);
1378 gru.RoleData[0].Description = Utils.StringToBytes(string.Empty);
1379 gru.RoleData[0].Powers = 0u;
1380 gru.RoleData[0].Title = Utils.StringToBytes(string.Empty);
1381 gru.RoleData[0].UpdateType = (byte)GroupRoleUpdate.Delete;
1382 Client.Network.SendPacket(gru);
1383 }
1384  
1385 /// <summary>Remove an avatar from a role</summary>
1386 /// <param name="group">Group ID to update</param>
1387 /// <param name="role">Role ID to be removed from</param>
1388 /// <param name="member">Avatar's Key to remove</param>
1389 public void RemoveFromRole(UUID group, UUID role, UUID member)
1390 {
1391 OpenMetaverse.Packets.GroupRoleChangesPacket grc = new GroupRoleChangesPacket();
1392 grc.AgentData.AgentID = Client.Self.AgentID;
1393 grc.AgentData.SessionID = Client.Self.SessionID;
1394 grc.AgentData.GroupID = group;
1395 grc.RoleChange = new GroupRoleChangesPacket.RoleChangeBlock[1];
1396 grc.RoleChange[0] = new GroupRoleChangesPacket.RoleChangeBlock();
1397 //Add to members and role
1398 grc.RoleChange[0].MemberID = member;
1399 grc.RoleChange[0].RoleID = role;
1400 //1 = Remove From Role TODO: this should be in an enum
1401 grc.RoleChange[0].Change = 1;
1402 Client.Network.SendPacket(grc);
1403 }
1404  
1405 /// <summary>Assign an avatar to a role</summary>
1406 /// <param name="group">Group ID to update</param>
1407 /// <param name="role">Role ID to assign to</param>
1408 /// <param name="member">Avatar's ID to assign to role</param>
1409 public void AddToRole(UUID group, UUID role, UUID member)
1410 {
1411 OpenMetaverse.Packets.GroupRoleChangesPacket grc = new GroupRoleChangesPacket();
1412 grc.AgentData.AgentID = Client.Self.AgentID;
1413 grc.AgentData.SessionID = Client.Self.SessionID;
1414 grc.AgentData.GroupID = group;
1415 grc.RoleChange = new GroupRoleChangesPacket.RoleChangeBlock[1];
1416 grc.RoleChange[0] = new GroupRoleChangesPacket.RoleChangeBlock();
1417 //Add to members and role
1418 grc.RoleChange[0].MemberID = member;
1419 grc.RoleChange[0].RoleID = role;
1420 //0 = Add to Role TODO: this should be in an enum
1421 grc.RoleChange[0].Change = 0;
1422 Client.Network.SendPacket(grc);
1423 }
1424  
1425 /// <summary>Request the group notices list</summary>
1426 /// <param name="group">Group ID to fetch notices for</param>
1427 public void RequestGroupNoticesList(UUID group)
1428 {
1429 OpenMetaverse.Packets.GroupNoticesListRequestPacket gnl = new GroupNoticesListRequestPacket();
1430 gnl.AgentData.AgentID = Client.Self.AgentID;
1431 gnl.AgentData.SessionID = Client.Self.SessionID;
1432 gnl.Data.GroupID = group;
1433 Client.Network.SendPacket(gnl);
1434 }
1435  
1436 /// <summary>Request a group notice by key</summary>
1437 /// <param name="noticeID">ID of group notice</param>
1438 public void RequestGroupNotice(UUID noticeID)
1439 {
1440 OpenMetaverse.Packets.GroupNoticeRequestPacket gnr = new GroupNoticeRequestPacket();
1441 gnr.AgentData.AgentID = Client.Self.AgentID;
1442 gnr.AgentData.SessionID = Client.Self.SessionID;
1443 gnr.Data.GroupNoticeID = noticeID;
1444 Client.Network.SendPacket(gnr);
1445 }
1446  
1447 /// <summary>Send out a group notice</summary>
1448 /// <param name="group">Group ID to update</param>
1449 /// <param name="notice"><code>GroupNotice</code> structure containing notice data</param>
1450 public void SendGroupNotice(UUID group, GroupNotice notice)
1451 {
1452 Client.Self.InstantMessage(Client.Self.Name, group, notice.Subject + "|" + notice.Message,
1453 UUID.Zero, InstantMessageDialog.GroupNotice, InstantMessageOnline.Online,
1454 Vector3.Zero, UUID.Zero, notice.SerializeAttachment());
1455 }
1456  
1457 /// <summary>Start a group proposal (vote)</summary>
1458 /// <param name="group">The Group ID to send proposal to</param>
1459 /// <param name="prop"><code>GroupProposal</code> structure containing the proposal</param>
1460 public void StartProposal(UUID group, GroupProposal prop)
1461 {
1462 StartGroupProposalPacket p = new StartGroupProposalPacket();
1463 p.AgentData.AgentID = Client.Self.AgentID;
1464 p.AgentData.SessionID = Client.Self.SessionID;
1465 p.ProposalData.GroupID = group;
1466 p.ProposalData.ProposalText = Utils.StringToBytes(prop.VoteText);
1467 p.ProposalData.Quorum = prop.Quorum;
1468 p.ProposalData.Majority = prop.Majority;
1469 p.ProposalData.Duration = prop.Duration;
1470 Client.Network.SendPacket(p);
1471 }
1472  
1473 /// <summary>Request to leave a group</summary>
1474 /// <remarks>Subscribe to <code>OnGroupLeft</code> event to receive confirmation</remarks>
1475 /// <param name="groupID">The group to leave</param>
1476 public void LeaveGroup(UUID groupID)
1477 {
1478 LeaveGroupRequestPacket p = new LeaveGroupRequestPacket();
1479 p.AgentData.AgentID = Client.Self.AgentID;
1480 p.AgentData.SessionID = Client.Self.SessionID;
1481 p.GroupData.GroupID = groupID;
1482  
1483 Client.Network.SendPacket(p);
1484 }
1485  
1486 /// <summary>
1487 /// Gets the URI of the cpability for handling group bans
1488 /// </summary>
1489 /// <param name="groupID">Group ID</param>
1490 /// <returns>null, if the feature is not supported, or URI of the capability</returns>
1491 public Uri GetGroupAPIUri(UUID groupID)
1492 {
1493 Uri ret = null;
1494  
1495 if (Client.Network.Connected
1496 && Client.Network.CurrentSim != null
1497 && Client.Network.CurrentSim.Caps != null)
1498 {
1499 ret = Client.Network.CurrentSim.Caps.CapabilityURI("GroupAPIv1");
1500 if (ret != null)
1501 {
1502 ret = new Uri(string.Format("{0}?group_id={1}", ret.ToString(), groupID.ToString()));
1503 }
1504 }
1505  
1506 return ret;
1507 }
1508  
1509 /// <summary>
1510 /// Request a list of residents banned from joining a group
1511 /// </summary>
1512 /// <param name="groupID">UUID of the group</param>
1513 public void RequestBannedAgents(UUID groupID)
1514 {
1515 RequestBannedAgents(groupID, null);
1516 }
1517  
1518 /// <summary>
1519 /// Request a list of residents banned from joining a group
1520 /// </summary>
1521 /// <param name="groupID">UUID of the group</param>
1522 /// <param name="callback">Callback on request completition</param>
1523 public void RequestBannedAgents(UUID groupID, EventHandler<BannedAgentsEventArgs> callback)
1524 {
1525 Uri uri = GetGroupAPIUri(groupID);
1526 if (uri == null) return;
1527  
1528 CapsClient req = new CapsClient(uri);
1529 req.OnComplete += (client, result, error) =>
1530 {
1531 try
1532 {
1533  
1534 if (error != null)
1535 {
1536 throw error;
1537 }
1538 else
1539 {
1540 UUID gid = ((OSDMap)result)["group_id"];
1541 var banList = (OSDMap)((OSDMap)result)["ban_list"];
1542 Dictionary<UUID, DateTime> bannedAgents = new Dictionary<UUID, DateTime>(banList.Count);
1543  
1544 foreach (var id in banList.Keys)
1545 {
1546 bannedAgents[new UUID(id)] = ((OSDMap)banList[id])["ban_date"].AsDate();
1547 }
1548  
1549 var ret = new BannedAgentsEventArgs(groupID, true, bannedAgents);
1550 OnBannedAgents(ret);
1551 if (callback != null) try { callback(this, ret); }
1552 catch { }
1553 }
1554  
1555 }
1556 catch (Exception ex)
1557 {
1558 Logger.Log("Failed to get a list of banned group members: " + ex.Message, Helpers.LogLevel.Warning, Client);
1559 var ret = new BannedAgentsEventArgs(groupID, false, null);
1560 OnBannedAgents(ret);
1561 if (callback != null) try { callback(this, ret); }
1562 catch { }
1563 }
1564  
1565 };
1566  
1567 req.BeginGetResponse(Client.Settings.CAPS_TIMEOUT);
1568 }
1569  
1570 /// <summary>
1571 /// Request that group of agents be banned or unbanned from the group
1572 /// </summary>
1573 /// <param name="groupID">Group ID</param>
1574 /// <param name="action">Ban/Unban action</param>
1575 /// <param name="agents">Array of agents UUIDs to ban</param>
1576 public void RequestBanAction(UUID groupID, GroupBanAction action, UUID[] agents)
1577 {
1578 RequestBanAction(groupID, action, agents, null);
1579 }
1580  
1581 /// <summary>
1582 /// Request that group of agents be banned or unbanned from the group
1583 /// </summary>
1584 /// <param name="groupID">Group ID</param>
1585 /// <param name="action">Ban/Unban action</param>
1586 /// <param name="agents">Array of agents UUIDs to ban</param>
1587 /// <param name="callback">Callback</param>
1588 public void RequestBanAction(UUID groupID, GroupBanAction action, UUID[] agents, EventHandler<EventArgs> callback)
1589 {
1590 Uri uri = GetGroupAPIUri(groupID);
1591 if (uri == null) return;
1592  
1593 CapsClient req = new CapsClient(uri);
1594 req.OnComplete += (client, result, error) =>
1595 {
1596 if (callback != null) try { callback(this, EventArgs.Empty); }
1597 catch { }
1598 };
1599  
1600 OSDMap OSDRequest = new OSDMap();
1601 OSDRequest["ban_action"] = (int)action;
1602 OSDArray banIDs = new OSDArray(agents.Length);
1603 foreach (var agent in agents)
1604 {
1605 banIDs.Add(agent);
1606 }
1607 OSDRequest["ban_ids"] = banIDs;
1608  
1609 req.BeginGetResponse(OSDRequest, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
1610 }
1611  
1612  
1613  
1614 #endregion
1615  
1616 #region Packet Handlers
1617  
1618 protected void AgentGroupDataUpdateMessageHandler(string capsKey, IMessage message, Simulator simulator)
1619 {
1620 if (m_CurrentGroups != null)
1621 {
1622 AgentGroupDataUpdateMessage msg = (AgentGroupDataUpdateMessage)message;
1623  
1624 Dictionary<UUID, Group> currentGroups = new Dictionary<UUID, Group>();
1625 for (int i = 0; i < msg.GroupDataBlock.Length; i++)
1626 {
1627 Group group = new Group();
1628 group.ID = msg.GroupDataBlock[i].GroupID;
1629 group.InsigniaID = msg.GroupDataBlock[i].GroupInsigniaID;
1630 group.Name = msg.GroupDataBlock[i].GroupName;
1631 group.Contribution = msg.GroupDataBlock[i].Contribution;
1632 group.AcceptNotices = msg.GroupDataBlock[i].AcceptNotices;
1633 group.Powers = msg.GroupDataBlock[i].GroupPowers;
1634 group.ListInProfile = msg.NewGroupDataBlock[i].ListInProfile;
1635  
1636 currentGroups.Add(group.ID, group);
1637  
1638 lock (GroupName2KeyCache.Dictionary)
1639 {
1640 if (!GroupName2KeyCache.Dictionary.ContainsKey(group.ID))
1641 GroupName2KeyCache.Dictionary.Add(group.ID, group.Name);
1642 }
1643 }
1644 OnCurrentGroups(new CurrentGroupsEventArgs(currentGroups));
1645 }
1646 }
1647  
1648 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1649 /// <param name="sender">The sender</param>
1650 /// <param name="e">The EventArgs object containing the packet data</param>
1651 protected void AgentDropGroupHandler(object sender, PacketReceivedEventArgs e)
1652 {
1653 if (m_GroupDropped != null)
1654 {
1655 Packet packet = e.Packet;
1656 OnGroupDropped(new GroupDroppedEventArgs(((AgentDropGroupPacket)packet).AgentData.GroupID));
1657 }
1658 }
1659  
1660 protected void AgentDropGroupMessageHandler(string capsKey, IMessage message, Simulator simulator)
1661 {
1662  
1663 if (m_GroupDropped != null)
1664 {
1665 AgentDropGroupMessage msg = (AgentDropGroupMessage)message;
1666 for (int i = 0; i < msg.AgentDataBlock.Length; i++)
1667 {
1668 OnGroupDropped(new GroupDroppedEventArgs(msg.AgentDataBlock[i].GroupID));
1669 }
1670 }
1671 }
1672  
1673 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1674 /// <param name="sender">The sender</param>
1675 /// <param name="e">The EventArgs object containing the packet data</param>
1676 protected void GroupProfileReplyHandler(object sender, PacketReceivedEventArgs e)
1677 {
1678 if (m_GroupProfile != null)
1679 {
1680 Packet packet = e.Packet;
1681 GroupProfileReplyPacket profile = (GroupProfileReplyPacket)packet;
1682 Group group = new Group();
1683  
1684 group.ID = profile.GroupData.GroupID;
1685 group.AllowPublish = profile.GroupData.AllowPublish;
1686 group.Charter = Utils.BytesToString(profile.GroupData.Charter);
1687 group.FounderID = profile.GroupData.FounderID;
1688 group.GroupMembershipCount = profile.GroupData.GroupMembershipCount;
1689 group.GroupRolesCount = profile.GroupData.GroupRolesCount;
1690 group.InsigniaID = profile.GroupData.InsigniaID;
1691 group.MaturePublish = profile.GroupData.MaturePublish;
1692 group.MembershipFee = profile.GroupData.MembershipFee;
1693 group.MemberTitle = Utils.BytesToString(profile.GroupData.MemberTitle);
1694 group.Money = profile.GroupData.Money;
1695 group.Name = Utils.BytesToString(profile.GroupData.Name);
1696 group.OpenEnrollment = profile.GroupData.OpenEnrollment;
1697 group.OwnerRole = profile.GroupData.OwnerRole;
1698 group.Powers = (GroupPowers)profile.GroupData.PowersMask;
1699 group.ShowInList = profile.GroupData.ShowInList;
1700  
1701 OnGroupProfile(new GroupProfileEventArgs(group));
1702 }
1703 }
1704  
1705 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1706 /// <param name="sender">The sender</param>
1707 /// <param name="e">The EventArgs object containing the packet data</param>
1708 protected void GroupNoticesListReplyHandler(object sender, PacketReceivedEventArgs e)
1709 {
1710 if (m_GroupNoticesListReply != null)
1711 {
1712 Packet packet = e.Packet;
1713 GroupNoticesListReplyPacket reply = (GroupNoticesListReplyPacket)packet;
1714  
1715 List<GroupNoticesListEntry> notices = new List<GroupNoticesListEntry>();
1716  
1717 foreach (GroupNoticesListReplyPacket.DataBlock entry in reply.Data)
1718 {
1719 GroupNoticesListEntry notice = new GroupNoticesListEntry();
1720 notice.FromName = Utils.BytesToString(entry.FromName);
1721 notice.Subject = Utils.BytesToString(entry.Subject);
1722 notice.NoticeID = entry.NoticeID;
1723 notice.Timestamp = entry.Timestamp;
1724 notice.HasAttachment = entry.HasAttachment;
1725 notice.AssetType = (AssetType)entry.AssetType;
1726  
1727 notices.Add(notice);
1728 }
1729  
1730 OnGroupNoticesListReply(new GroupNoticesListReplyEventArgs(reply.AgentData.GroupID, notices));
1731 }
1732 }
1733  
1734 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1735 /// <param name="sender">The sender</param>
1736 /// <param name="e">The EventArgs object containing the packet data</param>
1737 protected void GroupTitlesReplyHandler(object sender, PacketReceivedEventArgs e)
1738 {
1739 if (m_GroupTitles != null)
1740 {
1741 Packet packet = e.Packet;
1742 GroupTitlesReplyPacket titles = (GroupTitlesReplyPacket)packet;
1743 Dictionary<UUID, GroupTitle> groupTitleCache = new Dictionary<UUID, GroupTitle>();
1744  
1745 foreach (GroupTitlesReplyPacket.GroupDataBlock block in titles.GroupData)
1746 {
1747 GroupTitle groupTitle = new GroupTitle();
1748  
1749 groupTitle.GroupID = titles.AgentData.GroupID;
1750 groupTitle.RoleID = block.RoleID;
1751 groupTitle.Title = Utils.BytesToString(block.Title);
1752 groupTitle.Selected = block.Selected;
1753  
1754 groupTitleCache[block.RoleID] = groupTitle;
1755 }
1756 OnGroupTitles(new GroupTitlesReplyEventArgs(titles.AgentData.RequestID, titles.AgentData.GroupID, groupTitleCache));
1757 }
1758 }
1759  
1760 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1761 /// <param name="sender">The sender</param>
1762 /// <param name="e">The EventArgs object containing the packet data</param>
1763 protected void GroupMembersHandler(object sender, PacketReceivedEventArgs e)
1764 {
1765 Packet packet = e.Packet;
1766 GroupMembersReplyPacket members = (GroupMembersReplyPacket)packet;
1767 Dictionary<UUID, GroupMember> groupMemberCache = null;
1768  
1769 lock (GroupMembersRequests)
1770 {
1771 // If nothing is registered to receive this RequestID drop the data
1772 if (GroupMembersRequests.Contains(members.GroupData.RequestID))
1773 {
1774 lock (TempGroupMembers.Dictionary)
1775 {
1776 if (!TempGroupMembers.TryGetValue(members.GroupData.RequestID, out groupMemberCache))
1777 {
1778 groupMemberCache = new Dictionary<UUID, GroupMember>();
1779 TempGroupMembers[members.GroupData.RequestID] = groupMemberCache;
1780 }
1781  
1782 foreach (GroupMembersReplyPacket.MemberDataBlock block in members.MemberData)
1783 {
1784 GroupMember groupMember = new GroupMember();
1785  
1786 groupMember.ID = block.AgentID;
1787 groupMember.Contribution = block.Contribution;
1788 groupMember.IsOwner = block.IsOwner;
1789 groupMember.OnlineStatus = Utils.BytesToString(block.OnlineStatus);
1790 groupMember.Powers = (GroupPowers)block.AgentPowers;
1791 groupMember.Title = Utils.BytesToString(block.Title);
1792  
1793 groupMemberCache[block.AgentID] = groupMember;
1794 }
1795  
1796 if (groupMemberCache.Count >= members.GroupData.MemberCount)
1797 {
1798 GroupMembersRequests.Remove(members.GroupData.RequestID);
1799 TempGroupMembers.Remove(members.GroupData.RequestID);
1800 }
1801 }
1802 }
1803 }
1804  
1805 if (m_GroupMembers != null && groupMemberCache != null && groupMemberCache.Count >= members.GroupData.MemberCount)
1806 {
1807 OnGroupMembersReply(new GroupMembersReplyEventArgs(members.GroupData.RequestID, members.GroupData.GroupID, groupMemberCache));
1808 }
1809 }
1810  
1811 protected void GroupMembersHandlerCaps(UUID requestID, OSD result)
1812 {
1813 try
1814 {
1815 OSDMap res = (OSDMap)result;
1816 int memberCount = res["member_count"];
1817 OSDArray titlesOSD = (OSDArray)res["titles"];
1818 string[] titles = new string[titlesOSD.Count];
1819 for (int i = 0; i < titlesOSD.Count; i++)
1820 {
1821 titles[i] = titlesOSD[i];
1822 }
1823 UUID groupID = res["group_id"];
1824 GroupPowers defaultPowers = (GroupPowers)(ulong)((OSDMap)res["defaults"])["default_powers"];
1825 OSDMap membersOSD = (OSDMap)res["members"];
1826 Dictionary<UUID, GroupMember> groupMembers = new Dictionary<UUID, GroupMember>(membersOSD.Count);
1827 foreach (var memberID in membersOSD.Keys)
1828 {
1829 OSDMap member = (OSDMap)membersOSD[memberID];
1830  
1831 GroupMember groupMember = new GroupMember();
1832 groupMember.ID = (UUID)memberID;
1833 groupMember.Contribution = member["donated_square_meters"];
1834 groupMember.IsOwner = "Y" == member["owner"].AsString();
1835 groupMember.OnlineStatus = member["last_login"];
1836 groupMember.Powers = defaultPowers;
1837 if (member.ContainsKey("powers"))
1838 {
1839 groupMember.Powers = (GroupPowers)(ulong)member["powers"];
1840 }
1841 groupMember.Title = titles[(int)member["title"]];
1842  
1843 groupMembers[groupMember.ID] = groupMember;
1844 }
1845  
1846 OnGroupMembersReply(new GroupMembersReplyEventArgs(requestID, groupID, groupMembers));
1847 }
1848 catch (Exception ex)
1849 {
1850 Logger.Log("Failed to decode result of GroupMemberData capability: ", Helpers.LogLevel.Error, Client, ex);
1851 }
1852 }
1853  
1854 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1855 /// <param name="sender">The sender</param>
1856 /// <param name="e">The EventArgs object containing the packet data</param>
1857 protected void GroupRoleDataReplyHandler(object sender, PacketReceivedEventArgs e)
1858 {
1859 Packet packet = e.Packet;
1860 GroupRoleDataReplyPacket roles = (GroupRoleDataReplyPacket)packet;
1861 Dictionary<UUID, GroupRole> groupRoleCache = null;
1862  
1863 lock (GroupRolesRequests)
1864 {
1865 // If nothing is registered to receive this RequestID drop the data
1866 if (GroupRolesRequests.Contains(roles.GroupData.RequestID))
1867 {
1868 lock (TempGroupRoles.Dictionary)
1869 {
1870 if (!TempGroupRoles.TryGetValue(roles.GroupData.RequestID, out groupRoleCache))
1871 {
1872 groupRoleCache = new Dictionary<UUID, GroupRole>();
1873 TempGroupRoles[roles.GroupData.RequestID] = groupRoleCache;
1874 }
1875  
1876 foreach (GroupRoleDataReplyPacket.RoleDataBlock block in roles.RoleData)
1877 {
1878 GroupRole groupRole = new GroupRole();
1879  
1880 groupRole.GroupID = roles.GroupData.GroupID;
1881 groupRole.ID = block.RoleID;
1882 groupRole.Description = Utils.BytesToString(block.Description);
1883 groupRole.Name = Utils.BytesToString(block.Name);
1884 groupRole.Powers = (GroupPowers)block.Powers;
1885 groupRole.Title = Utils.BytesToString(block.Title);
1886  
1887 groupRoleCache[block.RoleID] = groupRole;
1888 }
1889  
1890 if (groupRoleCache.Count >= roles.GroupData.RoleCount)
1891 {
1892 GroupRolesRequests.Remove(roles.GroupData.RequestID);
1893 TempGroupRoles.Remove(roles.GroupData.RequestID);
1894 }
1895 }
1896 }
1897 }
1898  
1899 if (m_GroupRoles != null && groupRoleCache != null && groupRoleCache.Count >= roles.GroupData.RoleCount)
1900 {
1901 OnGroupRoleDataReply(new GroupRolesDataReplyEventArgs(roles.GroupData.RequestID, roles.GroupData.GroupID, groupRoleCache));
1902 }
1903 }
1904  
1905 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1906 /// <param name="sender">The sender</param>
1907 /// <param name="e">The EventArgs object containing the packet data</param>
1908 protected void GroupRoleMembersReplyHandler(object sender, PacketReceivedEventArgs e)
1909 {
1910 Packet packet = e.Packet;
1911 GroupRoleMembersReplyPacket members = (GroupRoleMembersReplyPacket)packet;
1912 List<KeyValuePair<UUID, UUID>> groupRoleMemberCache = null;
1913  
1914 try
1915 {
1916 lock (GroupRolesMembersRequests)
1917 {
1918 // If nothing is registered to receive this RequestID drop the data
1919 if (GroupRolesMembersRequests.Contains(members.AgentData.RequestID))
1920 {
1921 lock (TempGroupRolesMembers.Dictionary)
1922 {
1923 if (!TempGroupRolesMembers.TryGetValue(members.AgentData.RequestID, out groupRoleMemberCache))
1924 {
1925 groupRoleMemberCache = new List<KeyValuePair<UUID, UUID>>();
1926 TempGroupRolesMembers[members.AgentData.RequestID] = groupRoleMemberCache;
1927 }
1928  
1929 foreach (GroupRoleMembersReplyPacket.MemberDataBlock block in members.MemberData)
1930 {
1931 KeyValuePair<UUID, UUID> rolemember =
1932 new KeyValuePair<UUID, UUID>(block.RoleID, block.MemberID);
1933  
1934 groupRoleMemberCache.Add(rolemember);
1935 }
1936  
1937 if (groupRoleMemberCache.Count >= members.AgentData.TotalPairs)
1938 {
1939 GroupRolesMembersRequests.Remove(members.AgentData.RequestID);
1940 TempGroupRolesMembers.Remove(members.AgentData.RequestID);
1941 }
1942 }
1943 }
1944 }
1945 }
1946 catch (Exception ex)
1947 {
1948 Logger.Log(ex.Message, Helpers.LogLevel.Error, Client, ex);
1949 }
1950  
1951 if (m_GroupRoleMembers != null && groupRoleMemberCache != null && groupRoleMemberCache.Count >= members.AgentData.TotalPairs)
1952 {
1953 OnGroupRoleMembers(new GroupRolesMembersReplyEventArgs(members.AgentData.RequestID, members.AgentData.GroupID, groupRoleMemberCache));
1954 }
1955 }
1956  
1957 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1958 /// <param name="sender">The sender</param>
1959 /// <param name="e">The EventArgs object containing the packet data</param>
1960 protected void GroupActiveProposalItemHandler(object sender, PacketReceivedEventArgs e)
1961 {
1962 //GroupActiveProposalItemReplyPacket proposal = (GroupActiveProposalItemReplyPacket)packet;
1963  
1964 // TODO: Create a proposal struct to represent the fields in a proposal item
1965 }
1966  
1967 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1968 /// <param name="sender">The sender</param>
1969 /// <param name="e">The EventArgs object containing the packet data</param>
1970 protected void GroupVoteHistoryItemHandler(object sender, PacketReceivedEventArgs e)
1971 {
1972 //GroupVoteHistoryItemReplyPacket history = (GroupVoteHistoryItemReplyPacket)packet;
1973  
1974 // TODO: This was broken in the official viewer when I was last trying to work on it
1975 }
1976  
1977 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1978 /// <param name="sender">The sender</param>
1979 /// <param name="e">The EventArgs object containing the packet data</param>
1980 protected void GroupAccountSummaryReplyHandler(object sender, PacketReceivedEventArgs e)
1981 {
1982 if (m_GroupAccountSummary != null)
1983 {
1984 Packet packet = e.Packet;
1985 GroupAccountSummaryReplyPacket summary = (GroupAccountSummaryReplyPacket)packet;
1986 GroupAccountSummary account = new GroupAccountSummary();
1987  
1988 account.Balance = summary.MoneyData.Balance;
1989 account.CurrentInterval = summary.MoneyData.CurrentInterval;
1990 account.GroupTaxCurrent = summary.MoneyData.GroupTaxCurrent;
1991 account.GroupTaxEstimate = summary.MoneyData.GroupTaxEstimate;
1992 account.IntervalDays = summary.MoneyData.IntervalDays;
1993 account.LandTaxCurrent = summary.MoneyData.LandTaxCurrent;
1994 account.LandTaxEstimate = summary.MoneyData.LandTaxEstimate;
1995 account.LastTaxDate = Utils.BytesToString(summary.MoneyData.LastTaxDate);
1996 account.LightTaxCurrent = summary.MoneyData.LightTaxCurrent;
1997 account.LightTaxEstimate = summary.MoneyData.LightTaxEstimate;
1998 account.NonExemptMembers = summary.MoneyData.NonExemptMembers;
1999 account.ObjectTaxCurrent = summary.MoneyData.ObjectTaxCurrent;
2000 account.ObjectTaxEstimate = summary.MoneyData.ObjectTaxEstimate;
2001 account.ParcelDirFeeCurrent = summary.MoneyData.ParcelDirFeeCurrent;
2002 account.ParcelDirFeeEstimate = summary.MoneyData.ParcelDirFeeEstimate;
2003 account.StartDate = Utils.BytesToString(summary.MoneyData.StartDate);
2004 account.TaxDate = Utils.BytesToString(summary.MoneyData.TaxDate);
2005 account.TotalCredits = summary.MoneyData.TotalCredits;
2006 account.TotalDebits = summary.MoneyData.TotalDebits;
2007  
2008 OnGroupAccountSummaryReply(new GroupAccountSummaryReplyEventArgs(summary.AgentData.GroupID, account));
2009 }
2010 }
2011  
2012 /// <summary>Process an incoming packet and raise the appropriate events</summary>
2013 /// <param name="sender">The sender</param>
2014 /// <param name="e">The EventArgs object containing the packet data</param>
2015 protected void CreateGroupReplyHandler(object sender, PacketReceivedEventArgs e)
2016 {
2017 if (m_GroupCreated != null)
2018 {
2019 Packet packet = e.Packet;
2020 CreateGroupReplyPacket reply = (CreateGroupReplyPacket)packet;
2021  
2022 string message = Utils.BytesToString(reply.ReplyData.Message);
2023  
2024 OnGroupCreatedReply(new GroupCreatedReplyEventArgs(reply.ReplyData.GroupID, reply.ReplyData.Success, message));
2025 }
2026 }
2027  
2028 /// <summary>Process an incoming packet and raise the appropriate events</summary>
2029 /// <param name="sender">The sender</param>
2030 /// <param name="e">The EventArgs object containing the packet data</param>
2031 protected void JoinGroupReplyHandler(object sender, PacketReceivedEventArgs e)
2032 {
2033 if (m_GroupJoined != null)
2034 {
2035 Packet packet = e.Packet;
2036 JoinGroupReplyPacket reply = (JoinGroupReplyPacket)packet;
2037  
2038 OnGroupJoinedReply(new GroupOperationEventArgs(reply.GroupData.GroupID, reply.GroupData.Success));
2039 }
2040 }
2041  
2042 /// <summary>Process an incoming packet and raise the appropriate events</summary>
2043 /// <param name="sender">The sender</param>
2044 /// <param name="e">The EventArgs object containing the packet data</param>
2045 protected void LeaveGroupReplyHandler(object sender, PacketReceivedEventArgs e)
2046 {
2047 if (m_GroupLeft != null)
2048 {
2049 Packet packet = e.Packet;
2050 LeaveGroupReplyPacket reply = (LeaveGroupReplyPacket)packet;
2051  
2052 OnGroupLeaveReply(new GroupOperationEventArgs(reply.GroupData.GroupID, reply.GroupData.Success));
2053 }
2054 }
2055  
2056 /// <summary>Process an incoming packet and raise the appropriate events</summary>
2057 /// <param name="sender">The sender</param>
2058 /// <param name="e">The EventArgs object containing the packet data</param>
2059 private void UUIDGroupNameReplyHandler(object sender, PacketReceivedEventArgs e)
2060 {
2061 Packet packet = e.Packet;
2062 UUIDGroupNameReplyPacket reply = (UUIDGroupNameReplyPacket)packet;
2063 UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] blocks = reply.UUIDNameBlock;
2064  
2065 Dictionary<UUID, string> groupNames = new Dictionary<UUID, string>();
2066  
2067 foreach (UUIDGroupNameReplyPacket.UUIDNameBlockBlock block in blocks)
2068 {
2069 groupNames.Add(block.ID, Utils.BytesToString(block.GroupName));
2070 if (!GroupName2KeyCache.ContainsKey(block.ID))
2071 GroupName2KeyCache.Add(block.ID, Utils.BytesToString(block.GroupName));
2072 }
2073  
2074 if (m_GroupNames != null)
2075 {
2076 OnGroupNamesReply(new GroupNamesEventArgs(groupNames));
2077 }
2078 }
2079  
2080 /// <summary>Process an incoming packet and raise the appropriate events</summary>
2081 /// <param name="sender">The sender</param>
2082 /// <param name="e">The EventArgs object containing the packet data</param>
2083 protected void EjectGroupMemberReplyHandler(object sender, PacketReceivedEventArgs e)
2084 {
2085 Packet packet = e.Packet;
2086 EjectGroupMemberReplyPacket reply = (EjectGroupMemberReplyPacket)packet;
2087  
2088 // TODO: On Success remove the member from the cache(s)
2089  
2090 if (m_GroupMemberEjected != null)
2091 {
2092 OnGroupMemberEjected(new GroupOperationEventArgs(reply.GroupData.GroupID, reply.EjectData.Success));
2093 }
2094 }
2095  
2096 #endregion Packet Handlers
2097 }
2098  
2099 #region EventArgs
2100  
2101 /// <summary>Contains the current groups your agent is a member of</summary>
2102 public class CurrentGroupsEventArgs : EventArgs
2103 {
2104 private readonly Dictionary<UUID, Group> m_Groups;
2105  
2106 /// <summary>Get the current groups your agent is a member of</summary>
2107 public Dictionary<UUID, Group> Groups { get { return m_Groups; } }
2108  
2109 /// <summary>Construct a new instance of the CurrentGroupsEventArgs class</summary>
2110 /// <param name="groups">The current groups your agent is a member of</param>
2111 public CurrentGroupsEventArgs(Dictionary<UUID, Group> groups)
2112 {
2113 this.m_Groups = groups;
2114 }
2115 }
2116  
2117 /// <summary>A Dictionary of group names, where the Key is the groups ID and the value is the groups name</summary>
2118 public class GroupNamesEventArgs : EventArgs
2119 {
2120 private readonly Dictionary<UUID, string> m_GroupNames;
2121  
2122 /// <summary>Get the Group Names dictionary</summary>
2123 public Dictionary<UUID, string> GroupNames { get { return m_GroupNames; } }
2124  
2125 /// <summary>Construct a new instance of the GroupNamesEventArgs class</summary>
2126 /// <param name="groupNames">The Group names dictionary</param>
2127 public GroupNamesEventArgs(Dictionary<UUID, string> groupNames)
2128 {
2129 this.m_GroupNames = groupNames;
2130 }
2131 }
2132  
2133 /// <summary>Represents the members of a group</summary>
2134 public class GroupMembersReplyEventArgs : EventArgs
2135 {
2136 private readonly UUID m_RequestID;
2137 private readonly UUID m_GroupID;
2138 private readonly Dictionary<UUID, GroupMember> m_Members;
2139  
2140 /// <summary>Get the ID as returned by the request to correlate
2141 /// this result set and the request</summary>
2142 public UUID RequestID { get { return m_RequestID; } }
2143 /// <summary>Get the ID of the group</summary>
2144 public UUID GroupID { get { return m_GroupID; } }
2145 /// <summary>Get the dictionary of members</summary>
2146 public Dictionary<UUID, GroupMember> Members { get { return m_Members; } }
2147  
2148 /// <summary>
2149 /// Construct a new instance of the GroupMembersReplyEventArgs class
2150 /// </summary>
2151 /// <param name="requestID">The ID of the request</param>
2152 /// <param name="groupID">The ID of the group</param>
2153 /// <param name="members">The membership list of the group</param>
2154 public GroupMembersReplyEventArgs(UUID requestID, UUID groupID, Dictionary<UUID, GroupMember> members)
2155 {
2156 this.m_RequestID = requestID;
2157 this.m_GroupID = groupID;
2158 this.m_Members = members;
2159 }
2160 }
2161  
2162 /// <summary>Represents the roles associated with a group</summary>
2163 public class GroupRolesDataReplyEventArgs : EventArgs
2164 {
2165 private readonly UUID m_RequestID;
2166 private readonly UUID m_GroupID;
2167 private readonly Dictionary<UUID, GroupRole> m_Roles;
2168  
2169 /// <summary>Get the ID as returned by the request to correlate
2170 /// this result set and the request</summary>
2171 public UUID RequestID { get { return m_RequestID; } }
2172 /// <summary>Get the ID of the group</summary>
2173 public UUID GroupID { get { return m_GroupID; } }
2174 /// <summary>Get the dictionary containing the roles</summary>
2175 public Dictionary<UUID, GroupRole> Roles { get { return m_Roles; } }
2176  
2177 /// <summary>Construct a new instance of the GroupRolesDataReplyEventArgs class</summary>
2178 /// <param name="requestID">The ID as returned by the request to correlate
2179 /// this result set and the request</param>
2180 /// <param name="groupID">The ID of the group</param>
2181 /// <param name="roles">The dictionary containing the roles</param>
2182 public GroupRolesDataReplyEventArgs(UUID requestID, UUID groupID, Dictionary<UUID, GroupRole> roles)
2183 {
2184 this.m_RequestID = requestID;
2185 this.m_GroupID = groupID;
2186 this.m_Roles = roles;
2187 }
2188 }
2189  
2190 /// <summary>Represents the Role to Member mappings for a group</summary>
2191 public class GroupRolesMembersReplyEventArgs : EventArgs
2192 {
2193 private readonly UUID m_RequestID;
2194 private readonly UUID m_GroupID;
2195 private readonly List<KeyValuePair<UUID, UUID>> m_RolesMembers;
2196  
2197 /// <summary>Get the ID as returned by the request to correlate
2198 /// this result set and the request</summary>
2199 public UUID RequestID { get { return m_RequestID; } }
2200 /// <summary>Get the ID of the group</summary>
2201 public UUID GroupID { get { return m_GroupID; } }
2202 /// <summary>Get the member to roles map</summary>
2203 public List<KeyValuePair<UUID, UUID>> RolesMembers { get { return m_RolesMembers; } }
2204  
2205 /// <summary>Construct a new instance of the GroupRolesMembersReplyEventArgs class</summary>
2206 /// <param name="requestID">The ID as returned by the request to correlate
2207 /// this result set and the request</param>
2208 /// <param name="groupID">The ID of the group</param>
2209 /// <param name="rolesMembers">The member to roles map</param>
2210 public GroupRolesMembersReplyEventArgs(UUID requestID, UUID groupID, List<KeyValuePair<UUID, UUID>> rolesMembers)
2211 {
2212 this.m_RequestID = requestID;
2213 this.m_GroupID = groupID;
2214 this.m_RolesMembers = rolesMembers;
2215 }
2216 }
2217  
2218 /// <summary>Represents the titles for a group</summary>
2219 public class GroupTitlesReplyEventArgs : EventArgs
2220 {
2221 private readonly UUID m_RequestID;
2222 private readonly UUID m_GroupID;
2223 private readonly Dictionary<UUID, GroupTitle> m_Titles;
2224  
2225 /// <summary>Get the ID as returned by the request to correlate
2226 /// this result set and the request</summary>
2227 public UUID RequestID { get { return m_RequestID; } }
2228 /// <summary>Get the ID of the group</summary>
2229 public UUID GroupID { get { return m_GroupID; } }
2230 /// <summary>Get the titles</summary>
2231 public Dictionary<UUID, GroupTitle> Titles { get { return m_Titles; } }
2232  
2233 /// <summary>Construct a new instance of the GroupTitlesReplyEventArgs class</summary>
2234 /// <param name="requestID">The ID as returned by the request to correlate
2235 /// this result set and the request</param>
2236 /// <param name="groupID">The ID of the group</param>
2237 /// <param name="titles">The titles</param>
2238 public GroupTitlesReplyEventArgs(UUID requestID, UUID groupID, Dictionary<UUID, GroupTitle> titles)
2239 {
2240 this.m_RequestID = requestID;
2241 this.m_GroupID = groupID;
2242 this.m_Titles = titles;
2243 }
2244 }
2245  
2246 /// <summary>Represents the summary data for a group</summary>
2247 public class GroupAccountSummaryReplyEventArgs : EventArgs
2248 {
2249 private readonly UUID m_GroupID;
2250 private readonly GroupAccountSummary m_Summary;
2251  
2252 /// <summary>Get the ID of the group</summary>
2253 public UUID GroupID { get { return m_GroupID; } }
2254 /// <summary>Get the summary data</summary>
2255 public GroupAccountSummary Summary { get { return m_Summary; } }
2256  
2257 /// <summary>Construct a new instance of the GroupAccountSummaryReplyEventArgs class</summary>
2258 /// <param name="groupID">The ID of the group</param>
2259 /// <param name="summary">The summary data</param>
2260 public GroupAccountSummaryReplyEventArgs(UUID groupID, GroupAccountSummary summary)
2261 {
2262 this.m_GroupID = groupID;
2263 this.m_Summary = summary;
2264 }
2265 }
2266  
2267 /// <summary>A response to a group create request</summary>
2268 public class GroupCreatedReplyEventArgs : EventArgs
2269 {
2270 private readonly UUID m_GroupID;
2271 private readonly bool m_Success;
2272 private readonly string m_Message;
2273  
2274 /// <summary>Get the ID of the group</summary>
2275 public UUID GroupID { get { return m_GroupID; } }
2276 /// <summary>true of the group was created successfully</summary>
2277 public bool Success { get { return m_Success; } }
2278 /// <summary>A string containing the message</summary>
2279 public string Message { get { return m_Message; } }
2280  
2281 /// <summary>Construct a new instance of the GroupCreatedReplyEventArgs class</summary>
2282 /// <param name="groupID">The ID of the group</param>
2283 /// <param name="success">the success or faulure of the request</param>
2284 /// <param name="messsage">A string containing additional information</param>
2285 public GroupCreatedReplyEventArgs(UUID groupID, bool success, string messsage)
2286 {
2287 this.m_GroupID = groupID;
2288 this.m_Success = success;
2289 this.m_Message = messsage;
2290 }
2291 }
2292  
2293 /// <summary>Represents a response to a request</summary>
2294 public class GroupOperationEventArgs : EventArgs
2295 {
2296 private readonly UUID m_GroupID;
2297 private readonly bool m_Success;
2298  
2299 /// <summary>Get the ID of the group</summary>
2300 public UUID GroupID { get { return m_GroupID; } }
2301 /// <summary>true of the request was successful</summary>
2302 public bool Success { get { return m_Success; } }
2303  
2304 /// <summary>Construct a new instance of the GroupOperationEventArgs class</summary>
2305 /// <param name="groupID">The ID of the group</param>
2306 /// <param name="success">true of the request was successful</param>
2307 public GroupOperationEventArgs(UUID groupID, bool success)
2308 {
2309 this.m_GroupID = groupID;
2310 this.m_Success = success;
2311 }
2312 }
2313  
2314 /// <summary>Represents your agent leaving a group</summary>
2315 public class GroupDroppedEventArgs : EventArgs
2316 {
2317 private readonly UUID m_GroupID;
2318 /// <summary>Get the ID of the group</summary>
2319 public UUID GroupID { get { return m_GroupID; } }
2320  
2321 /// <summary>Construct a new instance of the GroupDroppedEventArgs class</summary>
2322 /// <param name="groupID">The ID of the group</param>
2323 public GroupDroppedEventArgs(UUID groupID)
2324 {
2325 m_GroupID = groupID;
2326 }
2327 }
2328  
2329 /// <summary>Represents a list of active group notices</summary>
2330 public class GroupNoticesListReplyEventArgs : EventArgs
2331 {
2332 private readonly UUID m_GroupID;
2333 private readonly List<GroupNoticesListEntry> m_Notices;
2334  
2335 /// <summary>Get the ID of the group</summary>
2336 public UUID GroupID { get { return m_GroupID; } }
2337 /// <summary>Get the notices list</summary>
2338 public List<GroupNoticesListEntry> Notices { get { return m_Notices; } }
2339  
2340 /// <summary>Construct a new instance of the GroupNoticesListReplyEventArgs class</summary>
2341 /// <param name="groupID">The ID of the group</param>
2342 /// <param name="notices">The list containing active notices</param>
2343 public GroupNoticesListReplyEventArgs(UUID groupID, List<GroupNoticesListEntry> notices)
2344 {
2345 m_GroupID = groupID;
2346 m_Notices = notices;
2347 }
2348 }
2349  
2350 /// <summary>Represents the profile of a group</summary>
2351 public class GroupProfileEventArgs : EventArgs
2352 {
2353 private readonly Group m_Group;
2354  
2355 /// <summary>Get the group profile</summary>
2356 public Group Group { get { return m_Group; } }
2357  
2358 /// <summary>Construct a new instance of the GroupProfileEventArgs class</summary>
2359 /// <param name="group">The group profile</param>
2360 public GroupProfileEventArgs(Group group)
2361 {
2362 this.m_Group = group;
2363 }
2364 }
2365  
2366 /// <summary>
2367 /// Provides notification of a group invitation request sent by another Avatar
2368 /// </summary>
2369 /// <remarks>The <see cref="GroupInvitation"/> invitation is raised when another avatar makes an offer for our avatar
2370 /// to join a group.</remarks>
2371 public class GroupInvitationEventArgs : EventArgs
2372 {
2373 private readonly UUID m_FromAgentID;
2374 private readonly string m_FromAgentName;
2375 private readonly string m_Message;
2376 private readonly Simulator m_Simulator;
2377  
2378 /// <summary>The ID of the Avatar sending the group invitation</summary>
2379 public UUID AgentID { get { return m_FromAgentID; } }
2380 /// <summary>The name of the Avatar sending the group invitation</summary>
2381 public string FromName { get { return m_FromAgentName; } }
2382 /// <summary>A message containing the request information which includes
2383 /// the name of the group, the groups charter and the fee to join details</summary>
2384 public string Message { get { return m_Message; } }
2385 /// <summary>The Simulator</summary>
2386 public Simulator Simulator { get { return m_Simulator; } }
2387  
2388 /// <summary>Set to true to accept invitation, false to decline</summary>
2389 public bool Accept { get; set; }
2390  
2391 public GroupInvitationEventArgs(Simulator simulator, UUID agentID, string agentName, string message)
2392 {
2393 this.m_Simulator = simulator;
2394 this.m_FromAgentID = agentID;
2395 this.m_FromAgentName = agentName;
2396 this.m_Message = message;
2397 }
2398 }
2399  
2400 /// <summary>
2401 /// Result of the request for list of agents banned from a group
2402 /// </summary>
2403 public class BannedAgentsEventArgs : EventArgs
2404 {
2405 readonly UUID mGroupID;
2406 readonly bool mSuccess;
2407 readonly Dictionary<UUID, DateTime> mBannedAgents;
2408  
2409 /// <summary> Indicates if list of banned agents for a group was successfully retrieved </summary>
2410 public UUID GroupID { get { return mGroupID; } }
2411  
2412 /// <summary> Indicates if list of banned agents for a group was successfully retrieved </summary>
2413 public bool Success { get { return mSuccess; } }
2414  
2415 /// <summary> Array containing a list of UUIDs of the agents banned from a group </summary>
2416 public Dictionary<UUID, DateTime> BannedAgents { get { return mBannedAgents; } }
2417  
2418 public BannedAgentsEventArgs(UUID groupID, bool success, Dictionary<UUID, DateTime> bannedAgents)
2419 {
2420 this.mGroupID = groupID;
2421 this.mSuccess = success;
2422 this.mBannedAgents = bannedAgents;
2423 }
2424 }
2425  
2426 #endregion
2427 }