diff --git a/libsecondlife/AvatarManager.cs b/libsecondlife/AvatarManager.cs
index 35e17819..1108153a 100644
--- a/libsecondlife/AvatarManager.cs
+++ b/libsecondlife/AvatarManager.cs
@@ -25,6 +25,7 @@
*/
using System;
+using System.Text;
using System.Collections.Generic;
using System.Threading;
using libsecondlife.Packets;
@@ -52,7 +53,27 @@ namespace libsecondlife
public string GroupTitle;
/// true of Avatar has chosen to list this in their profile
public bool ListInProfile;
- }
+ }
+
+ ///
+ /// Holds group information on an individual profile pick
+ ///
+ public struct ProfilePick
+ {
+ public LLUUID PickID;
+ public LLUUID CreatorID;
+ public bool TopPick;
+ public LLUUID ParcelID;
+ public string Name;
+ public string Desc;
+ public LLUUID SnapshotID;
+ public string User;
+ public string OriginalName;
+ public string SimName;
+ public LLVector3d PosGlobal;
+ public int SortOrder;
+ public bool Enabled;
+ }
#endregion
///
@@ -130,7 +151,18 @@ namespace libsecondlife
///
public delegate void EffectCallback(EffectType type, LLUUID sourceID, LLUUID targetID,
LLVector3d targetPos, float duration, LLUUID id);
-
+ ///
+ /// Callback returning a dictionary of avatar's picks
+ ///
+ ///
+ ///
+ public delegate void AvatarPicksCallback(LLUUID avatarid, Dictionary picks);
+ ///
+ /// Callback returning a details of a specifick pick
+ ///
+ ///
+ ///
+ public delegate void PickInfoCallback(LLUUID pickid, ProfilePick pick);
///
public event AvatarAppearanceCallback OnAvatarAppearance;
///
@@ -149,6 +181,10 @@ namespace libsecondlife
public event LookAtCallback OnLookAt;
///
public event EffectCallback OnEffect;
+ ///
+ public event AvatarPicksCallback OnAvatarPicks;
+ ///
+ public event PickInfoCallback OnPickInfo;
private SecondLife Client;
@@ -178,6 +214,10 @@ namespace libsecondlife
Client.Network.RegisterCallback(PacketType.UUIDNameReply, new NetworkManager.PacketCallback(AvatarNameHandler));
Client.Network.RegisterCallback(PacketType.AvatarPickerReply, new NetworkManager.PacketCallback(AvatarPickerReplyHandler));
Client.Network.RegisterCallback(PacketType.AvatarAnimation, new NetworkManager.PacketCallback(AvatarAnimationHandler));
+
+ // Picks callbacks
+ Client.Network.RegisterCallback(PacketType.AvatarPicksReply, new NetworkManager.PacketCallback(AvatarPicksHandler));
+ Client.Network.RegisterCallback(PacketType.PickInfoReply, new NetworkManager.PacketCallback(PickInfoHandler));
}
/// Tracks the specified avatar on your map
@@ -255,6 +295,51 @@ namespace libsecondlife
Client.Network.SendPacket(aprp);
}
+ ///
+ /// Start a request for Avatar Picks
+ ///
+ /// UUID of the avatar
+ public void RequestAvatarPicks(LLUUID avatarid)
+ {
+ GenericMessagePacket gmp = new GenericMessagePacket();
+
+ gmp.AgentData.AgentID = Client.Self.AgentID;
+ gmp.AgentData.SessionID = Client.Self.SessionID;
+ gmp.AgentData.TransactionID = LLUUID.Zero;
+
+ gmp.MethodData.Method = Helpers.StringToField("avatarpicksrequest");
+ gmp.MethodData.Invoice = LLUUID.Zero;
+ gmp.ParamList = new GenericMessagePacket.ParamListBlock[1];
+ gmp.ParamList[0] = new GenericMessagePacket.ParamListBlock();
+ gmp.ParamList[0].Parameter = Helpers.StringToField(avatarid.ToString());
+
+ Client.Network.SendPacket(gmp);
+ }
+
+ ///
+ /// Start a request for details of a specific profile pick
+ ///
+ /// UUID of the avatar
+ /// UUID of the profile pick
+ public void RequestPickInfo(LLUUID avatarid, LLUUID pickid)
+ {
+ GenericMessagePacket gmp = new GenericMessagePacket();
+
+ gmp.AgentData.AgentID = Client.Self.AgentID;
+ gmp.AgentData.SessionID = Client.Self.SessionID;
+ gmp.AgentData.TransactionID = LLUUID.Zero;
+
+ gmp.MethodData.Method = Helpers.StringToField("pickinforequest");
+ gmp.MethodData.Invoice = LLUUID.Zero;
+ gmp.ParamList = new GenericMessagePacket.ParamListBlock[2];
+ gmp.ParamList[0] = new GenericMessagePacket.ParamListBlock();
+ gmp.ParamList[0].Parameter = Helpers.StringToField(avatarid.ToString());
+ gmp.ParamList[1] = new GenericMessagePacket.ParamListBlock();
+ gmp.ParamList[1].Parameter = Helpers.StringToField(pickid.ToString());
+
+ Client.Network.SendPacket(gmp);
+ }
+
#region Packet Handlers
///
@@ -546,6 +631,60 @@ namespace libsecondlife
}
}
+ ///
+ /// Process an incoming list of profile picks
+ ///
+ private void AvatarPicksHandler(Packet packet, Simulator simulator)
+ {
+ if (OnAvatarPicks == null) {
+ return;
+ }
+ AvatarPicksReplyPacket p = (AvatarPicksReplyPacket)packet;
+ Dictionary picks = new Dictionary();
+
+ foreach (AvatarPicksReplyPacket.DataBlock b in p.Data) {
+ picks.Add(b.PickID, Helpers.FieldToUTF8String(b.PickName));
+ }
+
+ try {
+ OnAvatarPicks(p.AgentData.TargetID, picks);
+ } catch (Exception ex) {
+ Logger.Log(ex.Message, Helpers.LogLevel.Error, Client, ex);
+ }
+ }
+
+ ///
+ /// Process an incoming details of a profile pick
+ ///
+ private void PickInfoHandler(Packet packet, Simulator simulator)
+ {
+ if (OnPickInfo == null) {
+ return;
+ }
+
+ PickInfoReplyPacket p = (PickInfoReplyPacket)packet;
+ ProfilePick ret = new ProfilePick();
+ ret.CreatorID = p.Data.CreatorID;
+ ret.Desc = Helpers.FieldToUTF8String(p.Data.Desc);
+ ret.Enabled = p.Data.Enabled;
+ ret.Name = Helpers.FieldToUTF8String(p.Data.Name);
+ ret.OriginalName = Helpers.FieldToUTF8String(p.Data.OriginalName);
+ ret.ParcelID = p.Data.ParcelID;
+ ret.PickID = p.Data.PickID;
+ ret.PosGlobal = p.Data.PosGlobal;
+ ret.SimName = Helpers.FieldToUTF8String(p.Data.SimName);
+ ret.SnapshotID = p.Data.SnapshotID;
+ ret.SortOrder = p.Data.SortOrder;
+ ret.TopPick = p.Data.TopPick;
+ ret.User = Helpers.FieldToUTF8String(p.Data.User);
+
+ try {
+ OnPickInfo(ret.PickID, ret);
+ } catch (Exception ex) {
+ Logger.Log(ex.Message, Helpers.LogLevel.Error, Client, ex);
+ }
+ }
+
protected void AvatarAnimationHandler(Packet packet, Simulator sim)
{
//FIXME