/* * Copyright (c) 2006, Second Life Reverse Engineering Team * All rights reserved. * * - Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * - Neither the name of the Second Life Reverse Engineering Team nor the names * of its contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Collections.Generic; using libsecondlife.Packets; namespace libsecondlife { public class GroupMember { public LLUUID ID; public int Contribution; public string OnlineStatus; public ulong Powers; public string Title; public bool IsOwner; public GroupMember(LLUUID id) { ID = id; } } public class GroupRole { public LLUUID ID; public string Name; public string Title; public string Description; public ulong Powers; public GroupRole(LLUUID id) { ID = id; } } public class GroupTitle { public string Title; public bool Selected; } /// /// Represents a group in Second Life /// public class Group { public LLUUID ID; public LLUUID InsigniaID; public LLUUID FounderID; public LLUUID OwnerRole; public string Name; public string Charter; public string MemberTitle; public bool OpenEnrollment; public bool ShowInList; public ulong Powers; public bool AcceptNotices; public bool AllowPublish; public bool MaturePublish; public int MembershipFee; public int Money; public int Contribution; public int GroupMembershipCount; public int GroupRolesCount; public Group(LLUUID id) { ID = id; InsigniaID = new LLUUID(); } public override string ToString() { return Name; } } public class GroupProfile { public LLUUID ID; public LLUUID InsigniaID; public LLUUID FounderID; public LLUUID OwnerRole; public string Name; public string Charter; public string MemberTitle; public bool OpenEnrollment; public bool ShowInList; public ulong Powers; public bool AcceptNotices; public bool AllowPublish; public bool MaturePublish; public int MembershipFee; public int Money; public int Contribution; public int GroupMembershipCount; public int GroupRolesCount; } /// /// Handles all network traffic related to reading and writing group /// information /// public class GroupManager { /// /// Callback for the list of groups the avatar is currently a member of /// /// public delegate void CurrentGroupsCallback(Dictionary groups); /// /// Callback for the profile of a group /// /// public delegate void GroupProfileCallback(GroupProfile group); /// /// Callback for the member list of a group /// /// public delegate void GroupMembersCallback(Dictionary members); /// /// Callback for the role list of a group /// /// public delegate void GroupRolesCallback(Dictionary roles); /// /// Callback for the title list of a group /// /// public delegate void GroupTitlesCallback(Dictionary titles); private SecondLife Client; // No need for concurrency with the current group list request private CurrentGroupsCallback OnCurrentGroups; private Dictionary GroupProfileCallbacks; private Dictionary GroupMembersCallbacks; private Dictionary GroupRolesCallbacks; private Dictionary GroupTitlesCallbacks; /// A list of all the lists of group members, indexed by the request ID private Dictionary> GroupMembersCaches; /// A list of all the lists of group roles, indexed by the request ID private Dictionary> GroupRolesCaches; /// /// /// /// public GroupManager(SecondLife client) { Client = client; GroupProfileCallbacks = new Dictionary(); GroupMembersCallbacks = new Dictionary(); GroupRolesCallbacks = new Dictionary(); GroupTitlesCallbacks = new Dictionary(); GroupMembersCaches = new Dictionary>(); GroupRolesCaches = new Dictionary>(); Client.Network.RegisterCallback(PacketType.AgentGroupDataUpdate, new PacketCallback(GroupDataHandler)); Client.Network.RegisterCallback(PacketType.GroupTitlesReply, new PacketCallback(GroupTitlesHandler)); Client.Network.RegisterCallback(PacketType.GroupProfileReply, new PacketCallback(GroupProfileHandler)); Client.Network.RegisterCallback(PacketType.GroupMembersReply, new PacketCallback(GroupMembersHandler)); Client.Network.RegisterCallback(PacketType.GroupRoleDataReply, new PacketCallback(GroupRoleDataHandler)); Client.Network.RegisterCallback(PacketType.GroupRoleMembersReply, new PacketCallback(GroupRoleMembersHandler)); Client.Network.RegisterCallback(PacketType.GroupActiveProposalItemReply, new PacketCallback(GroupActiveProposalItemHandler)); Client.Network.RegisterCallback(PacketType.GroupVoteHistoryItemReply, new PacketCallback(GroupVoteHistoryItemHandler)); Client.Network.RegisterCallback(PacketType.GroupAccountSummaryReply, new PacketCallback(GroupAccountSummaryHandler)); Client.Network.RegisterCallback(PacketType.GroupAccountDetailsReply, new PacketCallback(GroupAccountDetailsHandler)); Client.Network.RegisterCallback(PacketType.GroupAccountTransactionsReply, new PacketCallback(GroupAccountTransactionsHandler)); } /// /// /// /// public void BeginGetCurrentGroups(CurrentGroupsCallback cgc) { OnCurrentGroups = cgc; AgentDataUpdateRequestPacket request = new AgentDataUpdateRequestPacket(); request.AgentData.AgentID = Client.Network.AgentID; request.AgentData.SessionID = Client.Network.SessionID; Client.Network.SendPacket(request); } /// /// /// /// /// public void BeginGetGroupProfile(LLUUID group, GroupProfileCallback gpc) { GroupProfileCallbacks[group] = gpc; GroupProfileRequestPacket request = new GroupProfileRequestPacket(); request.AgentData.AgentID = Client.Network.AgentID; request.AgentData.SessionID = Client.Network.SessionID; request.GroupData.GroupID = group; Client.Network.SendPacket(request); } /// /// /// /// /// public void BeginGetGroupMembers(LLUUID group, GroupMembersCallback gmc) { LLUUID requestID = LLUUID.GenerateUUID(); lock (GroupMembersCaches) { GroupMembersCaches[requestID] = new Dictionary(); } GroupMembersCallbacks[group] = gmc; GroupMembersRequestPacket request = new GroupMembersRequestPacket(); request.AgentData.AgentID = Client.Network.AgentID; request.AgentData.SessionID = Client.Network.SessionID; request.GroupData.GroupID = group; request.GroupData.RequestID = requestID; Client.Network.SendPacket(request); } public void BeginGetGroupRoles(LLUUID group, GroupRolesCallback grc) { LLUUID requestID = LLUUID.GenerateUUID(); lock (GroupRolesCaches) { GroupRolesCaches[requestID] = new Dictionary(); } GroupRolesCallbacks[group] = grc; GroupRoleDataRequestPacket request = new GroupRoleDataRequestPacket(); request.AgentData.AgentID = Client.Network.AgentID; request.AgentData.SessionID = Client.Network.SessionID; request.GroupData.GroupID = group; request.GroupData.RequestID = requestID; Client.Network.SendPacket(request); } public void BeginGetGroupTitles(LLUUID group, GroupTitlesCallback gtc) { LLUUID requestID = LLUUID.GenerateUUID(); GroupTitlesCallbacks[group] = gtc; GroupTitlesRequestPacket request = new GroupTitlesRequestPacket(); request.AgentData.AgentID = Client.Network.AgentID; request.AgentData.SessionID = Client.Network.SessionID; request.AgentData.GroupID = group; request.AgentData.RequestID = requestID; Client.Network.SendPacket(request); } private void GroupDataHandler(Packet packet, Simulator simulator) { if (OnCurrentGroups != null) { AgentGroupDataUpdatePacket update = (AgentGroupDataUpdatePacket)packet; Dictionary currentGroups = new Dictionary(); foreach (AgentGroupDataUpdatePacket.GroupDataBlock block in update.GroupData) { Group group = new Group(block.GroupID); group.InsigniaID = block.GroupInsigniaID; group.Name = Helpers.FieldToString(block.GroupName); group.Powers = block.GroupPowers; group.Contribution = block.Contribution; group.AcceptNotices = block.AcceptNotices; currentGroups[block.GroupID] = group; } if (OnCurrentGroups != null) { OnCurrentGroups(currentGroups); } } } private void GroupProfileHandler(Packet packet, Simulator simulator) { GroupProfileReplyPacket profile = (GroupProfileReplyPacket)packet; if (GroupProfileCallbacks.ContainsKey(profile.GroupData.GroupID)) { GroupProfile group = new GroupProfile(); group.AllowPublish = profile.GroupData.AllowPublish; group.Charter = Helpers.FieldToString(profile.GroupData.Charter); group.FounderID = profile.GroupData.FounderID; group.GroupMembershipCount = profile.GroupData.GroupMembershipCount; group.GroupRolesCount = profile.GroupData.GroupRolesCount; group.InsigniaID = profile.GroupData.InsigniaID; group.MaturePublish = profile.GroupData.MaturePublish; group.MembershipFee = profile.GroupData.MembershipFee; group.MemberTitle = Helpers.FieldToString(profile.GroupData.MemberTitle); group.Money = profile.GroupData.Money; group.Name = Helpers.FieldToString(profile.GroupData.Name); group.OpenEnrollment = profile.GroupData.OpenEnrollment; group.OwnerRole = profile.GroupData.OwnerRole; group.Powers = profile.GroupData.PowersMask; group.ShowInList = profile.GroupData.ShowInList; GroupProfileCallbacks[profile.GroupData.GroupID](group); } } private void GroupTitlesHandler(Packet packet, Simulator simulator) { GroupTitlesReplyPacket titles = (GroupTitlesReplyPacket)packet; Dictionary groupTitleCache = new Dictionary(); foreach (GroupTitlesReplyPacket.GroupDataBlock block in titles.GroupData) { GroupTitle groupTitle = new GroupTitle(); groupTitle.Title = Helpers.FieldToString(block.Title); groupTitle.Selected = block.Selected; groupTitleCache[block.RoleID] = groupTitle; } GroupTitlesCallbacks[titles.AgentData.GroupID](groupTitleCache); } private void GroupMembersHandler(Packet packet, Simulator simulator) { GroupMembersReplyPacket members = (GroupMembersReplyPacket)packet; Dictionary groupMemberCache = null; lock (GroupMembersCaches) { // If nothing is registered to receive this RequestID drop the data if (GroupMembersCaches.ContainsKey(members.GroupData.RequestID)) { groupMemberCache = GroupMembersCaches[members.GroupData.RequestID]; foreach (GroupMembersReplyPacket.MemberDataBlock block in members.MemberData) { GroupMember groupMember = new GroupMember(block.AgentID); groupMember.Contribution = block.Contribution; groupMember.IsOwner = block.IsOwner; groupMember.OnlineStatus = Helpers.FieldToString(block.OnlineStatus); groupMember.Powers = block.AgentPowers; groupMember.Title = Helpers.FieldToString(block.Title); groupMemberCache[block.AgentID] = groupMember; } } } // Check if we've received all the group members that are showing up if (groupMemberCache != null && groupMemberCache.Count >= members.GroupData.MemberCount) { GroupMembersCallbacks[members.GroupData.GroupID](groupMemberCache); } } private void GroupRoleDataHandler(Packet packet, Simulator simulator) { GroupRoleDataReplyPacket roles = (GroupRoleDataReplyPacket)packet; Dictionary groupRoleCache = null; lock (GroupRolesCaches) { // If nothing is registered to receive this RequestID drop the data if (GroupRolesCaches.ContainsKey(roles.GroupData.RequestID)) { groupRoleCache = GroupRolesCaches[roles.GroupData.RequestID]; foreach (GroupRoleDataReplyPacket.RoleDataBlock block in roles.RoleData) { GroupRole groupRole = new GroupRole(block.RoleID); groupRole.Description = Helpers.FieldToString(block.Description); groupRole.Name = Helpers.FieldToString(block.Name); groupRole.Powers = block.Powers; groupRole.Title = Helpers.FieldToString(block.Title); groupRoleCache[block.RoleID] = groupRole; } } } // Check if we've received all the group members that are showing up if (groupRoleCache != null && groupRoleCache.Count >= roles.GroupData.RoleCount) { GroupRolesCallbacks[roles.GroupData.GroupID](groupRoleCache); } } private void GroupRoleMembersHandler(Packet packet, Simulator simulator) { GroupRoleMembersReplyPacket members = (GroupRoleMembersReplyPacket)packet; } private void GroupActiveProposalItemHandler(Packet packet, Simulator simulator) { ; } private void GroupVoteHistoryItemHandler(Packet packet, Simulator simulator) { ; } private void GroupAccountSummaryHandler(Packet packet, Simulator simulator) { ; } private void GroupAccountDetailsHandler(Packet packet, Simulator simulator) { ; } private void GroupAccountTransactionsHandler(Packet packet, Simulator simulator) { ; } } }