/*
* 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
{
#region Structs
///
/// Avatar group management
///
public struct GroupMember
{
/// Key of Group Member
public LLUUID ID;
/// Total land contribution
public int Contribution;
/// Online status information
public string OnlineStatus;
/// Abilities that the Group Member has
public ulong Powers;
/// Current group title
public string Title;
/// Is a group owner
public bool IsOwner;
}
///
/// Role manager for a group
///
public struct GroupRole
{
/// Key of Role
public LLUUID ID;
/// Name of Role
public string Name;
/// Group Title associated with Role
public string Title;
/// Description of Role
public string Description;
/// Abilities Associated with Role
public ulong Powers;
///
/// Returns the role's title
///
/// The role's title
public override string ToString()
{
return Name;
}
}
///
/// Class to represent Group Title
///
public struct GroupTitle
{
/// Group Title
public string Title;
/// Whether title is Active
public bool Selected;
}
///
/// Represents a group in Second Life
///
public struct Group
{
/// Key of Group
public LLUUID ID;
/// Key of Group Insignia
public LLUUID InsigniaID;
/// Key of Group Founder
public LLUUID FounderID;
/// Key of Group Role for Owners
public LLUUID OwnerRole;
/// Name of Group
public string Name;
/// Text of Group Charter
public string Charter;
/// Title of "everyone" role
public string MemberTitle;
/// Is the group open for enrolement to everyone
public bool OpenEnrollment;
/// Will group show up in search
public bool ShowInList;
///
public ulong Powers;
///
public bool AcceptNotices;
///
public bool AllowPublish;
/// Is the group Mature
public bool MaturePublish;
/// Cost of group membership
public int MembershipFee;
///
public int Money;
///
public int Contribution;
///
public int GroupMembershipCount;
///
public int GroupRolesCount;
///
/// Returns the name of the group
///
///
public override string ToString()
{
return Name;
}
}
///
/// Profile of a group
///
public struct GroupProfile
{
///
public LLUUID ID;
/// Key of Group Insignia
public LLUUID InsigniaID;
/// Key of Group Founder
public LLUUID FounderID;
/// Key of Group Role for Owners
public LLUUID OwnerRole;
/// Name of Group
public string Name;
/// Text of Group Charter
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;
}
///
/// A group Vote
///
public struct Vote
{
/// Key of Avatar who created Vote
public LLUUID Candidate;
/// Text of the Vote proposal
public string VoteString;
/// Total number of votes
public int NumVotes;
}
public struct GroupProposal
{
public string VoteText;
public int Quorum;
public float Majority;
public int Duration;
}
///
///
///
public struct GroupAccountSummary
{
///
public int IntervalDays;
///
public int CurrentInterval;
///
public string StartDate;
///
public int Balance;
///
public int TotalCredits;
///
public int TotalDebits;
///
public int ObjectTaxCurrent;
///
public int LightTaxCurrent;
///
public int LandTaxCurrent;
///
public int GroupTaxCurrent;
///
public int ParcelDirFeeCurrent;
///
public int ObjectTaxEstimate;
///
public int LightTaxEstimate;
///
public int LandTaxEstimate;
///
public int GroupTaxEstimate;
///
public int ParcelDirFeeEstimate;
///
public int NonExemptMembers;
///
public string LastTaxDate;
///
public string TaxDate;
}
///
///
///
public struct GroupAccountDetails
{
///
public int IntervalDays;
///
public int CurrentInterval;
///
public string StartDate;
/// A list of description/amount pairs making up the account
/// history
public List> HistoryItems;
}
///
///
///
public struct GroupAccountTransactions
{
///
public int IntervalDays;
///
public int CurrentInterval;
///
public string StartDate;
/// List of all the transactions for this group
public List Transactions;
}
///
/// A single transaction made by a group
///
public struct Transaction
{
///
public string Time;
///
public string User;
///
public int Type;
///
public string Item;
///
public int Amount;
}
///
/// Struct representing a group notice
///
public struct GroupNotice
{
///
public string Subject;
///
public string Message;
///
public LLUUID AttachmentID;
///
public LLUUID OwnerID;
///
///
///
///
public byte[] SerializeAttachment()
{
if (OwnerID == null || OwnerID == LLUUID.Zero || AttachmentID == null || AttachmentID == LLUUID.Zero)
return new byte[0];
//I guess this is how this works, no gaurentees
string lsd = "" + AttachmentID.ToString() + ""
+ OwnerID.ToString() + "";
return Helpers.StringToField(lsd);
}
}
#endregion Structs
#region Enums
///
/// Role update flags
///
public enum GroupRoleUpdate : uint
{
NoUpdate,
UpdateData,
UpdatePowers,
UpdateAll,
Create,
Delete
}
///
/// Group role powers flags
///
[Flags]
public enum GroupRolePowers : long
{
None = 0,
Invite = 1 << 1,
Eject = 1 << 2,
ChangeOptions = 1 << 3,
CreateRole = 1 << 4,
DeleteRole = 1 << 5,
RoleProperties = 1 << 6,
AssignMemberLimited = 1 << 7,
AssignMember = 1 << 8,
RemoveMember = 1 << 9,
ChangeActions = 1 << 10,
ChangeIdentity = 1 << 11,
LandDeed = 1 << 12,
LandRelease = 1 << 13,
LandSetSale = 1 << 14,
LandDevideJoin = 1 << 15,
FindPlaces = 1 << 17,
LandChangeIdentity = 1 << 18,
SetLandingPoint = 1 << 19,
ChangeMedia = 1 << 20,
LandEdit = 1 << 21,
LandOptions = 1 << 22,
AllowEditLand = 1 << 23,
AllowFly = 1 << 24,
AllowRez = 1 << 25,
AllowLandmark = 1 << 26,
AllowSetHome = 1 << 28,
LandManageAllowed = 1 << 29,
LandManageBanned = 1 << 30,
LandManagePasses = 1 << 31,
LandEjectAndFreeze = 1 << 32,
ReturnGroupOwned = 1 << 48,
ReturnGroupSet = 1 << 33,
ReturnNonGroup = 1 << 34,
LandGardening = 1 << 35,
DeedObject = 1 << 36,
ObjectManipulate = 1 << 38,
ObjectSetForSale = 1 << 39,
Accountable = 1 << 40,
SendNotices = 1 << 42,
ReceiveNotices = 1 << 43,
StartProposal = 1 << 44,
VoteOnProposal = 1 << 45
}
#endregion Enums
///
/// Handles all network traffic related to reading and writing group
/// information
///
public class GroupManager
{
#region Delegates
///
/// 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 a pairing of roles to members
///
///
public delegate void GroupRolesMembersCallback(List> rolesMembers);
///
/// Callback for the title list of a group
///
///
public delegate void GroupTitlesCallback(Dictionary titles);
///
///
///
///
public delegate void GroupAccountSummaryCallback(GroupAccountSummary summary);
///
///
///
///
public delegate void GroupAccountDetailsCallback(GroupAccountDetails details);
///
///
///
///
public delegate void GroupAccountTransactionsCallback(GroupAccountTransactions transactions);
#endregion Delegates
#region Events
///
public event CurrentGroupsCallback OnCurrentGroups;
///
public event GroupProfileCallback OnGroupProfile;
///
public event GroupMembersCallback OnGroupMembers;
///
public event GroupRolesCallback OnGroupRoles;
///
public event GroupRolesMembersCallback OnGroupRolesMembers;
///
public event GroupTitlesCallback OnGroupTitles;
///
public event GroupAccountSummaryCallback OnGroupAccountSummary;
///
public event GroupAccountDetailsCallback OnGroupAccountDetails;
///
//public event GroupAccountTransactionsCallback OnGroupAccountTransactions;
#endregion Events
private SecondLife Client;
/// 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;
/// A list of all the role to member mappings
private Dictionary>> GroupRolesMembersCaches;
///
///
///
///
public GroupManager(SecondLife client)
{
Client = client;
GroupMembersCaches = new Dictionary>();
GroupRolesCaches = new Dictionary>();
GroupRolesMembersCaches = new Dictionary>>();
Client.Network.RegisterCallback(PacketType.AgentGroupDataUpdate, new NetworkManager.PacketCallback(GroupDataHandler));
Client.Network.RegisterCallback(PacketType.GroupTitlesReply, new NetworkManager.PacketCallback(GroupTitlesHandler));
Client.Network.RegisterCallback(PacketType.GroupProfileReply, new NetworkManager.PacketCallback(GroupProfileHandler));
Client.Network.RegisterCallback(PacketType.GroupMembersReply, new NetworkManager.PacketCallback(GroupMembersHandler));
Client.Network.RegisterCallback(PacketType.GroupRoleDataReply, new NetworkManager.PacketCallback(GroupRoleDataHandler));
Client.Network.RegisterCallback(PacketType.GroupRoleMembersReply, new NetworkManager.PacketCallback(GroupRoleMembersHandler));
Client.Network.RegisterCallback(PacketType.GroupActiveProposalItemReply, new NetworkManager.PacketCallback(GroupActiveProposalItemHandler));
Client.Network.RegisterCallback(PacketType.GroupVoteHistoryItemReply, new NetworkManager.PacketCallback(GroupVoteHistoryItemHandler));
Client.Network.RegisterCallback(PacketType.GroupAccountSummaryReply, new NetworkManager.PacketCallback(GroupAccountSummaryHandler));
Client.Network.RegisterCallback(PacketType.GroupAccountDetailsReply, new NetworkManager.PacketCallback(GroupAccountDetailsHandler));
Client.Network.RegisterCallback(PacketType.GroupAccountTransactionsReply, new NetworkManager.PacketCallback(GroupAccountTransactionsHandler));
}
///
///
///
public void BeginGetCurrentGroups()
{
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)
{
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)
{
LLUUID requestID = LLUUID.Random();
lock (GroupMembersCaches) GroupMembersCaches[requestID] = new Dictionary();
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)
{
LLUUID requestID = LLUUID.Random();
lock (GroupRolesCaches) GroupRolesCaches[requestID] = new Dictionary();
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 BeginGetGroupRoleMembers(LLUUID group)
{
LLUUID requestID = LLUUID.Random();
lock (GroupRolesMembersCaches)
{
GroupRolesMembersCaches[requestID] = new List>();
}
GroupRoleMembersRequestPacket request = new GroupRoleMembersRequestPacket();
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)
{
LLUUID requestID = LLUUID.Random();
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);
}
///
/// Begin to get the group account summary
///
/// The group's ID
/// How long of an interval
/// Which interval (0 for current, 1 for last)
public void BeginGetGroupAccountSummary(LLUUID group, int intervalDays, int currentInterval)
{
GroupAccountSummaryRequestPacket p = new GroupAccountSummaryRequestPacket();
p.AgentData.AgentID = Client.Network.AgentID;
p.AgentData.SessionID = Client.Network.SessionID;
p.AgentData.GroupID = group;
p.MoneyData.RequestID = LLUUID.Random();
p.MoneyData.CurrentInterval = currentInterval;
p.MoneyData.IntervalDays = intervalDays;
Client.Network.SendPacket(p);
}
///
/// Invites a user to a group
///
/// The group to invite to.
/// A list of roles to invite a person to
/// Key of person to invite
public void Invite(LLUUID group, List roles, LLUUID personkey)
{
libsecondlife.Packets.InviteGroupRequestPacket igp = new libsecondlife.Packets.InviteGroupRequestPacket();
igp.AgentData = new libsecondlife.Packets.InviteGroupRequestPacket.AgentDataBlock();
igp.AgentData.AgentID = Client.Network.AgentID;
igp.AgentData.SessionID = Client.Network.SessionID;
igp.GroupData = new libsecondlife.Packets.InviteGroupRequestPacket.GroupDataBlock();
igp.GroupData.GroupID = group;
List idbs = new List();
foreach (LLUUID role in roles)
{
libsecondlife.Packets.InviteGroupRequestPacket.InviteDataBlock idb = new libsecondlife.Packets.InviteGroupRequestPacket.InviteDataBlock();
idb.InviteeID = personkey;
idb.RoleID = role;
idbs.Add(idb);
}
igp.InviteData = idbs.ToArray();
Client.Network.SendPacket(igp);
}
///
/// Create a new group. This method automaticaly deducts the group creation feild
///
/// Group struct containing the new group info
public void CreateGroup(Group group)
{
libsecondlife.Packets.CreateGroupRequestPacket cgrp = new CreateGroupRequestPacket();
//Fill in agent data
cgrp.AgentData = new CreateGroupRequestPacket.AgentDataBlock();
cgrp.AgentData.AgentID = Client.Network.AgentID;
cgrp.AgentData.SessionID = Client.Network.SessionID;
//Fill in group data
cgrp.GroupData = new CreateGroupRequestPacket.GroupDataBlock();
cgrp.GroupData.AllowPublish = group.AllowPublish;
cgrp.GroupData.Charter = Helpers.StringToField(group.Charter);
cgrp.GroupData.InsigniaID = group.InsigniaID;
cgrp.GroupData.MaturePublish = group.MaturePublish;
cgrp.GroupData.MembershipFee = group.MembershipFee;
cgrp.GroupData.Name = Helpers.StringToField(group.Name);
cgrp.GroupData.OpenEnrollment = group.OpenEnrollment;
cgrp.GroupData.ShowInList = group.ShowInList;
//Send it
Client.Network.SendPacket(cgrp);
}
///
/// Update a group's profile and other information
///
/// Group struct to update
public void UpdateGroup(LLUUID id, Group group)
{
libsecondlife.Packets.UpdateGroupInfoPacket cgrp = new UpdateGroupInfoPacket();
//Fill in agent data
cgrp.AgentData = new UpdateGroupInfoPacket.AgentDataBlock();
cgrp.AgentData.AgentID = Client.Network.AgentID;
cgrp.AgentData.SessionID = Client.Network.SessionID;
//Fill in group data
cgrp.GroupData = new UpdateGroupInfoPacket.GroupDataBlock();
cgrp.GroupData.GroupID = id;
cgrp.GroupData.AllowPublish = group.AllowPublish;
cgrp.GroupData.Charter = Helpers.StringToField(group.Charter);
cgrp.GroupData.InsigniaID = group.InsigniaID;
cgrp.GroupData.MaturePublish = group.MaturePublish;
cgrp.GroupData.MembershipFee = group.MembershipFee;
cgrp.GroupData.OpenEnrollment = group.OpenEnrollment;
cgrp.GroupData.ShowInList = group.ShowInList;
//Send it
Client.Network.SendPacket(cgrp);
}
///
/// Eject a user from a group
///
/// Group to eject the user from
/// Avatar's key to eject
public void EjectUser(LLUUID group, LLUUID member)
{
libsecondlife.Packets.EjectGroupMemberRequestPacket eject = new EjectGroupMemberRequestPacket();
eject.AgentData = new EjectGroupMemberRequestPacket.AgentDataBlock();
eject.AgentData.AgentID = Client.Network.AgentID;
eject.AgentData.SessionID = Client.Network.SessionID;
//Group
eject.GroupData = new EjectGroupMemberRequestPacket.GroupDataBlock();
eject.GroupData.GroupID = group;
//People to eject
eject.EjectData = new EjectGroupMemberRequestPacket.EjectDataBlock[1];
eject.EjectData[0] = new EjectGroupMemberRequestPacket.EjectDataBlock();
eject.EjectData[0].EjecteeID = member;
//send it
Client.Network.SendPacket(eject);
}
///
/// Update role information
///
/// Group to update
/// Role to update
public void UpdateRole(LLUUID group, GroupRole role)
{
libsecondlife.Packets.GroupRoleUpdatePacket gru = new GroupRoleUpdatePacket();
gru.AgentData.AgentID = Client.Network.AgentID;
gru.AgentData.SessionID = Client.Network.SessionID;
gru.AgentData.GroupID = group;
gru.RoleData = new GroupRoleUpdatePacket.RoleDataBlock[1];
gru.RoleData[0].Name = Helpers.StringToField(role.Name);
gru.RoleData[0].Description = Helpers.StringToField(role.Description);
gru.RoleData[0].Powers = role.Powers;
gru.RoleData[0].Title = Helpers.StringToField(role.Title);
gru.RoleData[0].UpdateType = (byte)GroupRoleUpdate.UpdateAll;
Client.Network.SendPacket(gru);
}
///
/// Create a new role
///
/// Group to update
/// Role to create
public void CreateRole(LLUUID group, GroupRole role)
{
libsecondlife.Packets.GroupRoleUpdatePacket gru = new GroupRoleUpdatePacket();
gru.AgentData.AgentID = Client.Network.AgentID;
gru.AgentData.SessionID = Client.Network.SessionID;
gru.AgentData.GroupID = group;
gru.RoleData = new GroupRoleUpdatePacket.RoleDataBlock[1];
gru.RoleData[0].Name = Helpers.StringToField(role.Name);
gru.RoleData[0].Description = Helpers.StringToField(role.Description);
gru.RoleData[0].Powers = role.Powers;
gru.RoleData[0].Title = Helpers.StringToField(role.Title);
gru.RoleData[0].UpdateType = (byte)GroupRoleUpdate.Create;
Client.Network.SendPacket(gru);
}
///
/// Remove an avatar from a role
///
/// Group to update
/// Role to be removed from
/// Avatar to remove
public void RemoveFromRole(LLUUID group, LLUUID role, LLUUID member)
{
libsecondlife.Packets.GroupRoleChangesPacket grc = new GroupRoleChangesPacket();
grc.AgentData.AgentID = Client.Network.AgentID;
grc.AgentData.SessionID = Client.Network.SessionID;
grc.AgentData.GroupID = group;
grc.RoleChange = new GroupRoleChangesPacket.RoleChangeBlock[1];
grc.RoleChange[0] = new GroupRoleChangesPacket.RoleChangeBlock();
//Add to members and role
grc.RoleChange[0].MemberID = member;
grc.RoleChange[0].RoleID = role;
//1 = Remove From Role
grc.RoleChange[0].Change = 1;
Client.Network.SendPacket(grc);
}
///
/// Assign an avatar to a role
///
/// Group to update
/// Role to assign to
/// Avatar to assign
public void AddToRole(LLUUID group, LLUUID role, LLUUID member)
{
libsecondlife.Packets.GroupRoleChangesPacket grc = new GroupRoleChangesPacket();
grc.AgentData.AgentID = Client.Network.AgentID;
grc.AgentData.SessionID = Client.Network.SessionID;
grc.AgentData.GroupID = group;
grc.RoleChange = new GroupRoleChangesPacket.RoleChangeBlock[1];
grc.RoleChange[0] = new GroupRoleChangesPacket.RoleChangeBlock();
//Add to members and role
grc.RoleChange[0].MemberID = member;
grc.RoleChange[0].RoleID = role;
//0 = Add to Role
grc.RoleChange[0].Change = 0;
Client.Network.SendPacket(grc);
}
///
///
///
///
///
public void SendGroupNotice(LLUUID group, GroupNotice notice)
{
Client.Self.InstantMessage(Client.ToString(), group, notice.Subject + "|" + notice.Message,
LLUUID.Zero, MainAvatar.InstantMessageDialog.GroupNotice, MainAvatar.InstantMessageOnline.Online,
LLVector3.Zero, LLUUID.Zero, notice.SerializeAttachment());
}
///
/// Start a group proposal (vote)
///
/// The group to send it to
/// The proposal to start
public void StartProposal(LLUUID group, GroupProposal prop)
{
StartGroupProposalPacket p = new StartGroupProposalPacket();
p.AgentData.AgentID = Client.Network.AgentID;
p.AgentData.SessionID = Client.Network.SessionID;
p.ProposalData.GroupID = group;
p.ProposalData.ProposalText = Helpers.StringToField(prop.VoteText);
p.ProposalData.Quorum = prop.Quorum;
p.ProposalData.Majority = prop.Majority;
p.ProposalData.Duration = prop.Duration;
Client.Network.SendPacket(p);
}
#region Packet Handlers
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();
group.ID = block.GroupID;
group.InsigniaID = block.GroupInsigniaID;
group.Name = Helpers.FieldToUTF8String(block.GroupName);
group.Powers = block.GroupPowers;
group.Contribution = block.Contribution;
group.AcceptNotices = block.AcceptNotices;
currentGroups[block.GroupID] = group;
}
try { OnCurrentGroups(currentGroups); }
catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
}
}
private void GroupProfileHandler(Packet packet, Simulator simulator)
{
if (OnGroupProfile != null)
{
GroupProfileReplyPacket profile = (GroupProfileReplyPacket)packet;
GroupProfile group = new GroupProfile();
group.AllowPublish = profile.GroupData.AllowPublish;
group.Charter = Helpers.FieldToUTF8String(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.FieldToUTF8String(profile.GroupData.MemberTitle);
group.Money = profile.GroupData.Money;
group.Name = Helpers.FieldToUTF8String(profile.GroupData.Name);
group.OpenEnrollment = profile.GroupData.OpenEnrollment;
group.OwnerRole = profile.GroupData.OwnerRole;
group.Powers = profile.GroupData.PowersMask;
group.ShowInList = profile.GroupData.ShowInList;
try { OnGroupProfile(group); }
catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
}
}
private void GroupTitlesHandler(Packet packet, Simulator simulator)
{
if (OnGroupTitles != null)
{
GroupTitlesReplyPacket titles = (GroupTitlesReplyPacket)packet;
Dictionary groupTitleCache = new Dictionary();
foreach (GroupTitlesReplyPacket.GroupDataBlock block in titles.GroupData)
{
GroupTitle groupTitle = new GroupTitle();
groupTitle.Title = Helpers.FieldToUTF8String(block.Title);
groupTitle.Selected = block.Selected;
groupTitleCache[block.RoleID] = groupTitle;
}
try { OnGroupTitles(groupTitleCache); }
catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
}
}
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();
groupMember.ID = block.AgentID;
groupMember.Contribution = block.Contribution;
groupMember.IsOwner = block.IsOwner;
groupMember.OnlineStatus = Helpers.FieldToUTF8String(block.OnlineStatus);
groupMember.Powers = block.AgentPowers;
groupMember.Title = Helpers.FieldToUTF8String(block.Title);
groupMemberCache[block.AgentID] = groupMember;
}
}
}
// Check if we've received all the group members that are showing up
if (OnGroupMembers != null && groupMemberCache != null && groupMemberCache.Count >= members.GroupData.MemberCount)
{
try { OnGroupMembers(groupMemberCache); }
catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
}
}
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();
groupRole.ID = block.RoleID;
groupRole.Description = Helpers.FieldToUTF8String(block.Description);
groupRole.Name = Helpers.FieldToUTF8String(block.Name);
groupRole.Powers = block.Powers;
groupRole.Title = Helpers.FieldToUTF8String(block.Title);
groupRoleCache[block.RoleID] = groupRole;
}
}
}
// Check if we've received all the group members that are showing up
if (OnGroupRoles != null && groupRoleCache != null && groupRoleCache.Count >= roles.GroupData.RoleCount)
{
try { OnGroupRoles(groupRoleCache); }
catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
}
}
private void GroupRoleMembersHandler(Packet packet, Simulator simulator)
{
GroupRoleMembersReplyPacket members = (GroupRoleMembersReplyPacket)packet;
List> groupRoleMemberCache = null;
lock (GroupRolesMembersCaches)
{
// If nothing is registered to receive this RequestID drop the data
if (GroupRolesMembersCaches.ContainsKey(members.AgentData.RequestID))
{
groupRoleMemberCache = GroupRolesMembersCaches[members.AgentData.RequestID];
foreach (GroupRoleMembersReplyPacket.MemberDataBlock block in members.MemberData)
{
KeyValuePair rolemember =
new KeyValuePair(block.RoleID, block.MemberID);
groupRoleMemberCache.Add(rolemember);
}
}
}
Client.DebugLog("Pairs Ratio: " + groupRoleMemberCache.Count + "/" + members.AgentData.TotalPairs);
// Check if we've received all the pairs that are showing up
if (OnGroupRolesMembers != null && groupRoleMemberCache != null && groupRoleMemberCache.Count >= members.AgentData.TotalPairs)
{
try { OnGroupRolesMembers(groupRoleMemberCache); }
catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
}
}
private void GroupActiveProposalItemHandler(Packet packet, Simulator simulator)
{
//GroupActiveProposalItemReplyPacket proposal = (GroupActiveProposalItemReplyPacket)packet;
// TODO: Create a proposal struct to represent the fields in a proposal item
}
private void GroupVoteHistoryItemHandler(Packet packet, Simulator simulator)
{
//GroupVoteHistoryItemReplyPacket history = (GroupVoteHistoryItemReplyPacket)packet;
// TODO: This was broken in the official viewer when I was last trying to work on it
}
private void GroupAccountSummaryHandler(Packet packet, Simulator simulator)
{
if (OnGroupAccountSummary != null)
{
GroupAccountSummaryReplyPacket summary = (GroupAccountSummaryReplyPacket)packet;
GroupAccountSummary account = new GroupAccountSummary();
account.Balance = summary.MoneyData.Balance;
account.CurrentInterval = summary.MoneyData.CurrentInterval;
account.GroupTaxCurrent = summary.MoneyData.GroupTaxCurrent;
account.GroupTaxEstimate = summary.MoneyData.GroupTaxEstimate;
account.IntervalDays = summary.MoneyData.IntervalDays;
account.LandTaxCurrent = summary.MoneyData.LandTaxCurrent;
account.LandTaxEstimate = summary.MoneyData.LandTaxEstimate;
account.LastTaxDate = Helpers.FieldToUTF8String(summary.MoneyData.LastTaxDate);
account.LightTaxCurrent = summary.MoneyData.LightTaxCurrent;
account.LightTaxEstimate = summary.MoneyData.LightTaxEstimate;
account.NonExemptMembers = summary.MoneyData.NonExemptMembers;
account.ObjectTaxCurrent = summary.MoneyData.ObjectTaxCurrent;
account.ObjectTaxEstimate = summary.MoneyData.ObjectTaxEstimate;
account.ParcelDirFeeCurrent = summary.MoneyData.ParcelDirFeeCurrent;
account.ParcelDirFeeEstimate = summary.MoneyData.ParcelDirFeeEstimate;
account.StartDate = Helpers.FieldToUTF8String(summary.MoneyData.StartDate);
account.TaxDate = Helpers.FieldToUTF8String(summary.MoneyData.TaxDate);
account.TotalCredits = summary.MoneyData.TotalCredits;
account.TotalDebits = summary.MoneyData.TotalDebits;
try { OnGroupAccountSummary(account); }
catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
}
}
private void GroupAccountDetailsHandler(Packet packet, Simulator simulator)
{
if (OnGroupAccountDetails != null)
{
GroupAccountDetailsReplyPacket details = (GroupAccountDetailsReplyPacket)packet;
GroupAccountDetails account = new GroupAccountDetails();
account.CurrentInterval = details.MoneyData.CurrentInterval;
account.IntervalDays = details.MoneyData.IntervalDays;
account.StartDate = Helpers.FieldToUTF8String(details.MoneyData.StartDate);
account.HistoryItems = new List>();
foreach (GroupAccountDetailsReplyPacket.HistoryDataBlock block in details.HistoryData)
{
KeyValuePair item =
new KeyValuePair(Helpers.FieldToUTF8String(block.Description), block.Amount);
account.HistoryItems.Add(item);
}
try { OnGroupAccountDetails(account); }
catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
}
}
private void GroupAccountTransactionsHandler(Packet packet, Simulator simulator)
{
//GroupAccountTransactionsReplyPacket transactions = (GroupAccountTransactionsReplyPacket)packet;
// TODO: This one is slightly different than the previous two
//if (GroupAccountTransactionsCallbacks.ContainsKey(transactions.AgentData.GroupID))
//{
// GroupAccountTransactions account = new GroupAccountTransactions();
// ;
// try { OnGroupAccountTransactions(account); }
// catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
//}
}
#endregion Packet Handlers
}
}