Example #1
0
        /// <summary>
        /// Get a pronouncable form of each wearable type.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        string WearableType(InventoryWearable item)
        {
            switch (item.WearableType)
            {
            case OpenMetaverse.WearableType.Shirt: return("shirt");

            case OpenMetaverse.WearableType.Pants: return("pants");

            case OpenMetaverse.WearableType.Skirt: return("skirt");

            case OpenMetaverse.WearableType.Shoes: return("shoes");

            case OpenMetaverse.WearableType.Jacket: return("jacket");

            case OpenMetaverse.WearableType.Socks: return("socks");

            case OpenMetaverse.WearableType.Undershirt: return("undershirt");

            case OpenMetaverse.WearableType.Underpants: return("underpants");

            case OpenMetaverse.WearableType.Skin: return("skin");

            case OpenMetaverse.WearableType.Eyes: return("eyes");

            case OpenMetaverse.WearableType.Gloves: return("gloves");

            case OpenMetaverse.WearableType.Hair: return("hair");

            case OpenMetaverse.WearableType.Shape: return("body shape");

            default: return("clothes");
            }
        }
Example #2
0
        /// <summary>
        /// Add a single wearable to your outfit, replacing if nessesary.
        /// </summary>
        /// <param name="wearable"></param>
        public void Wear(InventoryWearable wearable)
        {
            List <InventoryWearable> x = new List <InventoryWearable>();

            x.Add(wearable);
            Wear(x);
        }
Example #3
0
        void Inventory_ItemReceived(object sender, ItemReceivedEventArgs e)
        {
            var  links     = ContentLinks();
            bool partOfCOF = links.Any(cofItem => cofItem.AssetUUID == e.Item.UUID);

            if (partOfCOF)
            {
                lock (Content)
                {
                    Content[e.Item.UUID] = e.Item;
                }
            }

            if (Content.Count != links.Count)
            {
                return;
            }
            COFReady = true;
            if (AppearanceSent)
            {
                InitialUpdate();
            }
            lock (Content)
            {
                foreach (InventoryItem link in Content.Values)
                {
                    if (link.InventoryType == InventoryType.Wearable)
                    {
                        InventoryWearable w  = (InventoryWearable)link;
                        InventoryItem     lk = links.Find(l => l.AssetUUID == w.UUID);
                        // Logger.DebugLog(string.Format("\nName: {0}\nDescription: {1}\nType: {2} - {3}", w.Name, lk == null ? "" : lk.Description, w.Flags.ToString(), w.WearableType.ToString())); ;
                    }
                }
            }
        }
Example #4
0
 /// <summary>
 /// Creates a new COF link
 /// </summary>
 /// <param name="item">Original item to be linked from COF</param>
 public void AddLink(InventoryItem item)
 {
     if (item.InventoryType == InventoryType.Wearable && !IsBodyPart(item))
     {
         InventoryWearable w = (InventoryWearable)item;
         int    layer        = 0;
         string desc         = string.Format("@{0}{1:00}", (int)w.WearableType, layer);
         AddLink(item, desc);
     }
     else
     {
         AddLink(item, string.Empty);
     }
 }
Example #5
0
 /// <summary>
 /// Creates a new COF link
 /// </summary>
 /// <param name="item">Original item to be linked from COF</param>
 public void AddLink(InventoryItem item)
 {
     if (item.InventoryType == InventoryType.Wearable && !IsBodyPart(item))
     {
         InventoryWearable w = (InventoryWearable)item;
         int    layer        = 0;
         string desc         = $"@{(int) w.WearableType}{layer:00}";
         AddLink(item, desc);
     }
     else
     {
         AddLink(item, string.Empty);
     }
 }
Example #6
0
        /// <summary>
        /// Equivalent to the SL "Replace Outfit" command.  All clothing is removed, and replaced with wearables in given folder.  Body wearables will be replaced if provided.
        /// </summary>
        /// <param name="outfitFolder">Contains the wearable items to put on.</param>
        /// <param name="TimeOut">How long to wait for outfit directory information to download</param>
        public void WearOutfit(InventoryFolder outfitFolder, int TimeOut)
        {
            // Refresh download of outfit folder
            if (!outfitFolder.RequestDownloadContents(false).RequestComplete.WaitOne(TimeOut, false))
            {
                Console.WriteLine("An error occured while downloads the folder contents of : " + outfitFolder.Name);
            }

            // Make sure we have some Wearable Data to start with.
            if ((AgentWearablesData == null) || (AgentWearablesData.Length == 0))
            {
                GetWearables();
            }

            // Flush the cached clothing wearables so we can redefine them
            for (byte i = 4; i <= 12; i++)
            {
                AgentWearablesData[i].ItemID  = LLUUID.Zero;
                AgentWearablesData[i].AssetID = LLUUID.Zero;
            }

            // Replace with wearables from Outfit folder
            foreach (InventoryBase ib in outfitFolder.GetContents())
            {
                if (ib is InventoryWearable)
                {
                    InventoryWearable iw = (InventoryWearable)ib;
                    byte type            = ((AssetWearable)iw.Asset).TypeFromAsset;
                    AgentWearablesData[type].ItemID  = iw.ItemID;
                    AgentWearablesData[type].AssetID = iw.AssetID;
                }
            }

            // Create AgentIsNowWearing Packet, and send it
            SendAgentIsNowWearing();

            // Update local Appearance Info
            GetAvatarAppearanceInfoFromWearableAssets();

            // Send updated AgentSetAppearance to the grid
            SendAgentSetAppearance();
        }
Example #7
0
 /// <summary>
 /// Add a single wearable to your outfit, replacing if nessesary.
 /// </summary>
 /// <param name="wearable"></param>
 public void Wear(InventoryWearable wearable)
 {
     List<InventoryWearable> x = new List<InventoryWearable>();
     x.Add(wearable);
     Wear(x);
 }
Example #8
0
        /// <summary>
        /// Equivalent to the SL "Replace Outfit" command.  All clothing is removed, and replaced with wearables in given folder.  Body wearables will be replaced if provided.
        /// </summary>
        /// <param name="outfitFolder">Contains the wearable items to put on.</param>
        /// <param name="TimeOut">How long to wait for outfit directory information to download</param>
        public void WearOutfit(InventoryFolder outfitFolder, int TimeOut, bool removeExistingAttachments)
        {
            // Refresh download of outfit folder
            if (!outfitFolder.RequestDownloadContents(false, false, true).RequestComplete.WaitOne(TimeOut, false))
            {
                Client.Log("Outfit not changed. An error occured while downloads the folder contents of : " + outfitFolder.Name, Helpers.LogLevel.Error);
                return;
            }

            // Make sure we have some Wearable Data to start with.
            if (AgentWearablesSignal.WaitOne(1000, false) == false)
            {
                Client.Log("You must have set appearance at least once, before calling WearOutfit().  AgentWearablesSignal not set.", Helpers.LogLevel.Error);
                return;
            }

            // Flush the cached clothing wearables so we can redefine them
            for (byte i = 4; i <= 12; i++)
            {
                AgentWearablesData[i].ItemID  = LLUUID.Zero;
                AgentWearablesData[i].AssetID = LLUUID.Zero;
            }

            List <InventoryItem> attachments = new List <InventoryItem>();

            // Replace with wearables from Outfit folder
            foreach (InventoryBase ib in outfitFolder.GetContents())
            {
                if (ib is InventoryWearable)
                {
                    try
                    {
                        InventoryWearable iw = (InventoryWearable)ib;
                        Client.Log("Retrieving asset for " + iw.Name + "(" + iw.AssetID + ")", Helpers.LogLevel.Info);
                        AssetWearable.AppearanceLayerType AppearanceLayer = ((AssetWearable)iw.Asset).AppearanceLayer;

                        Client.Log("Adding skin/clothing layer for " + AppearanceLayer, Helpers.LogLevel.Info);
                        AgentWearablesData[(byte)AppearanceLayer].ItemID  = iw.ItemID;
                        AgentWearablesData[(byte)AppearanceLayer].AssetID = iw.AssetID;
                    }
                    catch (Exception e)
                    {
                        Client.Log("Asset for " + ib._Name + " unavailable: " + e.Message, Helpers.LogLevel.Error);
                    }
                }
                else if (ib is InventoryItem)
                {
                    InventoryItem ii = (InventoryItem)ib;
                    attachments.Add(ii);
                }
            }

            // Change attachments
            AddAttachments(attachments, removeExistingAttachments);

            // Create AgentIsNowWearing Packet, and send it
            SendAgentIsNowWearing();

            // Send updated AgentSetAppearance to the grid
            SendAgentSetAppearance();
        }
Example #9
0
        private void FillItemProperties()
        {
            txtItemName.Text = item.Name;

            if (item.AssetUUID != UUID.Zero)
            {
                txtUUID.Text = item.AssetUUID.ToString();
            }
            else
            {
                txtUUID.Text     = item.UUID.ToString();
                txtItemUUID.Text = item.UUID.ToString();
            }

            if (item.UUID != UUID.Zero)
            {
                txtItemUUID.Text = item.UUID.ToString();
            }

            txtItemCreator.Text     = txtItemOwner.Text = "Retreiving name...";
            txtItemDescription.Text = item.Description;

            List <UUID> avIDs = new List <UUID>();

            avIDs.Add(item.CreatorID);
            avIDs.Add(item.OwnerID);
            client.Avatars.RequestAvatarNames(avIDs);

            // Get permissions
            if ((item.Permissions.NextOwnerMask & PermissionMask.Modify) == PermissionMask.Modify)
            {
                checkBox1.Checked           = true;
                txtItemDescription.ReadOnly = false;
            }
            else
            {
                checkBox1.Checked           = false;
                txtItemDescription.ReadOnly = true;
            }

            if ((item.Permissions.NextOwnerMask & PermissionMask.Copy) == PermissionMask.Copy)
            {
                checkBox2.Checked = true;
            }
            else
            {
                checkBox2.Checked = false;
            }

            if ((item.Permissions.NextOwnerMask & PermissionMask.Transfer) == PermissionMask.Transfer)
            {
                checkBox3.Checked = true;
            }
            else
            {
                checkBox3.Checked = false;
            }

            // Set permission checboxes
            if ((item.Permissions.OwnerMask & PermissionMask.Modify) == PermissionMask.Modify)
            {
                checkBox1.Enabled           = true;
                txtItemDescription.ReadOnly = false;
            }
            else
            {
                checkBox1.Enabled           = false;
                txtItemDescription.ReadOnly = true;
            }

            if ((item.Permissions.OwnerMask & PermissionMask.Copy) == PermissionMask.Copy)
            {
                checkBox2.Enabled = true;
            }
            else
            {
                checkBox2.Enabled = false;
            }

            if ((item.Permissions.OwnerMask & PermissionMask.Transfer) == PermissionMask.Transfer)
            {
                checkBox3.Enabled = true;
                btnGive.Enabled   = true;
            }
            else
            {
                checkBox3.Enabled = false;
                btnGive.Enabled   = false;
            }

            label11.Visible = true;

            switch (item.InventoryType)
            {
            case InventoryType.Object:
                InventoryObjectConsole objectConsole = new InventoryObjectConsole(instance, item);
                btnDetach.Text     = "Detach";
                objectConsole.Dock = DockStyle.Fill;
                pnlItemTypeProp.Controls.Add(objectConsole);

                //objectConsole.Dispose();
                break;

            case InventoryType.Notecard:
                InventoryNotecardConsole notecardConsole = new InventoryNotecardConsole(instance, item);
                notecardConsole.Dock = DockStyle.Fill;
                pnlItemTypeProp.Controls.Add(notecardConsole);
                label11.Visible = false;

                //notecardConsole.Dispose();
                break;

            case InventoryType.LSL:
                InventoryScriptConsole scriptConsole = new InventoryScriptConsole(instance, item);
                scriptConsole.Dock = DockStyle.Fill;
                pnlItemTypeProp.Controls.Add(scriptConsole);
                label11.Visible = false;

                //scriptConsole.Dispose();
                break;

            case InventoryType.Snapshot:
                InventoryImageConsole imageConsole = new InventoryImageConsole(instance, item);
                imageConsole.Dock = DockStyle.Fill;
                pnlItemTypeProp.Controls.Add(imageConsole);
                label11.Visible = false;
                break;

            case InventoryType.Wearable:
                btnDetach.Text = "Take off";
                break;

            case InventoryType.Attachment:
                btnDetach.Text = "Detach";
                break;

            case InventoryType.Landmark:
                label11.Visible = false;
                break;

            case InventoryType.Animation:
                InventoryAnimationConsole animationConsole = new InventoryAnimationConsole(instance, item);
                animationConsole.Dock = DockStyle.Fill;
                pnlItemTypeProp.Controls.Add(animationConsole);
                label11.Visible = false;
                break;

            case InventoryType.Texture:
                imageConsole      = new InventoryImageConsole(instance, item);
                imageConsole.Dock = DockStyle.Fill;
                pnlItemTypeProp.Controls.Add(imageConsole);
                label11.Visible = false;
                break;

            case InventoryType.Gesture:
                InventoryGestureConsol gestureConsole = new InventoryGestureConsol(instance, item);
                gestureConsole.Dock = DockStyle.Fill;
                pnlItemTypeProp.Controls.Add(gestureConsole);
                label11.Visible = false;
                break;
            }

            if (item.InventoryType == InventoryType.Wearable)
            {
                InventoryWearable werbl = item as InventoryWearable;

                if (item.ParentUUID == instance.CoF.UUID)
                {
                    InventoryItem wItem = AInventoryItem(item);

                    werbl       = wItem as InventoryWearable;
                    label9.Text = "Wearable type: " + werbl.WearableType.ToString();
                }
                else
                {
                    label9.Text = "Wearable type: " + werbl.WearableType.ToString();
                }
            }
            else
            {
                //if (item.ParentUUID == instance.CoF.UUID)
                //{

                //}
                //else
                //{
                //    label9.Text = string.Empty;
                //}

                label9.Text = "Asset type: " + item.AssetType.ToString();
            }

            if ((item.Permissions.OwnerMask & PermissionMask.Modify) != PermissionMask.Modify)
            {
                checkBox1.Enabled = checkBox2.Enabled = checkBox3.Enabled = false;
            }

            fLoading = false;
        }
        /// <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;

            // 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
                // the "filler" block will not have a name
                if (itemBlock.Name.Length != 0)
                {
                    iDescendentsReceivedThisBlock++;

                    if (itemBlock.ItemID == LLUUID.Zero)
                    {
                        // this shouldn't ever happen, unless you've uploaded an invalid item
                        // to yourself while developping inventory code :-(
                    }
                    else
                    {
                        invItem = new InventoryItem(this, itemBlock);

                        InventoryFolder ifolder = (InventoryFolder)htFoldersByUUID[invItem.FolderID];

                        if (ifolder._Contents.Contains(invItem) == false)
                        {
                            if ((invItem.InvType == 7) && (invItem.Type == Asset.ASSET_TYPE_NOTECARD))
                            {
                                InventoryItem temp = new InventoryNotecard(this, invItem);
                                invItem = temp;
                            }

                            if ((invItem.InvType == 0) && (invItem.Type == Asset.ASSET_TYPE_IMAGE))
                            {
                                InventoryItem temp = new InventoryImage(this, invItem);
                                invItem = temp;
                            }

                            if ((invItem.InvType == 18) &&
                                (
                                    (invItem.Type == Asset.ASSET_TYPE_WEARABLE_BODY)
                                    || (invItem.Type == Asset.ASSET_TYPE_WEARABLE_CLOTHING)
                                )
                               )

                            {
                                InventoryItem temp = new InventoryWearable(this, invItem);
                                invItem = temp;
                            }

                            ifolder._Contents.Add(invItem);
                        }
                    }
                }
            }

            foreach (InventoryDescendentsPacket.FolderDataBlock folderBlock in reply.FolderData)
            {
                String name = System.Text.Encoding.UTF8.GetString(folderBlock.Name).Trim().Replace("\0", "");
                LLUUID folderid = folderBlock.FolderID;
                LLUUID parentid = folderBlock.ParentID;
            // unused?      sbyte type = folderBlock.Type;

                // There is always an folder block, even if there isn't any folders
                // the "filler" block will not have a name
                if (folderBlock.Name.Length != 0)
                {
                    invFolder = new InventoryFolder(this, name, folderid, parentid);

                    iDescendentsReceivedThisBlock++;

                    // Add folder to Parent
                    InventoryFolder ifolder = (InventoryFolder)htFoldersByUUID[invFolder.ParentID];
                    if (ifolder._Contents.Contains(invFolder) == false)
                    {
                        ifolder._Contents.Add(invFolder);
                    }

                    // Add folder to UUID Lookup
                    htFoldersByUUID[invFolder.FolderID] = invFolder;

                    // Do we recurse?
                    if (dr.Recurse)
                    {
                        // It's not the root, should be safe to "recurse"
                        if (!invFolder.FolderID.Equals(slClient.Self.InventoryRootFolderUUID))
                        {
                            bool alreadyQueued = false;
                            foreach (DownloadRequest_Folder adr in alFolderRequestQueue)
                            {
                                if (adr.FolderID == invFolder.FolderID)
                                {
                                    alreadyQueued = true;
                                    break;
                                }
                            }

                            if (!alreadyQueued)
                            {
                                alFolderRequestQueue.Add(new DownloadRequest_Folder(invFolder.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.
                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
                dr.Expected = iDescendentsExpected;
                dr.Received += iDescendentsReceivedThisBlock;
                dr.LastReceivedAtTick = Environment.TickCount;

                if (dr.Received >= dr.Expected)
                {
                    // Looks like after updating, we have all the descendents,
                    // remove from folder status.
                    FolderDownloadStatus.Remove(uuidFolderID);
                    dr.RequestComplete.Set();
                }
                else
                {
                    FolderDownloadStatus[uuidFolderID] = dr;
                }
            }
        }
Example #11
0
        /// <summary>
        /// Returned in response to a FetchInventoryDescendents request.  Contains information about the
        /// contents of a folder.
        /// </summary>
        /// <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;

            // Wait until it's safe to be looking at what is currently downloading.
            CurrentlyDownloadingMutex.WaitOne();

            // Make sure this request matches the one we believe is the currently downloading request
            if (((CurrentlyDownloadingRequest != null) && (CurrentlyDownloadingRequest.FolderID != uuidFolderID)) || (CurrentlyDownloadingRequest == null))
            {
                // Release so that we can let other things look at and modify what is currently downloading.
                CurrentlyDownloadingMutex.ReleaseMutex();

                // Log problem
                LogDescendantQueueEvent("Unexpected descendent packet for folder: " + uuidFolderID.ToStringHyphenated());

                // Just discard this packet...
                return;
            }

            // Get the Inventory folder that we'll be updating
            InventoryFolder InvFolderUpdating = (InventoryFolder)FoldersByUUID[uuidFolderID];


            // Update Inventory Manager's last tick point, used for timeouts and such
//            LastPacketRecievedAtTick = Environment.TickCount;

            // Used to count the number of descendants received to see if we're finished or not.
            int iDescendentsExpected = reply.AgentData.Descendents;
            int iDescendentsReceivedThisBlock = 0;

            #region Handle Child Items
            foreach (InventoryDescendentsPacket.ItemDataBlock itemBlock in reply.ItemData)
            {
                // There is always an item block, even if there isn't any items
                // the "filler" block will not have a name
                if (itemBlock.Name.Length != 0)
                {
                    iDescendentsReceivedThisBlock++;

                    if (itemBlock.ItemID == LLUUID.Zero)
                    {
                        // this shouldn't ever happen, unless you've uploaded an invalid item
                        // to yourself while developping inventory code :-(
                    }
                    else
                    {
                        InventoryItem TempInvItem = new InventoryItem(this, itemBlock);

                        if (InvFolderUpdating._Contents.Contains(TempInvItem) == false)
                        {
                            #region Create an instance of the appriopriate Inventory class
                            if ((TempInvItem.InvType == 7) && (TempInvItem.Type == (sbyte)Asset.AssetType.Notecard))
                            {
                                InventoryItem temp = new InventoryNotecard(this, TempInvItem);
                                TempInvItem = temp;
                            }
                            if ((TempInvItem.InvType == 3) && (TempInvItem.Type == (sbyte)Asset.AssetType.Landmark))
                            {
                                InventoryItem temp = new InventoryLandmark(this, TempInvItem);
                                TempInvItem = temp;
                            }

                            if ((TempInvItem.InvType == 0) && (TempInvItem.Type == (sbyte)Asset.AssetType.Texture))
                            {
                                InventoryItem temp = new InventoryImage(this, TempInvItem);
                                TempInvItem = temp;
                            }

                            if ((TempInvItem.InvType == 10) && (TempInvItem.Type == (sbyte)Asset.AssetType.LSLText))
                            {
                                InventoryItem temp = new InventoryScript(this, TempInvItem);
                                TempInvItem = temp;
                            }

                            if ((TempInvItem.InvType == 18) &&
                                (
                                    (TempInvItem.Type == (sbyte)Asset.AssetType.Bodypart)
                                    || (TempInvItem.Type == (sbyte)Asset.AssetType.Clothing)
                                )
                               )
                            {
                                InventoryItem temp = new InventoryWearable(this, TempInvItem);
                                TempInvItem = temp;
                            }
                            #endregion

                            InvFolderUpdating._Contents.Add(TempInvItem);
                        }
                    }
                }
            }
            #endregion

            #region Handle Child Folders
            foreach (InventoryDescendentsPacket.FolderDataBlock folderBlock in reply.FolderData)
            {
                String IncomingName = System.Text.Encoding.UTF8.GetString(folderBlock.Name).Trim().Replace("\0", "");
                LLUUID IncomingFolderID = folderBlock.FolderID;
                LLUUID IncomingParentID = folderBlock.ParentID;
                sbyte IncomingType = folderBlock.Type;

                // There is always an folder block, even if there isn't any folders
                // the "filler" block will not have a name
                if (folderBlock.Name.Length != 0)
                {
                    iDescendentsReceivedThisBlock++;

                    // See if the Incoming Folder already exists locally
                    if (FoldersByUUID.ContainsKey(IncomingFolderID))
                    {
                        InventoryFolder existingFolder = FoldersByUUID[IncomingFolderID];
                        existingFolder._Name = IncomingName;
                        existingFolder._Type = IncomingType;

                        // Check if parent of existing is the same as the incoming
                        if (!existingFolder.ParentID.Equals(IncomingParentID))
                        {
                            // Remove existing from old parent
                            if (FoldersByUUID.ContainsKey(existingFolder.ParentID))
                            {
                                InventoryFolder ExistingParent = FoldersByUUID[existingFolder.ParentID];
                                if (ExistingParent._Contents.Contains(existingFolder))
                                {
                                    ExistingParent._Contents.Remove(existingFolder);
                                }
                            }

                            // Set existings parent to new
                            existingFolder._ParentID = IncomingParentID;

                            // Connect existing folder to parent specified in new
                            if (FoldersByUUID.ContainsKey(IncomingParentID))
                            {
                                InventoryFolder ExistingParent = FoldersByUUID[IncomingParentID];
                                if (!ExistingParent._Contents.Contains(existingFolder))
                                {
                                    ExistingParent._Contents.Add(existingFolder);
                                }
                            }
                        }
                    }
                    else
                    {
                        InventoryFolder TempInvFolder = new InventoryFolder(this, IncomingName, IncomingFolderID, IncomingParentID, IncomingType);

                        // Add folder to Parent
                        if (InvFolderUpdating._Contents.Contains(TempInvFolder) == false)
                        {
                            InvFolderUpdating._Contents.Add(TempInvFolder);
                        }

                        // Add folder to local cache lookup
                        FoldersByUUID[TempInvFolder.FolderID] = TempInvFolder;

                    }


                    // Do we recurse?
                    if (CurrentlyDownloadingRequest.Recurse)
                    {
                        // It's not the root, should be safe to "recurse"
                        if (!IncomingFolderID.Equals(slClient.Self.InventoryRootFolderUUID))
                        {
                            FolderRequestPrepend(IncomingFolderID, CurrentlyDownloadingRequest.Recurse, CurrentlyDownloadingRequest.FetchFolders, CurrentlyDownloadingRequest.FetchItems, CurrentlyDownloadingRequest.Name + "/" + IncomingName);
                        }
                    }
                }
            }
            #endregion

            // Update total number of descendants expected , and update the total downloaded
            CurrentlyDownloadingRequest.Expected = iDescendentsExpected;
            CurrentlyDownloadingRequest.Received += iDescendentsReceivedThisBlock;
            CurrentlyDownloadingRequest.LastReceivedAtTick = Environment.TickCount;

            if ((iDescendentsExpected > 1) && (iDescendentsReceivedThisBlock == 0))
            {
                slClient.Log("Received an InventoryDescendant packet where it indicated that there should be at least 1 descendant, but none were present... [" + CurrentlyDownloadingRequest.Name + "]", Helpers.LogLevel.Warning); 
                CurrentlyDownloadingRequest.Expected = 0;
            }

            if (LogDescendantQueue)
            {
                slClient.Log("Received packet for: " + CurrentlyDownloadingRequest.ToString(), Helpers.LogLevel.Info);
            }

            // Check if we're finished
            if (CurrentlyDownloadingRequest.Received >= CurrentlyDownloadingRequest.Expected)
            {
                LogDescendantQueueEvent("Done downloading request: " + CurrentlyDownloadingRequest);

                // Singal anyone that was waiting for this request to finish
                CurrentlyDownloadingRequest.RequestComplete.Set();

                // Raise an event for anyone that cares to listen for downloaded folder events
                if (OnRequestDownloadFinishedEvent != null)
                {
                    DownloadRequest_EventArgs e = new DownloadRequest_EventArgs();
                    e.DownloadRequest = CurrentlyDownloadingRequest;
                    FireRequestDownloadFinishedEvent(InvFolderUpdating, e);
                }

                // Set Inventory Manager state to reflect that we're done with the current download
                CurrentlyDownloadingAFolder = false;
                CurrentlyDownloadingRequest = null;
            }

            // Release so that we can let other things look at and modify what is currently downloading.
            CurrentlyDownloadingMutex.ReleaseMutex();


            // If there's any more download requests queued, grab one, and go
            FolderRequestBegin();
        }