Begining major rework of Asset/Inventory code. Doing a lot of refectoing. What's in here so far?

+ Inventory, Asset and Image managers are now directly apart of the SecondLife class
+ Root Inventory folder has been added to MainAvatar and is set upon login
+ Inventory is no longer downloaded all at once, you have to request the download of individual folders
+ Folder downloading is available Asynchronously, and returns a object that has a ManualResetEvent that you can use to optionally block with
+ The code for AssetManager has been reworked some in prep for allowing Wearables to be Saved/Loaded to/from disk, and for creating new wearables.


git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@742 52acb1d6-8a22-11de-b505-999d5b087335
This commit is contained in:
Michael Cortez
2006-12-19 23:13:04 +00:00
parent df1ac0424f
commit b686cebf3d
17 changed files with 835 additions and 439 deletions

View File

@@ -18,30 +18,23 @@ namespace libsecondlife.AssetSystem
private uint SerialNum = 1;
private ManualResetEvent AgentWearablesSignal = null;
private AgentWearablesUpdatePacket.WearableDataBlock[] AgentWearablesData;
// This data defines all appearance info for an avatar
public AgentWearablesUpdatePacket.WearableDataBlock[] AgentWearablesData;
public SerializableDictionary<uint, float> AgentAppearanceParams = new SerializableDictionary<uint, float>();
public TextureEntry AgentTextureEntry = new TextureEntry("C228D1CF4B5D4BA884F4899A0796AA97"); // if this isn't valid, blame JH ;-)
public AppearanceManager(SecondLife client)
{
Client = client;
AManager = AssetManager.GetAssetManager(client);
AManager = client.Assets;
Client.Objects.OnNewAvatar += new ObjectManager.NewAvatarCallback(Objects_OnNewAvatar);
RegisterCallbacks();
}
void Objects_OnNewAvatar(Simulator simulator, Avatar avatar, ulong regionHandle, ushort timeDilation)
{
if (avatar.ID == Client.Network.AgentID)
{
Console.WriteLine("**********************");
Console.WriteLine("**********************");
Console.WriteLine("Saw Myself");
Console.WriteLine("**********************");
Console.WriteLine("**********************");
}
}
private void RegisterCallbacks()
{
Client.Network.RegisterCallback(libsecondlife.Packets.PacketType.AgentWearablesUpdate, new NetworkManager.PacketCallback(AgentWearablesUpdateCallbackHandler));
@@ -61,33 +54,8 @@ namespace libsecondlife.AssetSystem
return AgentWearablesData;
}
public void SendAgentSetAppearance()
public void GetAvatarAppearanceInfoFromWearableAssets()
{
TextureEntry textures = new TextureEntry("C228D1CF4B5D4BA884F4899A0796AA97"); // if this isn't valid, blame JH ;-)
// Face 17 - Under Pants
// textures.CreateFace(17).TextureID = "b0bac26505cc7076202ba2a2e05fd172"; //Default Men's briefs
// Face 16 - Under Shirt
// textures.CreateFace(16).TextureID = "d283de852dc3dc07dc452e1bfd4cf193"; //Default Men's tank
// Face 11 - Eyes
// textures.CreateFace(11).TextureID = "3abd329a78478984ac1cb95f4ef35fbe"; //Default Eye
// Face 10 -
// textures.CreateFace(10).TextureID = "c24403bc4569361852b31917ad733035"; //Default
// Face 9 -
// textures.CreateFace(9).TextureID = "a88225377555cf975720aa128e47f934"; //Default
// Face 8 -
// textures.CreateFace(8).TextureID = "472ccc472a4e2556d082f7bb708bcca7"; //Default
Dictionary<uint, float> AgentAppearance = new Dictionary<uint, float>();
foreach (AgentWearablesUpdatePacket.WearableDataBlock wdb in GetWearables())
{
if (wdb.ItemID == LLUUID.Zero)
@@ -124,13 +92,12 @@ namespace libsecondlife.AssetSystem
foreach (KeyValuePair<uint, LLUUID> texture in bp.textures)
{
Console.WriteLine(texture.Key + " : " + texture.Value);
textures.CreateFace(texture.Key).TextureID = texture.Value;
AgentTextureEntry.CreateFace(texture.Key).TextureID = texture.Value;
}
foreach (KeyValuePair<uint, float> kvp in bp.parameters)
{
AgentAppearance[kvp.Key] = bp.parameters[kvp.Key];
AgentAppearanceParams[kvp.Key] = bp.parameters[kvp.Key];
}
}
catch (Exception e)
@@ -145,46 +112,9 @@ namespace libsecondlife.AssetSystem
}
}
Dictionary<uint, byte> VisualParams = new Dictionary<uint, byte>();
float maxVal = 0;
float minVal = 0;
uint packetIdx = 0;
float range = 0;
float percentage = 0;
byte packetVal = 0;
foreach (KeyValuePair<uint, float> kvp in AgentAppearance)
{
packetIdx = AppearanceManager.GetAgentSetAppearanceIndex(kvp.Key) - 1; //TODO/FIXME: this should be zero indexed, not 1 based.
maxVal = BodyShapeParams.GetValueMax(kvp.Key);
minVal = BodyShapeParams.GetValueMin(kvp.Key);
range = maxVal - minVal;
percentage = (kvp.Value - minVal) / range;
packetVal = (byte)(percentage * (byte)255);
VisualParams[packetIdx] = packetVal;
}
AgentSetAppearancePacket p = new AgentSetAppearancePacket();
p.AgentData.AgentID = Client.Network.AgentID;
p.AgentData.SessionID = Client.Network.SessionID;
p.AgentData.SerialNum = ++SerialNum;
float AV_Height_Range = 2.025506f - 1.50856f;
float AV_Height = 1.50856f + (((float)VisualParams[25] / 255.0f) * AV_Height_Range);
p.AgentData.Size = new LLVector3(0.45f, 0.6f, AV_Height);
// p.AgentData.Size = new LLVector3(0.45f, 0.6f, 1.35187f);
// p.ObjectData.TextureEntry = textures.ToBytes();
foreach( uint faceid in textures.FaceTextures.Keys )
// Correct the order of the textures
foreach (uint faceid in AgentTextureEntry.FaceTextures.Keys)
{
switch (faceid)
{
@@ -210,22 +140,78 @@ namespace libsecondlife.AssetSystem
}
//Re-order texture faces to match Linden Labs internal data structure.
TextureEntry te2 = new TextureEntry(textures.DefaultTexture.TextureID);
te2.CreateFace(18).TextureID = textures.GetFace(18).TextureID;
te2.CreateFace(17).TextureID = textures.GetFace(17).TextureID;
te2.CreateFace(16).TextureID = textures.GetFace(16).TextureID;
te2.CreateFace(15).TextureID = textures.GetFace(15).TextureID;
te2.CreateFace(2).TextureID = textures.GetFace(2).TextureID;
te2.CreateFace(12).TextureID = textures.GetFace(12).TextureID;
te2.CreateFace(7).TextureID = textures.GetFace(7).TextureID;
te2.CreateFace(6).TextureID = textures.GetFace(6).TextureID;
te2.CreateFace(5).TextureID = textures.GetFace(5).TextureID;
te2.CreateFace(4).TextureID = textures.GetFace(4).TextureID;
te2.CreateFace(3).TextureID = textures.GetFace(3).TextureID;
te2.CreateFace(1).TextureID = textures.GetFace(1).TextureID;
te2.CreateFace(0).TextureID = textures.GetFace(0).TextureID;
p.ObjectData.TextureEntry = te2.ToBytes();
TextureEntry te2 = new TextureEntry(AgentTextureEntry.DefaultTexture.TextureID);
te2.CreateFace(18).TextureID = AgentTextureEntry.GetFace(18).TextureID;
te2.CreateFace(17).TextureID = AgentTextureEntry.GetFace(17).TextureID;
te2.CreateFace(16).TextureID = AgentTextureEntry.GetFace(16).TextureID;
te2.CreateFace(15).TextureID = AgentTextureEntry.GetFace(15).TextureID;
te2.CreateFace(2).TextureID = AgentTextureEntry.GetFace(2).TextureID;
te2.CreateFace(12).TextureID = AgentTextureEntry.GetFace(12).TextureID;
te2.CreateFace(7).TextureID = AgentTextureEntry.GetFace(7).TextureID;
te2.CreateFace(6).TextureID = AgentTextureEntry.GetFace(6).TextureID;
te2.CreateFace(5).TextureID = AgentTextureEntry.GetFace(5).TextureID;
te2.CreateFace(4).TextureID = AgentTextureEntry.GetFace(4).TextureID;
te2.CreateFace(3).TextureID = AgentTextureEntry.GetFace(3).TextureID;
te2.CreateFace(1).TextureID = AgentTextureEntry.GetFace(1).TextureID;
te2.CreateFace(0).TextureID = AgentTextureEntry.GetFace(0).TextureID;
AgentTextureEntry = te2;
}
private Dictionary<uint, byte> GetAssetParamsAsVisualParams()
{
Dictionary<uint, byte> VisualParams = new Dictionary<uint, byte>();
float maxVal = 0;
float minVal = 0;
uint packetIdx = 0;
float range = 0;
float percentage = 0;
byte packetVal = 0;
foreach (KeyValuePair<uint, float> kvp in AgentAppearanceParams)
{
packetIdx = AppearanceManager.GetAgentSetAppearanceIndex(kvp.Key) - 1; //TODO/FIXME: this should be zero indexed, not 1 based.
maxVal = BodyShapeParams.GetValueMax(kvp.Key);
minVal = BodyShapeParams.GetValueMin(kvp.Key);
range = maxVal - minVal;
percentage = (kvp.Value - minVal) / range;
packetVal = (byte)(percentage * (byte)255);
VisualParams[packetIdx] = packetVal;
}
return VisualParams;
}
private LLVector3 GetAgentSizeFromVisualParams(Dictionary<uint, byte> VisualParams)
{
float AV_Height_Range = 2.025506f - 1.50856f;
float AV_Height = 1.50856f + (((float)VisualParams[25] / 255.0f) * AV_Height_Range);
return new LLVector3(0.45f, 0.6f, AV_Height);
}
public void SendAgentSetAppearance()
{
// Get latest appearance info
if (AgentAppearanceParams.Count == 0)
{
GetAvatarAppearanceInfoFromWearableAssets();
}
AgentSetAppearancePacket p = new AgentSetAppearancePacket();
p.AgentData.AgentID = Client.Network.AgentID;
p.AgentData.SessionID = Client.Network.SessionID;
p.AgentData.SerialNum = ++SerialNum;
// Add Texture Data
p.ObjectData.TextureEntry = AgentTextureEntry.ToBytes();
// Add Visual Params
Dictionary<uint, byte> VisualParams = GetAssetParamsAsVisualParams();
p.VisualParam = new AgentSetAppearancePacket.VisualParamBlock[218];
for (uint i = 0; i < 218; i++)
{
@@ -240,33 +226,22 @@ namespace libsecondlife.AssetSystem
uint paramid = GetParamID(i + 1);
float defaultValue = BodyShapeParams.GetValueDefault(paramid);
maxVal = BodyShapeParams.GetValueMax(paramid);
minVal = BodyShapeParams.GetValueMin(paramid);
float minVal = BodyShapeParams.GetValueMin(paramid);
range = maxVal - minVal;
float range = BodyShapeParams.GetValueMax(paramid) - minVal;
percentage = (defaultValue - minVal) / range;
float percentage = (defaultValue - minVal) / range;
packetVal = (byte)(percentage * (byte)255);
byte packetVal = (byte)(percentage * (byte)255);
// Console.WriteLine("Warning Visual Param not defined, IDX: " + (i+1));
// Console.WriteLine("PID: " + paramid + " / Default: " + defaultValue);
p.VisualParam[i].ParamValue = packetVal;
}
}
// Add Size Data
p.AgentData.Size = GetAgentSizeFromVisualParams(VisualParams);
Client.Network.SendPacket(p);
Console.WriteLine("Default: " + textures.DefaultTexture.TextureID);
foreach (KeyValuePair<uint, TextureEntryFace> kvp in textures.FaceTextures)
{
Console.WriteLine(kvp.Key + " : " + kvp.Value.TextureID);
}
Console.WriteLine(p);
}

View File

@@ -43,8 +43,6 @@ namespace libsecondlife.AssetSystem
/// </summary>
public class AssetManager
{
private static Dictionary<LLUUID,AssetManager> AssetManagers = new Dictionary<LLUUID,AssetManager>();
public const int SINK_FEE_IMAGE = 1;
private SecondLife slClient;
@@ -55,12 +53,13 @@ namespace libsecondlife.AssetSystem
/// <summary>
/// </summary>
/// <param name="client"></param>
private AssetManager(SecondLife client)
internal AssetManager(SecondLife client)
{
slClient = client;
// need to make sure we don't keep around old AssetManagers connected to stale instances of SL
// Need to know when we're Connected/Disconnected to clear state
slClient.Network.OnDisconnected += new NetworkManager.DisconnectCallback(Network_OnDisconnected);
slClient.Network.OnConnected += new NetworkManager.ConnectedCallback(Network_OnConnected);
// Used to upload small assets, or as an initial start packet for large transfers
slClient.Network.RegisterCallback(PacketType.AssetUploadComplete, new NetworkManager.PacketCallback(AssetUploadCompleteCallbackHandler));
@@ -72,30 +71,20 @@ namespace libsecondlife.AssetSystem
slClient.Network.RegisterCallback(PacketType.RequestXfer, new NetworkManager.PacketCallback(RequestXferCallbackHandler));
}
void Network_OnDisconnected(NetworkManager.DisconnectType reason, string message)
void Network_OnConnected(object sender)
{
// Remove this asset manager from the managers list.
AssetManager.AssetManagers.Remove(this.slClient.Network.AgentID);
ClearState();
}
public static AssetManager GetAssetManager( SecondLife client )
void Network_OnDisconnected(NetworkManager.DisconnectType reason, string message)
{
lock (AssetManagers)
{
if (AssetManagers.ContainsKey(client.Network.AgentID))
{
AssetManager existingAssetManager = AssetManagers[client.Network.AgentID];
if (existingAssetManager.slClient.Network.Connected == false)
{
existingAssetManager.slClient = client;
}
return existingAssetManager;
} else {
AssetManager am = new AssetManager(client);
AssetManagers[client.Network.AgentID] = am;
return am;
}
}
ClearState();
}
private void ClearState()
{
htDownloadRequests.Clear();
curUploadRequest = null;
}
/// <summary>

View File

@@ -9,6 +9,8 @@ namespace libsecondlife.InventorySystem
/// </summary>
public class InventoryFolder : InventoryBase
{
public enum FolderUpdateFlag { None, NoRecurse, Recurse };
public string Name
{
get { return _Name; }
@@ -33,10 +35,10 @@ namespace libsecondlife.InventorySystem
set
{
InventoryFolder ifParent = iManager.getFolder(this.ParentID);
ifParent.alContents.Remove(this);
ifParent._Contents.Remove(this);
ifParent = iManager.getFolder(value);
ifParent.alContents.Add(this);
ifParent._Contents.Add(this);
this._ParentID = value;
@@ -50,7 +52,8 @@ namespace libsecondlife.InventorySystem
get { return _Type; }
}
public List<InventoryBase> alContents = new List<InventoryBase>();
internal List<InventoryBase> _Contents = new List<InventoryBase>();
internal InventoryFolder(InventoryManager manager)
: base(manager)
@@ -88,6 +91,29 @@ namespace libsecondlife.InventorySystem
this._Type = sbyte.Parse(htData["type_default"].ToString());
}
/// <summary>
/// Get the contents of this folder
/// </summary>
/// <returns>Contents of this folder</returns>
public List<InventoryBase> GetContents()
{
return _Contents;
}
/// <summary>
/// Request a download of this folder's content information.
/// </summary>
/// <param name="Recurse">Indicate if we should recursively download content information.</param>
/// <returns>The Request object for this download</returns>
public DownloadRequest_Folder BeginDownloadContents(bool recurse)
{
_Contents.Clear();
DownloadRequest_Folder dr = new DownloadRequest_Folder(FolderID, recurse);
iManager.RequestFolder(dr);
return dr;
}
public InventoryFolder CreateFolder(string name)
{
@@ -96,7 +122,7 @@ namespace libsecondlife.InventorySystem
public void Delete()
{
iManager.getFolder(this.ParentID).alContents.Remove(this);
iManager.getFolder(this.ParentID)._Contents.Remove(this);
iManager.FolderRemove(this);
}
@@ -123,7 +149,7 @@ namespace libsecondlife.InventorySystem
public List<InventoryBase> GetItemByName(string name)
{
List<InventoryBase> items = new List<InventoryBase>();
foreach (InventoryBase ib in alContents)
foreach (InventoryBase ib in _Contents)
{
if (ib is InventoryFolder)
{
@@ -155,7 +181,7 @@ namespace libsecondlife.InventorySystem
output += "Type = '" + Type + "' ";
output += ">\n";
foreach (Object oContent in alContents)
foreach (Object oContent in _Contents)
{
output += ((InventoryBase)oContent).toXML(outputAssets);
}

View File

@@ -37,8 +37,8 @@ namespace libsecondlife.InventorySystem
throw new Exception("Target Folder [" + value + "] does not exist.");
}
base.iManager.getFolder(this.FolderID).alContents.Remove(this);
iTargetFolder.alContents.Add(this);
base.iManager.getFolder(this.FolderID)._Contents.Remove(this);
iTargetFolder._Contents.Add(this);
_FolderID = value;
UpdateItem();
@@ -422,7 +422,7 @@ namespace libsecondlife.InventorySystem
/// </summary>
public void Delete()
{
base.iManager.getFolder(this.FolderID).alContents.Remove(this);
base.iManager.getFolder(this.FolderID)._Contents.Remove(this);
base.iManager.ItemRemove(this);
}

View File

@@ -27,6 +27,7 @@
//#define DEBUG_PACKETS
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
@@ -46,6 +47,7 @@ namespace libsecondlife.InventorySystem
// Reference to the SLClient Library
private SecondLife slClient;
private ManualResetEvent InventoryManagerInitialized = new ManualResetEvent(false);
// Reference to the Asset Manager
private static AssetManager slAssetManager;
@@ -56,15 +58,12 @@ namespace libsecondlife.InventorySystem
public InventoryPacketHelper InvPacketHelper = null;
// UUID of Root Inventory Folder
private LLUUID uuidRootFolder;
// Setup a dictionary to easily lookup folders by UUID
private Dictionary<LLUUID, InventoryFolder> htFoldersByUUID = new Dictionary<LLUUID, InventoryFolder>();
// Setup a dictionary to track download progress
private Dictionary<LLUUID, DescendentRequest> htFolderDownloadStatus;
private List<DescendentRequest> alFolderRequestQueue;
private Dictionary<LLUUID, DownloadRequest_Folder> FolderDownloadStatus = new Dictionary<LLUUID, DownloadRequest_Folder>();
private List<DownloadRequest_Folder> alFolderRequestQueue = new List<DownloadRequest_Folder>();
// Used to track current item being created
private InventoryItem iiCreationInProgress;
@@ -73,19 +72,16 @@ namespace libsecondlife.InventorySystem
private int LastPacketRecievedAtTick;
// Each InventorySystem needs to be initialized with a client and root folder.
public InventoryManager(SecondLife client, LLUUID rootFolder)
public InventoryManager(SecondLife client)
{
slClient = client;
if (slAssetManager == null)
{
slAssetManager = AssetManager.GetAssetManager(slClient);
}
slAssetManager = slClient.Assets;
InvPacketHelper = new InventoryPacketHelper(slClient.Network.AgentID, slClient.Network.SessionID);
InvPacketHelper = new InventoryPacketHelper(slClient);
uuidRootFolder = rootFolder;
resetFoldersByUUID();
// Need to know what when we're connected/disconnected
slClient.Network.OnConnected += new NetworkManager.ConnectedCallback(Network_OnConnected);
slClient.Network.OnDisconnected += new NetworkManager.DisconnectCallback(Network_OnDisconnected);
// Setup the callback for Inventory Downloads
slClient.Network.RegisterCallback(PacketType.InventoryDescendents, new NetworkManager.PacketCallback(InventoryDescendentsHandler));
@@ -95,25 +91,35 @@ namespace libsecondlife.InventorySystem
}
// Used primarily for debugging and testing
public AssetManager getAssetManager()
void Network_OnDisconnected(NetworkManager.DisconnectType reason, string message)
{
// Console.WriteLine("It is not recommended that you access the asset manager directly");
return AssetManager;
// Clear out current state
ClearState();
}
private void resetFoldersByUUID()
void Network_OnConnected(object sender)
{
// Init folder structure with root
htFoldersByUUID = new Dictionary<LLUUID,InventoryFolder>();
// Clear out current state
ClearState();
}
InventoryFolder ifRootFolder = new InventoryFolder(this, "My Inventory", uuidRootFolder, null);
htFoldersByUUID[uuidRootFolder] = ifRootFolder;
private void ClearState()
{
htFoldersByUUID.Clear();
FolderDownloadStatus.Clear();
alFolderRequestQueue.Clear();
if (slClient.Self.InventoryRootFolderUUID != null)
{
// Init folder structure with root
InventoryFolder ifRootFolder = new InventoryFolder(this, "My Inventory", slClient.Self.InventoryRootFolderUUID, null);
htFoldersByUUID[slClient.Self.InventoryRootFolderUUID] = ifRootFolder;
}
}
public InventoryFolder getRootFolder()
{
return htFoldersByUUID[uuidRootFolder];
return htFoldersByUUID[slClient.Self.InventoryRootFolderUUID];
}
public InventoryFolder getFolder(LLUUID folderID)
@@ -157,7 +163,7 @@ namespace libsecondlife.InventorySystem
{
string sCurFolder = qFolderPath.Dequeue();
foreach (InventoryBase ibFolder in ifRoot.alContents)
foreach (InventoryBase ibFolder in ifRoot._Contents)
{
if (ibFolder is libsecondlife.InventorySystem.InventoryFolder)
{
@@ -178,14 +184,18 @@ namespace libsecondlife.InventorySystem
return null;
}
private void RequestFolder(DescendentRequest dr)
/// <summary>
///
/// </summary>
/// <param name="dr"></param>
internal void RequestFolder(DownloadRequest_Folder dr)
{
Packet packet = InvPacketHelper.FetchInventoryDescendents(
dr.FolderID
, dr.FetchFolders
, dr.FetchItems);
htFolderDownloadStatus[dr.FolderID] = dr;
FolderDownloadStatus[dr.FolderID] = dr;
slClient.Network.SendPacket(packet);
}
@@ -197,10 +207,10 @@ namespace libsecondlife.InventorySystem
if (htFoldersByUUID.ContainsKey(ifolder.ParentID))
{
if (((InventoryFolder)htFoldersByUUID[ifolder.ParentID]).alContents.Contains(ifolder) == false)
if (((InventoryFolder)htFoldersByUUID[ifolder.ParentID])._Contents.Contains(ifolder) == false)
{
// Add new folder to the contents of the parent folder.
((InventoryFolder)htFoldersByUUID[ifolder.ParentID]).alContents.Add(ifolder);
((InventoryFolder)htFoldersByUUID[ifolder.ParentID])._Contents.Add(ifolder);
}
}
else
@@ -317,7 +327,7 @@ namespace libsecondlife.InventorySystem
internal void ItemRemove(InventoryItem iitem)
{
InventoryFolder ifolder = getFolder(iitem.FolderID);
ifolder.alContents.Remove(iitem);
ifolder._Contents.Remove(iitem);
Packet packet = InvPacketHelper.RemoveInventoryItem(iitem.ItemID);
slClient.Network.SendPacket(packet);
@@ -359,16 +369,16 @@ namespace libsecondlife.InventorySystem
public void DownloadInventory()
{
resetFoldersByUUID();
ClearState();
if (htFolderDownloadStatus == null)
if (FolderDownloadStatus == null)
{
// Create status table
htFolderDownloadStatus = new Dictionary<LLUUID,DescendentRequest>();
FolderDownloadStatus = new Dictionary<LLUUID, DownloadRequest_Folder>();
}
else
{
if (htFolderDownloadStatus.Count != 0)
if (FolderDownloadStatus.Count != 0)
{
throw new Exception("Inventory Download requested while previous download in progress.");
}
@@ -376,7 +386,7 @@ namespace libsecondlife.InventorySystem
if (alFolderRequestQueue == null)
{
alFolderRequestQueue = new List<DescendentRequest>();
alFolderRequestQueue = new List<DownloadRequest_Folder>();
}
// Set last packet received to now, just so out time-out timer works
@@ -384,13 +394,13 @@ namespace libsecondlife.InventorySystem
// Send Packet requesting the root Folder,
// this should recurse through all folders
RequestFolder(new DescendentRequest(uuidRootFolder));
RequestFolder(new DownloadRequest_Folder(slClient.Self.InventoryRootFolderUUID));
while ((htFolderDownloadStatus.Count > 0) || (alFolderRequestQueue.Count > 0))
while ((FolderDownloadStatus.Count > 0) || (alFolderRequestQueue.Count > 0))
{
if (htFolderDownloadStatus.Count == 0)
if (FolderDownloadStatus.Count == 0)
{
DescendentRequest dr = alFolderRequestQueue[0];
DownloadRequest_Folder dr = alFolderRequestQueue[0];
alFolderRequestQueue.RemoveAt(0);
RequestFolder(dr);
}
@@ -403,14 +413,14 @@ namespace libsecondlife.InventorySystem
// have to make a seperate list otherwise we run into modifying the original array
// while still enumerating it.
List<DescendentRequest> alRestartList = new List<DescendentRequest>();
List<DownloadRequest_Folder> alRestartList = new List<DownloadRequest_Folder>();
//if (htFolderDownloadStatus[0] != null)
//if (FolderDownloadStatus[0] != null)
//{
// Console.WriteLine(htFolderDownloadStatus[0].GetType());
// Console.WriteLine(FolderDownloadStatus[0].GetType());
//}
foreach (DescendentRequest dr in htFolderDownloadStatus.Values)
foreach (DownloadRequest_Folder dr in FolderDownloadStatus.Values)
{
Console.WriteLine(dr.FolderID + " " + dr.Expected + " / " + dr.Received + " / " + dr.LastReceivedAtTick);
@@ -418,7 +428,7 @@ namespace libsecondlife.InventorySystem
}
LastPacketRecievedAtTick = Environment.TickCount;
foreach (DescendentRequest dr in alRestartList)
foreach (DownloadRequest_Folder dr in alRestartList)
{
RequestFolder(dr);
}
@@ -477,21 +487,36 @@ namespace libsecondlife.InventorySystem
}
}
/// <summary>
/// Returned in response to a InventoryDescendantRequest. Contains information about the
/// contents of a folder.
/// </summary>
/// <seealso cref="InventoryManager.RequestFolder"/>
/// <param name="packet"></param>
/// <param name="simulator"></param>
public void InventoryDescendentsHandler(Packet packet, Simulator simulator)
{
InventoryDescendentsPacket reply = (InventoryDescendentsPacket)packet;
// The UUID of this folder.
LLUUID uuidFolderID = reply.AgentData.FolderID;
// Get the original Descendent Request for this Packet
DownloadRequest_Folder dr = (DownloadRequest_Folder)FolderDownloadStatus[uuidFolderID];
// Update Inventory Manager's last tick point, used for timeouts and such
LastPacketRecievedAtTick = Environment.TickCount;
// Some temp variables to be reused as we're parsing the packet
InventoryItem invItem;
InventoryFolder invFolder;
LLUUID uuidFolderID = LLUUID.Zero;
int iDescendentsExpected = int.MaxValue;
// Used to count the number of descendants received to see if we're finished or not.
int iDescendentsExpected = reply.AgentData.Descendents;
int iDescendentsReceivedThisBlock = 0;
foreach (InventoryDescendentsPacket.ItemDataBlock itemBlock in reply.ItemData)
{
// There is always an item block, even if there isn't any items
@@ -502,8 +527,8 @@ namespace libsecondlife.InventorySystem
if (itemBlock.ItemID == LLUUID.Zero)
{
// this shouldn't ever happen, but unless you've uploaded an invalid item
// to yourself while developping inventory code
// this shouldn't ever happen, unless you've uploaded an invalid item
// to yourself while developping inventory code :-(
}
else
{
@@ -511,7 +536,7 @@ namespace libsecondlife.InventorySystem
InventoryFolder ifolder = (InventoryFolder)htFoldersByUUID[invItem.FolderID];
if (ifolder.alContents.Contains(invItem) == false)
if (ifolder._Contents.Contains(invItem) == false)
{
if ((invItem.InvType == 7) && (invItem.Type == Asset.ASSET_TYPE_NOTECARD))
{
@@ -525,7 +550,7 @@ namespace libsecondlife.InventorySystem
invItem = temp;
}
ifolder.alContents.Add(invItem);
ifolder._Contents.Add(invItem);
}
}
}
@@ -549,9 +574,9 @@ namespace libsecondlife.InventorySystem
// Add folder to Parent
InventoryFolder ifolder = (InventoryFolder)htFoldersByUUID[invFolder.ParentID];
if (ifolder.alContents.Contains(invFolder) == false)
if (ifolder._Contents.Contains(invFolder) == false)
{
ifolder.alContents.Add(invFolder);
ifolder._Contents.Add(invFolder);
}
@@ -559,45 +584,45 @@ namespace libsecondlife.InventorySystem
htFoldersByUUID[invFolder.FolderID] = invFolder;
// It's not the root, should be safe to "recurse"
if (!invFolder.FolderID.Equals(uuidRootFolder))
// Do we recurse?
if (dr.Recurse)
{
bool alreadyQueued = false;
foreach (DescendentRequest dr in alFolderRequestQueue)
// It's not the root, should be safe to "recurse"
if (!invFolder.FolderID.Equals(slClient.Self.InventoryRootFolderUUID))
{
if (dr.FolderID == invFolder.FolderID)
bool alreadyQueued = false;
foreach (DownloadRequest_Folder adr in alFolderRequestQueue)
{
alreadyQueued = true;
break;
if (adr.FolderID == invFolder.FolderID)
{
alreadyQueued = true;
break;
}
}
}
if (!alreadyQueued)
{
alFolderRequestQueue.Add(new DescendentRequest(invFolder.FolderID));
if (!alreadyQueued)
{
alFolderRequestQueue.Add(new DownloadRequest_Folder(invFolder.FolderID));
}
}
}
}
}
// Check how many descendents we're actually supposed to receive
iDescendentsExpected = reply.AgentData.Descendents;
uuidFolderID = reply.AgentData.FolderID;
// Update download status for this folder
if (iDescendentsReceivedThisBlock >= iDescendentsExpected)
{
// We received all the descendents we're expecting for this folder
// in this packet, so go ahead and remove folder from status list.
htFolderDownloadStatus.Remove(uuidFolderID);
FolderDownloadStatus.Remove(uuidFolderID);
dr.RequestComplete.Set();
}
else
{
// This one packet didn't have all the descendents we're expecting
// so update the total we're expecting, and update the total downloaded
DescendentRequest dr = (DescendentRequest)htFolderDownloadStatus[uuidFolderID];
dr.Expected = iDescendentsExpected;
dr.Received += iDescendentsReceivedThisBlock;
dr.LastReceivedAtTick = Environment.TickCount;
@@ -606,41 +631,15 @@ namespace libsecondlife.InventorySystem
{
// Looks like after updating, we have all the descendents,
// remove from folder status.
htFolderDownloadStatus.Remove(uuidFolderID);
FolderDownloadStatus.Remove(uuidFolderID);
dr.RequestComplete.Set();
}
else
{
htFolderDownloadStatus[uuidFolderID] = dr;
FolderDownloadStatus[uuidFolderID] = dr;
// Console.WriteLine( uuidFolderID + " is expecting " + (iDescendentsExpected - iStatus[1]) + " more packets." );
}
}
}
private class DescendentRequest
{
public LLUUID FolderID;
public int Expected = int.MaxValue;
public int Received = 0;
public int LastReceivedAtTick = 0;
public bool FetchFolders = true;
public bool FetchItems = true;
public DescendentRequest(LLUUID folderID)
{
FolderID = folderID;
LastReceivedAtTick = Environment.TickCount;
}
public DescendentRequest(LLUUID folderID, bool fetchFolders, bool fetchItems)
{
FolderID = folderID;
FetchFolders = fetchFolders;
FetchItems = fetchItems;
LastReceivedAtTick = Environment.TickCount;
}
}
}
}

View File

@@ -11,13 +11,21 @@ namespace libsecondlife.InventorySystem
/// </summary>
public class InventoryPacketHelper
{
private LLUUID AgentID;
private LLUUID SessionID;
private SecondLife Client;
public InventoryPacketHelper(LLUUID AgentID, LLUUID SessionID)
private LLUUID AgentID
{
get { return Client.Network.AgentID; }
}
private LLUUID SessionID
{
get { return Client.Network.SessionID; }
}
public InventoryPacketHelper(SecondLife client)
{
this.AgentID = AgentID;
this.SessionID = SessionID;
Client = client;
}
public const int FETCH_INVENTORY_SORT_NAME = 0;

View File

@@ -175,6 +175,9 @@ namespace libsecondlife
public LLVector3 HomeLookAt = LLVector3.Zero;
/// <summary>Used for camera and control key state tracking</summary>
public MainAvatarStatus Status;
/// <summary>The UUID of your root inventory folder</summary>
public LLUUID InventoryRootFolderUUID;
/// <summary>Gets the health of the agent</summary>
public float Health

View File

@@ -1154,6 +1154,13 @@ namespace libsecondlife
Client.Self.HomePosition = posVector;
Client.Self.HomeLookAt = lookatVector;
// Get Inventory Root Folder
Client.Log("Pulling root folder UUID from login data.", Helpers.LogLevel.Debug);
ArrayList alInventoryRoot = (ArrayList)LoginValues["inventory-root"];
Hashtable htInventoryRoot = (Hashtable)alInventoryRoot[0];
Client.Self.InventoryRootFolderUUID = new LLUUID((string)htInventoryRoot["folder_id"]);
// Connect to the sim given in the login reply
Simulator simulator = new Simulator(Client, this.Callbacks, (uint)(int)LoginValues["circuit_code"],
IPAddress.Parse((string)LoginValues["sim_ip"]), (int)LoginValues["sim_port"]);

View File

@@ -28,6 +28,7 @@ using System;
using System.Collections.Generic;
using libsecondlife.Packets;
using libsecondlife.AssetSystem;
using libsecondlife.InventorySystem;
namespace libsecondlife
{
@@ -60,34 +61,19 @@ namespace libsecondlife
public ObjectManager Objects;
/// <summary>Group Subsystem</summary>
public GroupManager Groups;
/// <summary>Asset Subsystem</summary>
public AssetManager Assets;
/// <summary>Inventory Subsystem</summary>
public InventoryManager Inventory;
/// <summary>Image Subsystem</summary>
public ImageManager Images;
/// <summary>Throttling Subsystem</summary>
public AgentThrottle Throttle;
/// <summary>Settings Subsystem</summary>
public Settings Settings;
private ImageManager _ImageManager;
/// <summary>Image Subsystem</summary>
public ImageManager Images
{
get
{
if (_ImageManager == null)
{
_ImageManager = new ImageManager(this);
return _ImageManager;
}
else
{
return _ImageManager;
}
}
set
{
_ImageManager = value;
}
}
/// <summary>Triggered whenever a message is logged.
/// If this is left null, log messages will go to
/// the console</summary>
@@ -107,6 +93,11 @@ namespace libsecondlife
Grid = new GridManager(this);
Objects = new ObjectManager(this);
Groups = new GroupManager(this);
Assets = new AssetManager(this);
Images = new ImageManager(this);
Inventory = new InventoryManager(this);
Throttle = new AgentThrottle(this);
Settings = new Settings(this);
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using IA_SimpleInventory;
@@ -13,8 +14,12 @@ namespace IA_ImageTool
/// <summary>
/// Summary description for Class1.
/// </summary>
class ImageTool : SimpleInventory
class ImageTool
{
private SecondLife _Client;
private ManualResetEvent ConnectedSignal = new ManualResetEvent(false);
private List<LLUUID> _ImageIDs = new List<LLUUID>();
private string _FileName;
private bool _Put;
@@ -24,7 +29,7 @@ namespace IA_ImageTool
/// Used to upload/download images.
/// </summary>
[STAThread]
static new void Main(string[] args)
static void Main(string[] args)
{
if ( (File.Exists("libjasper.dll") == false) )
{
@@ -94,17 +99,16 @@ namespace IA_ImageTool
ImageTool it = new ImageTool(uuidList, filename, put, rate);
// Only download the inventory tree if we're planning on putting/uploading files.
it.DownloadInventoryOnConnect = put;
if (it.Connect(args[0], args[1], args[2]))
{
it.doStuff();
it.Disconnect();
if (it.ConnectedSignal.WaitOne(TimeSpan.FromMinutes(1), false))
{
it.doStuff();
System.Threading.Thread.Sleep(500);
it.Disconnect();
}
Console.WriteLine("Done logging out.");
}
}
@@ -114,12 +118,62 @@ namespace IA_ImageTool
_FileName = filename;
_Put = put;
_Rate = rate;
try
{
_Client = new SecondLife();
_Client.Network.OnConnected += new NetworkManager.ConnectedCallback(Network_OnConnected);
}
catch (Exception e)
{
// Error initializing the client
Console.WriteLine();
Console.WriteLine(e.ToString());
}
}
protected new void doStuff()
void Network_OnConnected(object sender)
{
ConnectedSignal.Set();
}
protected bool Connect(string FirstName, string LastName, string Password)
{
Console.WriteLine("Attempting to connect and login to SecondLife.");
// Setup Login to Second Life
Dictionary<string, object> loginReply = new Dictionary<string, object>();
// Login
if (!_Client.Network.Login(FirstName, LastName, Password, "ImageTool", "static.sprocket@gmail.com"))
{
// Login failed
Console.WriteLine("Error logging in: " + _Client.Network.LoginError);
return false;
}
// Login was successful
Console.WriteLine("Login was successful.");
Console.WriteLine("AgentID: " + _Client.Network.AgentID);
Console.WriteLine("SessionID: " + _Client.Network.SessionID);
return true;
}
protected void Disconnect()
{
// Logout of Second Life
Console.WriteLine("Request logout");
_Client.Network.Logout();
}
protected void doStuff()
{
if (_Put)
{
Console.WriteLine("Reading: " + _FileName);
byte[] j2cdata;
@@ -135,7 +189,7 @@ namespace IA_ImageTool
Console.WriteLine("Connecting to your Texture folder...");
InventoryFolder iFolder = AgentInventory.getFolder("Textures");
InventoryFolder iFolder = _Client.Inventory.getFolder("Textures");
Console.WriteLine("Uploading Texture...");
InventoryImage image = iFolder.NewImage(_FileName, "ImageTool Upload", j2cdata);
@@ -162,7 +216,7 @@ namespace IA_ImageTool
try
{
j2cdata = client.Images.RequestImage(ImageID);
j2cdata = _Client.Images.RequestImage(ImageID);
int end = Environment.TickCount;
Console.WriteLine("Elapsed download time, in TickCounts: " + (end - start));

View File

@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Xml;
using System.Xml.Serialization;
@@ -23,7 +25,7 @@ namespace IA_InventoryManager
/// * MOVE
/// * GIVE
/// </summary>
class iManager : SimpleInventory
class iManager
{
private char[] cmdSeperators = { ' ' };
private string curDirectory = "/";
@@ -31,9 +33,12 @@ namespace IA_InventoryManager
private string TYPE_DIR = "<DIR> ";
private string TYPE_ITEM = "<ITEM> ";
private SecondLife _Client;
private AppearanceManager aManager;
static new void Main(string[] args)
private ManualResetEvent ConnectedSignal = new ManualResetEvent(false);
static void Main(string[] args)
{
if (args.Length < 3)
{
@@ -42,18 +47,35 @@ namespace IA_InventoryManager
}
iManager it = new iManager();
it.Connect(args[0], args[1], args[2]);
it.doStuff();
it.Disconnect();
if (it.Connect(args[0], args[1], args[2]))
{
if (it.ConnectedSignal.WaitOne(TimeSpan.FromMinutes(1), false))
{
it.doStuff();
it.Disconnect();
}
}
}
System.Threading.Thread.Sleep(1000);
public iManager()
{
try
{
_Client = new SecondLife();
_Client.Network.OnConnected += new NetworkManager.ConnectedCallback(Network_OnConnected);
_Client.Self.OnTeleport += new TeleportCallback(Self_OnTeleport);
}
catch (Exception e)
{
// Error initializing the client
Console.WriteLine();
Console.WriteLine(e.ToString());
}
}
private new void doStuff()
private void doStuff()
{
client.Self.OnTeleport += new TeleportCallback(Self_OnTeleport);
System.Threading.Thread.Sleep(1000);
Console.WriteLine("==================================================================");
@@ -164,6 +186,17 @@ namespace IA_InventoryManager
getlook();
break;
case "saveav":
saveavatar(curCmdLine);
break;
case "savew":
savewearables(curCmdLine);
break;
case "loadw":
loadwearables(curCmdLine);
break;
default:
Console.WriteLine("Unknown command '" + curCmdLine[0] + "'.");
@@ -192,10 +225,144 @@ namespace IA_InventoryManager
Console.WriteLine("REGIONINFO - Display Grid Region Info.");
Console.WriteLine("TELEPORT - Teleport to a new sim.");
Console.WriteLine("NOTECARD - Create a new notecard.");
Console.WriteLine("XML - Display an item as xml");
Console.WriteLine("XML - Display an item as xml.");
Console.WriteLine("GETLOOK - Send an AgentSetAppearance based on your current weables.");
Console.WriteLine("SAVEAV - Serialize your current wearables and the info from them.");
Console.WriteLine("SAVEW - Serialize your current wearables.");
Console.WriteLine("LOADW - Load a previously serialized wearables.");
Console.WriteLine("QUIT - Exit the Inventory Manager.");
}
private void savewearables(string[] cmdLine)
{
if (aManager == null)
{
aManager = new AppearanceManager(_Client);
}
// Get Wearable Data
AgentWearablesUpdatePacket.WearableDataBlock[] wdbs = aManager.GetWearables();
List<AgentWearablesUpdatePacket.WearableDataBlock> WearablesList = new List<AgentWearablesUpdatePacket.WearableDataBlock>();
foreach (AgentWearablesUpdatePacket.WearableDataBlock wdb in wdbs)
{
WearablesList.Add(wdb);
}
// Serialize to XML
StringBuilder sb = new StringBuilder();
XmlWriterSettings xmlws = new XmlWriterSettings();
xmlws.Indent = true;
XmlWriter xmlw = XmlWriter.Create(sb, xmlws);
XmlSerializer serializer = new XmlSerializer(typeof(List<AgentWearablesUpdatePacket.WearableDataBlock>));
serializer.Serialize(xmlw, WearablesList);
// Output
if (cmdLine.Length >= 2)
{
Console.WriteLine("Writing wearable data to : " + cmdLine[1]);
File.WriteAllText(cmdLine[1], sb.ToString());
Console.WriteLine("Done...");
}
else
{
Console.WriteLine(sb.ToString());
}
}
private void loadwearables(string[] cmdLine)
{
if (cmdLine.Length < 2)
{
Console.WriteLine("You must specify the file to load the wearables from.");
Console.WriteLine("Usage: loadw [file.xml]");
return;
}
Console.WriteLine("Reading Wearable data from: " + cmdLine[1]);
try
{
XmlReader xmlr = XmlReader.Create(File.OpenText(cmdLine[1]));
XmlSerializer serializer = new XmlSerializer(typeof(List<AgentWearablesUpdatePacket.WearableDataBlock>));
List<AgentWearablesUpdatePacket.WearableDataBlock> WearablesList = (List<AgentWearablesUpdatePacket.WearableDataBlock>)serializer.Deserialize(xmlr);
foreach (AgentWearablesUpdatePacket.WearableDataBlock wdb in WearablesList)
{
Console.WriteLine(wdb.AssetID);
}
}
catch (Exception e)
{
Console.WriteLine("An error has occured...");
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
private void saveavatar(string[] cmdLine)
{
if (aManager == null)
{
aManager = new AppearanceManager(_Client);
}
AgentWearablesUpdatePacket.WearableDataBlock[] wdbs = aManager.GetWearables();
aManager.GetAvatarAppearanceInfoFromWearableAssets();
// Get the list of wearables
List<AgentWearablesUpdatePacket.WearableDataBlock> WearablesList = new List<AgentWearablesUpdatePacket.WearableDataBlock>();
foreach (AgentWearablesUpdatePacket.WearableDataBlock wdb in wdbs)
{
WearablesList.Add(wdb);
}
XmlWriterSettings xmlws = new XmlWriterSettings();
xmlws.OmitXmlDeclaration = true;
xmlws.Indent = true;
xmlws.CloseOutput = false;
StringBuilder Save = new StringBuilder();
Save.Append("<avatar_appearance>");
// Wearables
StringBuilder sb = new StringBuilder();
XmlWriter xmlw = XmlWriter.Create(sb, xmlws);
XmlSerializer serializer = new XmlSerializer(typeof(List<AgentWearablesUpdatePacket.WearableDataBlock>));
serializer.Serialize(xmlw, WearablesList);
Save.AppendLine(sb.ToString());
// Parameters
sb = new StringBuilder();
xmlw = XmlWriter.Create(sb, xmlws);
serializer = new XmlSerializer(typeof(SerializableDictionary<uint, float>));
serializer.Serialize(xmlw, aManager.AgentAppearanceParams);
Save.AppendLine(sb.ToString());
// Parameters
sb = new StringBuilder();
xmlw = XmlWriter.Create(sb, xmlws);
serializer = new XmlSerializer(typeof(TextureEntry));
serializer.Serialize(xmlw, aManager.AgentTextureEntry);
Save.AppendLine(sb.ToString());
// Finish off save data
Save.Append("</avatar_appearance>");
Console.WriteLine(Save.ToString());
//aManager.SendAgentSetAppearance
}
private void StandUpStraight()
{
AgentUpdatePacket p = new AgentUpdatePacket();
@@ -206,17 +373,17 @@ namespace IA_InventoryManager
p.AgentData.CameraUpAxis = new LLVector3(0, 0, 0);
p.AgentData.HeadRotation = new LLQuaternion(0, 0, 0, 1); ;
p.AgentData.BodyRotation = new LLQuaternion(0, 0, 0, 1); ;
p.AgentData.AgentID = client.Network.AgentID;
p.AgentData.SessionID = client.Network.SessionID;
p.AgentData.AgentID = _Client.Network.AgentID;
p.AgentData.SessionID = _Client.Network.SessionID;
p.AgentData.ControlFlags = (uint)Avatar.AgentUpdateFlags.AGENT_CONTROL_STAND_UP;
client.Network.SendPacket(p);
_Client.Network.SendPacket(p);
}
private void getlook()
{
if (aManager == null)
{
aManager = new AppearanceManager(client);
aManager = new AppearanceManager(_Client);
}
@@ -242,17 +409,20 @@ namespace IA_InventoryManager
{
}
InventoryFolder iFolder = AgentInventory.getFolder(curDirectory);
InventoryFolder iFolder = _Client.Inventory.getFolder(curDirectory);
InventoryBase itemOfInterest = null;
foreach (InventoryBase ib in iFolder.alContents)
iFolder.BeginDownloadContents(false).RequestComplete.WaitOne(15000,false);
foreach (InventoryBase ib in iFolder.GetContents())
{
if (ib is InventoryFolder)
{
InventoryFolder folder = (InventoryFolder)ib;
if (folder.Name.Equals(cmdLine[1]) || folder.FolderID.Equals(uuid))
{
// Refresh the folder tree for this folder before outputing it.
folder.BeginDownloadContents(true).RequestComplete.WaitOne(30000, false);
itemOfInterest = folder;
break;
}
@@ -309,7 +479,7 @@ namespace IA_InventoryManager
sb.Append(cki.Key.ToString());
} while (cki.Key != ConsoleKey.Escape);
InventoryFolder iFolder = AgentInventory.getFolder(curDirectory);
InventoryFolder iFolder = _Client.Inventory.getFolder(curDirectory);
iFolder.NewNotecard(cmdLine[1], NoteDesc, sb.ToString());
Console.WriteLine("Notecard '" + NoteName + " 'Created");
@@ -324,22 +494,22 @@ namespace IA_InventoryManager
return;
}
if (cmdLine[1].ToLower() == client.Network.CurrentSim.Region.Name.ToLower())
if (cmdLine[1].ToLower() == _Client.Network.CurrentSim.Region.Name.ToLower())
{
Console.WriteLine("TODO: Add the ability to teleport somewhere in the local region. " +
"Exiting for now, please specify a region other than the current one");
}
else
{
if (client.Grid.Regions.Count == 0)
if (_Client.Grid.Regions.Count == 0)
{
Console.WriteLine("Caching estate sims...");
client.Grid.AddEstateSims();
_Client.Grid.AddEstateSims();
System.Threading.Thread.Sleep(3000);
}
client.Self.Teleport(cmdLine[1], new LLVector3( float.Parse(cmdLine[2]), float.Parse(cmdLine[3]), float.Parse(cmdLine[4]) ) );
_Client.Self.Teleport(cmdLine[1], new LLVector3(float.Parse(cmdLine[2]), float.Parse(cmdLine[3]), float.Parse(cmdLine[4])));
}
}
@@ -360,7 +530,7 @@ namespace IA_InventoryManager
}
regionName = regionName.Trim();
GridRegion gr = client.Grid.GetGridRegion(regionName);
GridRegion gr = _Client.Grid.GetGridRegion(regionName);
Console.WriteLine(gr);
}
@@ -382,15 +552,17 @@ namespace IA_InventoryManager
// Arbitrary Asset
Asset asset = new Asset(cmdLine[2], sbyte.Parse(cmdLine[1]), null);
AgentInventory.getAssetManager().GetInventoryAsset(asset);
_Client.Assets.GetInventoryAsset(asset);
Console.WriteLine(asset.AssetDataToString());
}
else
{
// Asset for an item in inventory
InventoryFolder iFolder = AgentInventory.getFolder(curDirectory);
foreach (InventoryBase ib in iFolder.alContents)
InventoryFolder iFolder = _Client.Inventory.getFolder(curDirectory);
iFolder.BeginDownloadContents(false).RequestComplete.WaitOne(15000, false);
foreach (InventoryBase ib in iFolder.GetContents())
{
if (ib is InventoryItem)
{
@@ -423,7 +595,7 @@ namespace IA_InventoryManager
}
targetDir += combineCmdArg(cmdLine);
InventoryFolder iFolder = AgentInventory.getFolder(targetDir);
InventoryFolder iFolder = _Client.Inventory.getFolder(targetDir);
if (iFolder == null)
{
Console.WriteLine("Could not find directory: " + targetDir);
@@ -446,7 +618,7 @@ namespace IA_InventoryManager
string targetDir = combineCmdArg(cmdLine);
InventoryFolder iFolder = AgentInventory.getFolder(curDirectory);
InventoryFolder iFolder = _Client.Inventory.getFolder(curDirectory);
InventoryFolder newFolder = iFolder.CreateFolder(targetDir);
@@ -492,7 +664,7 @@ namespace IA_InventoryManager
Console.WriteLine("Changing directory to: " + targetDir );
InventoryFolder iFolder = AgentInventory.getFolder(targetDir);
InventoryFolder iFolder = _Client.Inventory.getFolder(targetDir);
if (iFolder == null)
{
@@ -521,8 +693,9 @@ namespace IA_InventoryManager
Console.WriteLine("..");
}
InventoryFolder iFolder = AgentInventory.getFolder(curDirectory);
foreach (InventoryBase ib in iFolder.alContents)
InventoryFolder iFolder = _Client.Inventory.getFolder(curDirectory);
iFolder.BeginDownloadContents(false).RequestComplete.WaitOne(15000, false);
foreach (InventoryBase ib in iFolder.GetContents())
{
if (ib is InventoryFolder)
{
@@ -550,5 +723,41 @@ namespace IA_InventoryManager
}
return rtn.Trim();
}
void Network_OnConnected(object sender)
{
ConnectedSignal.Set();
}
protected bool Connect(string FirstName, string LastName, string Password)
{
Console.WriteLine("Attempting to connect and login to SecondLife.");
// Setup Login to Second Life
Dictionary<string, object> loginReply = new Dictionary<string, object>();
// Login
if (!_Client.Network.Login(FirstName, LastName, Password, "createnotecard", "static.sprocket@gmail.com"))
{
// Login failed
Console.WriteLine("Error logging in: " + _Client.Network.LoginError);
return false;
}
// Login was successful
Console.WriteLine("Login was successful.");
Console.WriteLine("AgentID: " + _Client.Network.AgentID);
Console.WriteLine("SessionID: " + _Client.Network.SessionID);
return true;
}
protected void Disconnect()
{
// Logout of Second Life
Console.WriteLine("Request logout");
_Client.Network.Logout();
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using IA_SimpleInventory;
using IA_ImageTool;
@@ -11,11 +12,14 @@ using libsecondlife.AssetSystem;
namespace IA_MultiImageUpload
{
class MultiImageUpload : SimpleInventory
class MultiImageUpload
{
private SecondLife _Client;
private ManualResetEvent ConnectedSignal = new ManualResetEvent(false);
protected string ImageDirectory;
static new void Main(string[] args)
static void Main(string[] args)
{
if (args.Length < 4)
{
@@ -32,14 +36,31 @@ namespace IA_MultiImageUpload
}
MultiImageUpload app = new MultiImageUpload( fullpath );
app.Connect(args[0], args[1], args[2]);
app.doStuff();
app.Disconnect();
if (app.Connect(args[0], args[1], args[2]))
{
if (app.ConnectedSignal.WaitOne(TimeSpan.FromMinutes(1), false))
{
app.doStuff();
app.Disconnect();
}
}
}
public MultiImageUpload(string dir)
{
ImageDirectory = dir;
try
{
_Client = new SecondLife();
_Client.Network.OnConnected += new NetworkManager.ConnectedCallback(Network_OnConnected);
}
catch (Exception e)
{
// Error initializing the client
Console.WriteLine();
Console.WriteLine(e.ToString());
}
}
public static void Usage()
@@ -47,9 +68,9 @@ namespace IA_MultiImageUpload
System.Console.WriteLine("MultiImageUpload [FirstName] [LastName] [Password] [Directory]");
}
protected new void doStuff()
protected void doStuff()
{
InventoryFolder iFolder = AgentInventory.getFolder("Textures");
InventoryFolder iFolder = _Client.Inventory.getFolder("Textures");
iFolder = iFolder.CreateFolder(Helpers.GetUnixTime().ToString());
Console.WriteLine("Uploading images:");
@@ -79,5 +100,39 @@ namespace IA_MultiImageUpload
}
}
}
void Network_OnConnected(object sender)
{
ConnectedSignal.Set();
}
protected bool Connect(string FirstName, string LastName, string Password)
{
Console.WriteLine("Attempting to connect and login to SecondLife.");
// Setup Login to Second Life
Dictionary<string, object> loginReply = new Dictionary<string, object>();
// Login
if (!_Client.Network.Login(FirstName, LastName, Password, "MultiImageUpload", "static.sprocket@gmail.com"))
{
// Login failed
Console.WriteLine("Error logging in: " + _Client.Network.LoginError);
return false;
}
// Login was successful
Console.WriteLine("Login was successful.");
Console.WriteLine("AgentID: " + _Client.Network.AgentID);
Console.WriteLine("SessionID: " + _Client.Network.SessionID);
return true;
}
protected void Disconnect()
{
// Logout of Second Life
Console.WriteLine("Request logout");
_Client.Network.Logout();
}
}
}

View File

@@ -28,6 +28,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using IA_SimpleInventory;
using libsecondlife;
@@ -35,12 +36,16 @@ using libsecondlife.InventorySystem;
namespace IA_NotecardTool
{
class NotecardTool : SimpleInventory
class NotecardTool
{
private string FileName;
private string NotecardName;
static new void Main(string[] args)
private SecondLife _Client;
private ManualResetEvent ConnectedSignal = new ManualResetEvent(false);
static void Main(string[] args)
{
if (args.Length < 6)
{
@@ -59,21 +64,22 @@ namespace IA_NotecardTool
tool.FileName = args[5];
tool.Connect(args[0], args[1], args[2]);
tool.doStuff();
tool.Disconnect();
System.Threading.Thread.Sleep(500);
if (tool.ConnectedSignal.WaitOne(TimeSpan.FromMinutes(1), false))
{
tool.doStuff();
tool.Disconnect();
}
}
private new void doStuff()
private void doStuff()
{
Console.WriteLine("Reading " + FileName);
StreamReader sr = File.OpenText(FileName);
string Body = sr.ReadToEnd();
Console.WriteLine("Getting Notecard Folder");
InventoryFolder iFolder = base.AgentInventory.getFolder("Notecards");
InventoryFolder iFolder = _Client.Inventory.getFolder("Notecards");
Console.WriteLine("Creating Notecard");
@@ -81,5 +87,55 @@ namespace IA_NotecardTool
Console.WriteLine("Done.");
}
public NotecardTool()
{
try
{
_Client = new SecondLife();
_Client.Network.OnConnected += new NetworkManager.ConnectedCallback(Network_OnConnected);
}
catch (Exception e)
{
// Error initializing the client
Console.WriteLine();
Console.WriteLine(e.ToString());
}
}
void Network_OnConnected(object sender)
{
ConnectedSignal.Set();
}
protected bool Connect(string FirstName, string LastName, string Password)
{
Console.WriteLine("Attempting to connect and login to SecondLife.");
// Setup Login to Second Life
Dictionary<string, object> loginReply = new Dictionary<string, object>();
// Login
if (!_Client.Network.Login(FirstName, LastName, Password, "createnotecard", "static.sprocket@gmail.com"))
{
// Login failed
Console.WriteLine("Error logging in: " + _Client.Network.LoginError);
return false;
}
// Login was successful
Console.WriteLine("Login was successful.");
Console.WriteLine("AgentID: " + _Client.Network.AgentID);
Console.WriteLine("SessionID: " + _Client.Network.SessionID);
return true;
}
protected void Disconnect()
{
// Logout of Second Life
Console.WriteLine("Request logout");
_Client.Network.Logout();
}
}
}

View File

@@ -27,6 +27,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using libsecondlife;
using libsecondlife.InventorySystem;
@@ -38,10 +39,8 @@ namespace IA_SimpleInventory
/// </summary>
public class SimpleInventory
{
protected SecondLife client;
protected InventoryManager AgentInventory;
protected bool DownloadInventoryOnConnect = true;
private SecondLife client;
private ManualResetEvent ConnectedSignal = new ManualResetEvent(false);
public static void Main(string[] args)
{
@@ -53,9 +52,14 @@ namespace IA_SimpleInventory
}
SimpleInventory simple = new SimpleInventory();
simple.Connect(args[0], args[1], args[2]);
simple.doStuff();
simple.Disconnect();
if (simple.Connect(args[0], args[1], args[2]))
{
if (simple.ConnectedSignal.WaitOne(TimeSpan.FromMinutes(1), false))
{
simple.doStuff();
simple.Disconnect();
}
}
}
protected SimpleInventory()
@@ -63,6 +67,7 @@ namespace IA_SimpleInventory
try
{
client = new SecondLife();
client.Network.OnConnected += new NetworkManager.ConnectedCallback(Network_OnConnected);
}
catch (Exception e)
{
@@ -72,6 +77,11 @@ namespace IA_SimpleInventory
}
}
void Network_OnConnected(object sender)
{
ConnectedSignal.Set();
}
protected bool Connect(string FirstName, string LastName, string Password)
{
Console.WriteLine("Attempting to connect and login to SecondLife.");
@@ -80,7 +90,7 @@ namespace IA_SimpleInventory
Dictionary<string, object> loginReply = new Dictionary<string, object>();
// Login
if (!client.Network.Login(FirstName, LastName, Password, "createnotecard", "static.sprocket@gmail.com"))
if (!client.Network.Login(FirstName, LastName, Password, "IA_SimpleInventory", "static.sprocket@gmail.com"))
{
// Login failed
Console.WriteLine("Error logging in: " + client.Network.LoginError);
@@ -92,22 +102,6 @@ namespace IA_SimpleInventory
Console.WriteLine("AgentID: " + client.Network.AgentID);
Console.WriteLine("SessionID: " + client.Network.SessionID);
// Get Root Inventory Folder UUID
Console.WriteLine("Pulling root folder UUID from login data.");
ArrayList alInventoryRoot = (ArrayList)client.Network.LoginValues["inventory-root"];
Hashtable htInventoryRoot = (Hashtable)alInventoryRoot[0];
LLUUID agentRootFolderID = new LLUUID((string)htInventoryRoot["folder_id"]);
// Initialize Inventory Manager object
Console.WriteLine("Initializing Inventory Manager.");
AgentInventory = new InventoryManager(client, agentRootFolderID);
if (DownloadInventoryOnConnect)
{
// and request an inventory download
Console.WriteLine("Downloading Inventory.");
AgentInventory.DownloadInventory();
}
return true;
}
@@ -120,17 +114,19 @@ namespace IA_SimpleInventory
protected void doStuff()
{
// and request an inventory download
Console.WriteLine("Downloading Inventory.");
client.Inventory.DownloadInventory();
Console.WriteLine("Dumping a copy of " + client.Self.FirstName + "'s inventory to the console.");
Console.WriteLine();
if (AgentInventory != null)
{
InventoryFolder root = AgentInventory.getRootFolder();
InventoryFolder root = client.Inventory.getRootFolder();
if (root != null)
{
Console.WriteLine(root.toXML(false));
}
if (root != null)
{
Console.WriteLine(root.toXML(false));
}
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using IA_SimpleInventory;
using libsecondlife;
@@ -10,76 +11,79 @@ using libsecondlife.AssetSystem;
namespace IA_TestAsyncImage
{
class TestAsync : SimpleInventory
class TestAsync
{
ImageManager imgManager;
private SecondLife _Client;
private ManualResetEvent ConnectedSignal = new ManualResetEvent(false);
Queue<LLUUID> TextureQueue = new Queue<LLUUID>();
string OutputDirectory = "IA_TestAsyncImages";
private Queue<LLUUID> TextureQueue = new Queue<LLUUID>();
private string OutputDirectory = "IA_TestAsyncImages";
[STAThread]
static new void Main(string[] args)
static void Main(string[] args)
{
TestAsync app = new TestAsync();
app.DownloadInventoryOnConnect = false;
app.client.Objects.OnNewPrim += new ObjectManager.NewPrimCallback(app.Objects_OnNewPrim);
app.client.Objects.OnNewAvatar += new ObjectManager.NewAvatarCallback(app.Objects_OnNewAvatar);
app._Client.Objects.OnNewPrim += new ObjectManager.NewPrimCallback(app.Objects_OnNewPrim);
app._Client.Objects.OnNewAvatar += new ObjectManager.NewAvatarCallback(app.Objects_OnNewAvatar);
app.Connect(args[0], args[1], args[2]);
app.doStuff();
app.Disconnect();
System.Threading.Thread.Sleep(500);
if (app.ConnectedSignal.WaitOne(TimeSpan.FromMinutes(1), false))
{
app.doStuff();
app.Disconnect();
}
Console.WriteLine("Done...");
}
public TestAsync()
{
try
{
_Client = new SecondLife();
_Client.Images = new ImageManager(_Client, ImageManager.CacheTypes.Disk, OutputDirectory);
_Client.Network.OnConnected += new NetworkManager.ConnectedCallback(Network_OnConnected);
}
catch (Exception e)
{
// Error initializing the client
Console.WriteLine();
Console.WriteLine(e.ToString());
}
}
private void Objects_OnNewAvatar(Simulator simulator, Avatar avatar, ulong regionHandle, ushort timeDilation)
{
if (imgManager == null)
if (avatar.FirstLifeImage != null)
{
Console.WriteLine("ImageManager not ready yet, queueing Avatar textures.");
TextureQueue.Enqueue(avatar.FirstLifeImage);
TextureQueue.Enqueue(avatar.ProfileImage);
foreach (TextureEntryFace tef in avatar.Textures.FaceTextures.Values)
if (_Client.Images.isCachedImage(avatar.FirstLifeImage) == false)
{
TextureQueue.Enqueue(tef.TextureID);
_Client.Images.RequestImageAsync(avatar.FirstLifeImage);
}
}
else
if (avatar.ProfileImage != null)
{
if (avatar.FirstLifeImage != null)
if (_Client.Images.isCachedImage(avatar.FirstLifeImage) == false)
{
if (imgManager.isCachedImage(avatar.FirstLifeImage) == false)
{
imgManager.RequestImageAsync(avatar.FirstLifeImage);
}
_Client.Images.RequestImageAsync(avatar.ProfileImage);
}
}
if (avatar.ProfileImage != null)
if (avatar.Textures != null)
{
foreach (TextureEntryFace tef in avatar.Textures.FaceTextures.Values)
{
if (imgManager.isCachedImage(avatar.FirstLifeImage) == false)
if (_Client.Images.isCachedImage(tef.TextureID) == false)
{
imgManager.RequestImageAsync(avatar.ProfileImage);
_Client.Images.RequestImageAsync(tef.TextureID);
}
}
if (avatar.Textures != null)
{
foreach (TextureEntryFace tef in avatar.Textures.FaceTextures.Values)
else
{
if (imgManager.isCachedImage(tef.TextureID) == false)
{
imgManager.RequestImageAsync(tef.TextureID);
}
else
{
Console.WriteLine("Already cached: " + tef.TextureID);
}
Console.WriteLine("Already cached: " + tef.TextureID);
}
}
}
@@ -87,42 +91,29 @@ namespace IA_TestAsyncImage
private void Objects_OnNewPrim(Simulator simulator, PrimObject prim, ulong regionHandle, ushort timeDilation)
{
if (imgManager == null)
if ((prim.Textures.DefaultTexture != null) && (prim.Textures.DefaultTexture.TextureID != null))
{
Console.WriteLine("ImageManager not ready yet, queueing Prim textures.");
TextureQueue.Enqueue(prim.Textures.DefaultTexture.TextureID);
foreach (TextureEntryFace tef in prim.Textures.FaceTextures.Values)
if (_Client.Images.isCachedImage(prim.Textures.DefaultTexture.TextureID) == false)
{
TextureQueue.Enqueue(tef.TextureID);
_Client.Images.RequestImageAsync(prim.Textures.DefaultTexture.TextureID);
}
else
{
Console.WriteLine("Already cached: " + prim.Textures.DefaultTexture.TextureID);
}
}
else
if (prim.Textures.FaceTextures != null)
{
if ((prim.Textures.DefaultTexture != null) && (prim.Textures.DefaultTexture.TextureID != null))
foreach (TextureEntryFace tef in prim.Textures.FaceTextures.Values)
{
if (imgManager.isCachedImage(prim.Textures.DefaultTexture.TextureID) == false)
if (_Client.Images.isCachedImage(tef.TextureID) == false)
{
imgManager.RequestImageAsync(prim.Textures.DefaultTexture.TextureID);
_Client.Images.RequestImageAsync(tef.TextureID);
}
else
{
Console.WriteLine("Already cached: " + prim.Textures.DefaultTexture.TextureID);
}
}
if (prim.Textures.FaceTextures != null)
{
foreach (TextureEntryFace tef in prim.Textures.FaceTextures.Values)
{
if (imgManager.isCachedImage(tef.TextureID) == false)
{
imgManager.RequestImageAsync(tef.TextureID);
}
else
{
Console.WriteLine("Already cached: " + tef.TextureID);
}
Console.WriteLine("Already cached: " + tef.TextureID);
}
}
}
@@ -153,14 +144,14 @@ namespace IA_TestAsyncImage
}
}
protected new void doStuff()
protected void doStuff()
{
imgManager = new ImageManager(client, ImageManager.CacheTypes.Disk, OutputDirectory);
imgManager.OnImageRetrieved += new ImageRetrievedCallback(NewImageRetrievedCallBack);
_Client.Images.OnImageRetrieved += new ImageRetrievedCallback(NewImageRetrievedCallBack);
while (TextureQueue.Count > 0)
{
imgManager.RequestImageAsync(TextureQueue.Dequeue());
_Client.Images.RequestImageAsync(TextureQueue.Dequeue());
}
Console.WriteLine("Press any key to stop.");
@@ -183,5 +174,40 @@ namespace IA_TestAsyncImage
File.WriteAllBytes(filename, JasperWrapper.jasper_decode_j2c_to_tiff(j2cdata));
}
}
void Network_OnConnected(object sender)
{
ConnectedSignal.Set();
}
protected bool Connect(string FirstName, string LastName, string Password)
{
Console.WriteLine("Attempting to connect and login to SecondLife.");
// Setup Login to Second Life
Dictionary<string, object> loginReply = new Dictionary<string, object>();
// Login
if (!_Client.Network.Login(FirstName, LastName, Password, "createnotecard", "static.sprocket@gmail.com"))
{
// Login failed
Console.WriteLine("Error logging in: " + _Client.Network.LoginError);
return false;
}
// Login was successful
Console.WriteLine("Login was successful.");
Console.WriteLine("AgentID: " + _Client.Network.AgentID);
Console.WriteLine("SessionID: " + _Client.Network.SessionID);
return true;
}
protected void Disconnect()
{
// Logout of Second Life
Console.WriteLine("Request logout");
_Client.Network.Logout();
}
}
}

View File

@@ -136,7 +136,7 @@ namespace Teleport
}
}
Client.Self.OnTeleport += new TeleportCallback(Avatar_OnTeleportMessage);
Client.Self.OnTeleport += new TeleportCallback(Self_OnTeleport);
DoneTeleporting = false;
Client.Self.Teleport(RegionHandle, coords);
@@ -147,7 +147,7 @@ namespace Teleport
}
}
private void Avatar_OnTeleportMessage(Simulator currentSim, string message, TeleportStatus status)
void Self_OnTeleport(Simulator currentSim, string message, TeleportStatus status)
{
Console.WriteLine(message);

View File

@@ -107,6 +107,8 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="AvatarManager.cs" />
<Compile Include="InventorySystem\DownloadRequest_Folder.cs" />
<Compile Include="InventorySystem\InventoryWearable.cs" />
<Compile Include="MainAvatarStatus.cs" />
<Compile Include="MainAvatar.cs" />
<Compile Include="EstateTools.cs">