using System;
using System.Collections.Generic;
using System.Threading;
using libsecondlife;
using libsecondlife.Packets;
namespace libsecondlife.Utilities
{
///
/// Keeps an up to date inventory of the currently seen objects in each
/// simulator
///
//public class ObjectTracker
//{
// private SecondLife Client;
// private Dictionary> SimPrims = new Dictionary>();
// ///
// /// Default constructor
// ///
// /// A reference to the SecondLife client to track
// /// objects for
// public ObjectTracker(SecondLife client)
// {
// Client = client;
// }
//}
///
/// Maintains a cache of avatars and does blocking lookups for avatar data
///
public class AvatarTracker
{
protected SecondLife Client;
protected Dictionary avatars = new Dictionary();
protected Dictionary NameLookupEvents = new Dictionary();
public AvatarTracker(SecondLife client)
{
Client = client;
Client.Avatars.OnAvatarNames += new AvatarManager.AvatarNamesCallback(Avatars_OnAvatarNames);
}
///
/// Check if a particular avatar is in the local cache
///
///
///
public bool Contains(LLUUID id)
{
return avatars.ContainsKey(id);
}
///
/// Get an avatar's name, either from the cache or request it.
/// This function is blocking
///
/// Avatar key to look up
/// The avatar name, or String.Empty if the lookup failed
public string GetAvatarName(LLUUID id)
{
// Short circuit the cache lookup in GetAvatarNames
if (Contains(id))
return LocalAvatarNameLookup(id);
// Add to the dictionary
lock (NameLookupEvents)
NameLookupEvents.Add(id, new ManualResetEvent(false));
// Call function
Client.Avatars.RequestAvatarName(id);
// Start blocking while we wait for this name to be fetched
NameLookupEvents[id].WaitOne(5000, false);
// Clean up
lock (NameLookupEvents)
NameLookupEvents.Remove(id);
// Return
return LocalAvatarNameLookup(id);
}
///
///
///
///
//public void BeginGetAvatarName(LLUUID id)
//{
// // TODO: BeginGetAvatarNames is pretty bulky, rewrite a simple version here
// List ids = new List();
// ids.Add(id);
// BeginGetAvatarNames(ids);
//}
///
///
///
///
//public void BeginGetAvatarNames(List ids)
//{
// Dictionary havenames = new Dictionary();
// List neednames = new List();
// // Fire callbacks for the ones we already have cached
// foreach (LLUUID id in ids)
// {
// if (Avatars.ContainsKey(id))
// {
// havenames[id] = Avatars[id].Name;
// //Short circuit the lookup process
// if (ManualResetEvents.ContainsKey(id))
// {
// ManualResetEvents[id].Set();
// return;
// }
// }
// else
// {
// neednames.Add(id);
// }
// }
// if (havenames.Count > 0 && OnAgentNames != null)
// {
// OnAgentNames(havenames);
// }
// if (neednames.Count > 0)
// {
// UUIDNameRequestPacket request = new UUIDNameRequestPacket();
// request.UUIDNameBlock = new UUIDNameRequestPacket.UUIDNameBlockBlock[neednames.Count];
// for (int i = 0; i < neednames.Count; i++)
// {
// request.UUIDNameBlock[i] = new UUIDNameRequestPacket.UUIDNameBlockBlock();
// request.UUIDNameBlock[i].ID = neednames[i];
// }
// Client.Network.SendPacket(request);
// }
//}
///
/// This function will only check if the avatar name exists locally,
/// it will not do any networking calls to fetch the name
///
/// The avatar name, or an empty string if it's not found
protected string LocalAvatarNameLookup(LLUUID id)
{
lock (avatars)
{
if (avatars.ContainsKey(id))
return avatars[id].Name;
else
return String.Empty;
}
}
private void Avatars_OnAvatarNames(Dictionary names)
{
lock (avatars)
{
foreach (KeyValuePair kvp in names)
{
if (!avatars.ContainsKey(kvp.Key) || avatars[kvp.Key] == null)
avatars[kvp.Key] = new Avatar();
avatars[kvp.Key].Name = kvp.Value;
lock (NameLookupEvents)
{
if (NameLookupEvents.ContainsKey(kvp.Key))
NameLookupEvents[kvp.Key].Set();
}
}
}
}
}
}