void RemoveInventoryItem(IClientAPI remoteClient, UUID itemID, bool forceDelete)
        {
            if (!_cofSyncEnabled)
            {
                return;
            }

            CachedUserInfo userInfo
                = m_scene.CommsManager.UserService.GetUserDetails(remoteClient.AgentId);

            if (userInfo == null)
            {
                return;
            }

            InventoryItemBase item = userInfo.FindItem(itemID);

            if (item != null && item.AssetType == (int)AssetType.Link)
            {
                lock (_currentlyWaitingCOFBuilds)
                {
                    if (!_viewer2Users.Contains(remoteClient.AgentId))
                    {
                        _viewer2Users.Add(remoteClient.AgentId);
                    }
                    bool add = false;
                    Dictionary <UUID, BuildCOF> waitingCOFs = new Dictionary <UUID, BuildCOF>();
                    if ((add = !_currentlyWaitingCOFBuilds.TryGetValue(remoteClient.AgentId, out waitingCOFs)))
                    {
                        waitingCOFs = new Dictionary <UUID, BuildCOF>();
                    }
                    if (waitingCOFs.ContainsKey(itemID))
                    {
                        BuildCOF cof = waitingCOFs[itemID];
                        cof.COFHasBeenSet();
                        if (cof.Finished())
                        {
                            waitingCOFs.Remove(itemID);
                        }
                    }
                    else
                    {
                        BuildCOF cof = new BuildCOF(ClearWaitingCOF);
                        cof.COFHasBeenSet();
                        waitingCOFs.Add(itemID, cof);
                    }
                    if (add)
                    {
                        _currentlyWaitingCOFBuilds.Add(remoteClient.AgentId, waitingCOFs);
                    }
                }
            }
        }
        void LinkInventoryItem(IClientAPI remoteClient, UUID transActionID, UUID folderID,
                               uint callbackID, string description, string name, sbyte invType, sbyte type, UUID olditemID)
        {
            if (!_cofSyncEnabled)
            {
                return;
            }

            lock (_currentlyWaitingCOFBuilds)
            {
                if (!_viewer2Users.Contains(remoteClient.AgentId))
                {
                    _viewer2Users.Add(remoteClient.AgentId);
                }
                bool add = false;
                Dictionary <UUID, BuildCOF> waitingCOFs = new Dictionary <UUID, BuildCOF>();
                if ((add = !_currentlyWaitingCOFBuilds.TryGetValue(remoteClient.AgentId, out waitingCOFs)))
                {
                    waitingCOFs = new Dictionary <UUID, BuildCOF>();
                }
                if (waitingCOFs.ContainsKey(olditemID))
                {
                    BuildCOF cof = waitingCOFs[olditemID];
                    cof.COFHasBeenSet();
                    if (cof.Finished())
                    {
                        waitingCOFs.Remove(olditemID);
                    }
                }
                else
                {
                    BuildCOF cof = new BuildCOF(ClearWaitingCOF);
                    cof.COFHasBeenSet();
                    waitingCOFs.Add(olditemID, cof);
                }
                if (add)
                {
                    _currentlyWaitingCOFBuilds.Add(remoteClient.AgentId, waitingCOFs);
                }
            }
        }
        /// <summary>
        /// Update what the avatar is wearing using an item from their inventory.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void AvatarIsWearing(Object sender, AvatarWearingArgs e)
        {
            IClientAPI clientView = (IClientAPI)sender;
            ScenePresence avatar = m_scene.GetScenePresence(clientView.AgentId);
            
            if (avatar == null) 
            {
                m_log.Error("[APPEARANCE]: Avatar is child agent, ignoring AvatarIsWearing event");
                return;
            }

            CachedUserInfo profile = m_scene.CommsManager.UserService.GetUserDetails(clientView.AgentId);
            if (profile != null)
            {
                // we need to clean out the existing textures
                AvatarAppearance appearance = avatar.Appearance;
                avatar.Appearance.ResetAppearance();

                List<AvatarWearable> wearables = new List<AvatarWearable>();
                lock (_currentlyWaitingCOFBuilds)
                {
                    //Check to see whether the client can manage itself
                    if (_cofSyncEnabled && !_viewer2Users.Contains(clientView.AgentId))
                    {
                        foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
                        {
                            wearables.Add(new AvatarWearable(wear.Type, wear.ItemID, UUID.Zero));
                            AvatarWearable oldWearable = appearance.GetWearableOfType(wear.Type);
                            if (wear.ItemID != UUID.Zero)
                            {
                                if (oldWearable == null || oldWearable.ItemID == UUID.Zero || wear.ItemID != oldWearable.ItemID)
                                {
                                    bool add = false;
                                    Dictionary<UUID, BuildCOF> waitingCOFs = new Dictionary<UUID, BuildCOF>();
                                    if ((add = !_currentlyWaitingCOFBuilds.TryGetValue(clientView.AgentId, out waitingCOFs)))
                                        waitingCOFs = new Dictionary<UUID, BuildCOF>();
                                    //Make sure that the new item is added
                                    if (waitingCOFs.ContainsKey(wear.ItemID))
                                    {
                                        BuildCOF cof = waitingCOFs[wear.ItemID];
                                        cof.SetWearableToLookFor(wear.ItemID, m_scene, clientView.AgentId, true);
                                        if (cof.Finished())
                                            waitingCOFs.Remove(wear.ItemID);
                                    }
                                    else
                                    {
                                        BuildCOF cof = new BuildCOF(ClearWaitingCOF);
                                        cof.SetWearableToLookFor(wear.ItemID, m_scene, clientView.AgentId, true);
                                        waitingCOFs.Add(wear.ItemID, cof);
                                    }
                                    if (add)
                                        _currentlyWaitingCOFBuilds.Add(clientView.AgentId, waitingCOFs);
                                }
                                if (oldWearable != null && oldWearable.ItemID != UUID.Zero && wear.ItemID != oldWearable.ItemID)
                                {
                                    bool add = false;
                                    Dictionary<UUID, BuildCOF> waitingCOFs = new Dictionary<UUID, BuildCOF>();
                                    if ((add = !_currentlyWaitingCOFBuilds.TryGetValue(clientView.AgentId, out waitingCOFs)))
                                        waitingCOFs = new Dictionary<UUID, BuildCOF>();
                                    //Check for removal of old item
                                    if (waitingCOFs.ContainsKey(oldWearable.ItemID))
                                    {
                                        BuildCOF cof = waitingCOFs[oldWearable.ItemID];
                                        cof.SetWearableToLookFor(oldWearable.ItemID, m_scene, clientView.AgentId, false);
                                        if (cof.Finished())
                                            waitingCOFs.Remove(oldWearable.ItemID);
                                    }
                                    else
                                    {
                                        BuildCOF cof = new BuildCOF(ClearWaitingCOF);
                                        cof.SetWearableToLookFor(oldWearable.ItemID, m_scene, clientView.AgentId, false);
                                        waitingCOFs.Add(oldWearable.ItemID, cof);
                                    }
                                    if (add)
                                        _currentlyWaitingCOFBuilds.Add(clientView.AgentId, waitingCOFs);
                                }
                            }
                            else if (oldWearable != null && oldWearable.ItemID != UUID.Zero)
                            {
                                bool add = false;
                                Dictionary<UUID, BuildCOF> waitingCOFs = new Dictionary<UUID, BuildCOF>();
                                if ((add = !_currentlyWaitingCOFBuilds.TryGetValue(clientView.AgentId, out waitingCOFs)))
                                    waitingCOFs = new Dictionary<UUID, BuildCOF>();
                                //Remove the item if it was just removed
                                if (waitingCOFs.ContainsKey(oldWearable.ItemID))
                                {
                                    BuildCOF cof = waitingCOFs[oldWearable.ItemID];
                                    cof.SetWearableToLookFor(oldWearable.ItemID, m_scene, clientView.AgentId, false);
                                    if (cof.Finished())
                                        waitingCOFs.Remove(oldWearable.ItemID);
                                }
                                else
                                {
                                    BuildCOF cof = new BuildCOF(ClearWaitingCOF);
                                    cof.SetWearableToLookFor(oldWearable.ItemID, m_scene, clientView.AgentId, false);
                                    waitingCOFs.Add(oldWearable.ItemID, cof);
                                }
                                if (add)
                                    _currentlyWaitingCOFBuilds.Add(clientView.AgentId, waitingCOFs);
                            }
                        }
                    }
                    else
                    {
                        foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
                            wearables.Add(new AvatarWearable(wear.Type, wear.ItemID, UUID.Zero));
                    }
                }
                // Wearables are a stack. The entries we have represent the current "top" stack state.  Apply them

                SetAppearanceAssets(profile, ref wearables, clientView);
                avatar.Appearance.SetWearables(wearables);
                this.UpdateDatabase(clientView.AgentId, avatar.Appearance, null, null);
            }
            else
            {
                m_log.WarnFormat("[APPEARANCE]: Cannot set wearables for {0}, no user profile found", clientView.Name);
            }
        }
        void RemoveInventoryItem(IClientAPI remoteClient, UUID itemID, bool forceDelete)
        {
            if (!_cofSyncEnabled) return;

            CachedUserInfo userInfo
                = m_scene.CommsManager.UserService.GetUserDetails(remoteClient.AgentId);

            if (userInfo == null)
                return;

            InventoryItemBase item = userInfo.FindItem(itemID);

            if (item != null && item.AssetType == (int)AssetType.Link)
            {
                lock (_currentlyWaitingCOFBuilds)
                {
                    if(!_viewer2Users.Contains(remoteClient.AgentId))
                        _viewer2Users.Add(remoteClient.AgentId);
                    bool add = false;
                    Dictionary<UUID, BuildCOF> waitingCOFs = new Dictionary<UUID, BuildCOF>();
                    if ((add = !_currentlyWaitingCOFBuilds.TryGetValue(remoteClient.AgentId, out waitingCOFs)))
                        waitingCOFs = new Dictionary<UUID, BuildCOF>();
                    if (waitingCOFs.ContainsKey(itemID))
                    {
                        BuildCOF cof = waitingCOFs[itemID];
                        cof.COFHasBeenSet();
                        if (cof.Finished())
                            waitingCOFs.Remove(itemID);
                    }
                    else
                    {
                        BuildCOF cof = new BuildCOF(ClearWaitingCOF);
                        cof.COFHasBeenSet();
                        waitingCOFs.Add(itemID, cof);
                    }
                    if (add)
                        _currentlyWaitingCOFBuilds.Add(remoteClient.AgentId, waitingCOFs);
                }
            }
        }
        void LinkInventoryItem(IClientAPI remoteClient, UUID transActionID, UUID folderID,
            uint callbackID, string description, string name, sbyte invType, sbyte type, UUID olditemID)
        {
            if (!_cofSyncEnabled) return;

            lock (_currentlyWaitingCOFBuilds)
            {
                if (!_viewer2Users.Contains(remoteClient.AgentId))
                    _viewer2Users.Add(remoteClient.AgentId);
                bool add = false;
                Dictionary<UUID, BuildCOF> waitingCOFs = new Dictionary<UUID, BuildCOF>();
                if ((add = !_currentlyWaitingCOFBuilds.TryGetValue(remoteClient.AgentId, out waitingCOFs)))
                    waitingCOFs = new Dictionary<UUID, BuildCOF>();
                if (waitingCOFs.ContainsKey(olditemID))
                {
                    BuildCOF cof = waitingCOFs[olditemID];
                    cof.COFHasBeenSet();
                    if (cof.Finished())
                        waitingCOFs.Remove(olditemID);
                }
                else
                {
                    BuildCOF cof = new BuildCOF(ClearWaitingCOF);
                    cof.COFHasBeenSet();
                    waitingCOFs.Add(olditemID, cof);
                }
                if (add)
                    _currentlyWaitingCOFBuilds.Add(remoteClient.AgentId, waitingCOFs);
            }
            
        }
        /// <summary>
        /// Update what the avatar is wearing using an item from their inventory.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void AvatarIsWearing(Object sender, AvatarWearingArgs e)
        {
            IClientAPI    clientView = (IClientAPI)sender;
            ScenePresence avatar     = m_scene.GetScenePresence(clientView.AgentId);

            if (avatar == null)
            {
                m_log.Error("[APPEARANCE]: Avatar is child agent, ignoring AvatarIsWearing event");
                return;
            }

            CachedUserInfo profile = m_scene.CommsManager.UserService.GetUserDetails(clientView.AgentId);

            if (profile != null)
            {
                // we need to clean out the existing textures
                AvatarAppearance appearance = avatar.Appearance;
                avatar.Appearance.ResetAppearance();

                List <AvatarWearable> wearables = new List <AvatarWearable>();
                lock (_currentlyWaitingCOFBuilds)
                {
                    //Check to see whether the client can manage itself
                    if (_cofSyncEnabled && !_viewer2Users.Contains(clientView.AgentId))
                    {
                        foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
                        {
                            wearables.Add(new AvatarWearable(wear.Type, wear.ItemID, UUID.Zero));
                            AvatarWearable oldWearable = appearance.GetWearableOfType(wear.Type);
                            if (wear.ItemID != UUID.Zero)
                            {
                                if (oldWearable == null || oldWearable.ItemID == UUID.Zero || wear.ItemID != oldWearable.ItemID)
                                {
                                    bool add = false;
                                    Dictionary <UUID, BuildCOF> waitingCOFs = new Dictionary <UUID, BuildCOF>();
                                    if ((add = !_currentlyWaitingCOFBuilds.TryGetValue(clientView.AgentId, out waitingCOFs)))
                                    {
                                        waitingCOFs = new Dictionary <UUID, BuildCOF>();
                                    }
                                    //Make sure that the new item is added
                                    if (waitingCOFs.ContainsKey(wear.ItemID))
                                    {
                                        BuildCOF cof = waitingCOFs[wear.ItemID];
                                        cof.SetWearableToLookFor(wear.ItemID, m_scene, clientView.AgentId, true);
                                        if (cof.Finished())
                                        {
                                            waitingCOFs.Remove(wear.ItemID);
                                        }
                                    }
                                    else
                                    {
                                        BuildCOF cof = new BuildCOF(ClearWaitingCOF);
                                        cof.SetWearableToLookFor(wear.ItemID, m_scene, clientView.AgentId, true);
                                        waitingCOFs.Add(wear.ItemID, cof);
                                    }
                                    if (add)
                                    {
                                        _currentlyWaitingCOFBuilds.Add(clientView.AgentId, waitingCOFs);
                                    }
                                }
                                if (oldWearable != null && oldWearable.ItemID != UUID.Zero && wear.ItemID != oldWearable.ItemID)
                                {
                                    bool add = false;
                                    Dictionary <UUID, BuildCOF> waitingCOFs = new Dictionary <UUID, BuildCOF>();
                                    if ((add = !_currentlyWaitingCOFBuilds.TryGetValue(clientView.AgentId, out waitingCOFs)))
                                    {
                                        waitingCOFs = new Dictionary <UUID, BuildCOF>();
                                    }
                                    //Check for removal of old item
                                    if (waitingCOFs.ContainsKey(oldWearable.ItemID))
                                    {
                                        BuildCOF cof = waitingCOFs[oldWearable.ItemID];
                                        cof.SetWearableToLookFor(oldWearable.ItemID, m_scene, clientView.AgentId, false);
                                        if (cof.Finished())
                                        {
                                            waitingCOFs.Remove(oldWearable.ItemID);
                                        }
                                    }
                                    else
                                    {
                                        BuildCOF cof = new BuildCOF(ClearWaitingCOF);
                                        cof.SetWearableToLookFor(oldWearable.ItemID, m_scene, clientView.AgentId, false);
                                        waitingCOFs.Add(oldWearable.ItemID, cof);
                                    }
                                    if (add)
                                    {
                                        _currentlyWaitingCOFBuilds.Add(clientView.AgentId, waitingCOFs);
                                    }
                                }
                            }
                            else if (oldWearable != null && oldWearable.ItemID != UUID.Zero)
                            {
                                bool add = false;
                                Dictionary <UUID, BuildCOF> waitingCOFs = new Dictionary <UUID, BuildCOF>();
                                if ((add = !_currentlyWaitingCOFBuilds.TryGetValue(clientView.AgentId, out waitingCOFs)))
                                {
                                    waitingCOFs = new Dictionary <UUID, BuildCOF>();
                                }
                                //Remove the item if it was just removed
                                if (waitingCOFs.ContainsKey(oldWearable.ItemID))
                                {
                                    BuildCOF cof = waitingCOFs[oldWearable.ItemID];
                                    cof.SetWearableToLookFor(oldWearable.ItemID, m_scene, clientView.AgentId, false);
                                    if (cof.Finished())
                                    {
                                        waitingCOFs.Remove(oldWearable.ItemID);
                                    }
                                }
                                else
                                {
                                    BuildCOF cof = new BuildCOF(ClearWaitingCOF);
                                    cof.SetWearableToLookFor(oldWearable.ItemID, m_scene, clientView.AgentId, false);
                                    waitingCOFs.Add(oldWearable.ItemID, cof);
                                }
                                if (add)
                                {
                                    _currentlyWaitingCOFBuilds.Add(clientView.AgentId, waitingCOFs);
                                }
                            }
                        }
                    }
                    else
                    {
                        foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
                        {
                            wearables.Add(new AvatarWearable(wear.Type, wear.ItemID, UUID.Zero));
                        }
                    }
                }
                // Wearables are a stack. The entries we have represent the current "top" stack state.  Apply them

                SetAppearanceAssets(profile, ref wearables, clientView);
                avatar.Appearance.SetWearables(wearables);
                this.UpdateDatabase(clientView.AgentId, avatar.Appearance, null, null);
            }
            else
            {
                m_log.WarnFormat("[APPEARANCE]: Cannot set wearables for {0}, no user profile found", clientView.Name);
            }
        }