OSDN Git Service

RAD-469 Initialize avatar on first login for new accounts
authorLatif Khalifa <latifer@streamgrid.net>
Wed, 5 Mar 2014 00:03:48 +0000 (01:03 +0100)
committerLatif Khalifa <latifer@streamgrid.net>
Wed, 5 Mar 2014 00:04:18 +0000 (01:04 +0100)
Radegast/Core/InitialOutfit.cs [new file with mode: 0644]
Radegast/GUI/Consoles/Inventory/CurrentOutfitFolder.cs
Radegast/GUI/Consoles/Inventory/InventoryConsole.cs

diff --git a/Radegast/Core/InitialOutfit.cs b/Radegast/Core/InitialOutfit.cs
new file mode 100644 (file)
index 0000000..f508527
--- /dev/null
@@ -0,0 +1,208 @@
+// 
+// Radegast Metaverse Client
+// Copyright (c) 2009-2014, Radegast Development Team
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//     * Redistributions of source code must retain the above copyright notice,
+//       this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of the application "Radegast", nor the names of its
+//       contributors may be used to endorse or promote products derived from
+//       this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+
+namespace Radegast
+{
+    public class InitialOutfit
+    {
+
+        RadegastInstance Instance;
+        GridClient Client { get { return Instance.Client; }}
+        Inventory Store;
+
+        public InitialOutfit(RadegastInstance instance)
+        {
+            this.Instance = instance;
+            Store = Client.Inventory.Store;
+        }
+
+        public static InventoryNode FindNodeMyName(InventoryNode root, string name)
+        {
+            if (root.Data.Name == name)
+            {
+                return root;
+            }
+
+            foreach (var node in root.Nodes.Values)
+            {
+                var ret = FindNodeMyName(node, name);
+                if (ret != null)
+                {
+                    return ret;
+                }
+            }
+
+            return null;
+        }
+
+        public UUID CreateFolder(UUID parent, string name, AssetType type)
+        {
+            UUID ret = UUID.Zero;
+            AutoResetEvent folderCreated = new AutoResetEvent(false);
+
+            EventHandler<InventoryObjectAddedEventArgs> handler = (object sender, InventoryObjectAddedEventArgs e) =>
+            {
+                if (e.Obj.Name == name && e.Obj is InventoryFolder && ((InventoryFolder)e.Obj).PreferredType == type)
+                {
+                    ret = e.Obj.UUID;
+                    folderCreated.Set();
+                    Logger.Log("Created folder " + e.Obj.Name, Helpers.LogLevel.Info);
+                }
+            };
+
+            Client.Inventory.Store.InventoryObjectAdded += handler;
+            ret = Client.Inventory.CreateFolder(parent, name, type);
+            bool success = folderCreated.WaitOne(20 * 1000, false);
+            Client.Inventory.Store.InventoryObjectAdded -= handler;
+
+            if (success)
+            {
+                return ret;
+            }
+            else
+            {
+                return UUID.Zero;
+            }
+        }
+
+        List<InventoryBase> FetchFolder(InventoryFolder folder)
+        {
+            List<InventoryBase> ret = new List<InventoryBase>();
+
+            AutoResetEvent folderFetched = new AutoResetEvent(false);
+
+            EventHandler<FolderUpdatedEventArgs> handler = (object sender, FolderUpdatedEventArgs e) =>
+            {
+                if (e.FolderID == folder.UUID)
+                {
+                    ret = Store.GetContents(e.FolderID);
+                    folderFetched.Set();
+                }
+            };
+
+            Client.Inventory.FolderUpdated += handler;
+            Client.Inventory.RequestFolderContents(folder.UUID, folder.OwnerID, true, true, InventorySortOrder.ByName);
+            bool success = folderFetched.WaitOne(20 * 1000, false);
+            Client.Inventory.FolderUpdated -= handler;
+            return ret;
+        }
+
+        public void CheckFolders()
+        {
+            // Check if we have clothing folder
+            var clothingID = Client.Inventory.FindFolderForType(AssetType.Clothing);
+            if (clothingID == Store.RootFolder.UUID)
+            {
+                clothingID = CreateFolder(Store.RootFolder.UUID, "Clothing", AssetType.Clothing);
+            }
+
+            // Check if we have trash folder
+            var trashID = Client.Inventory.FindFolderForType(AssetType.TrashFolder);
+            if (trashID == Store.RootFolder.UUID)
+            {
+                trashID = CreateFolder(Store.RootFolder.UUID, "Trash", AssetType.TrashFolder);
+            }
+        }
+
+        public UUID CopyFolder(InventoryFolder folder, UUID destination)
+        {
+            UUID newFolderID = CreateFolder(destination, folder.Name, folder.PreferredType);
+            //var newFolder = (InventoryFolder)Store[newFolderID];
+
+            var items = FetchFolder(folder);
+            foreach (var item in items)
+            {
+                if (item is InventoryItem)
+                {
+                    AutoResetEvent itemCopied = new AutoResetEvent(false);
+                    Client.Inventory.RequestCopyItem(item.UUID, newFolderID, item.Name, item.OwnerID, (newItem) =>
+                    {
+                        itemCopied.Set();
+                    });
+                    if (itemCopied.WaitOne(20 * 1000, false))
+                    {
+                        Logger.Log("Copied item " + item.Name, Helpers.LogLevel.Info);
+                    }
+                    else
+                    {
+                        Logger.Log("Failed to copy item " + item.Name, Helpers.LogLevel.Warning);
+                    }
+                }
+                else if (item is InventoryFolder)
+                {
+                    CopyFolder((InventoryFolder)item, newFolderID);
+                }
+            }
+
+            return newFolderID;
+        }
+
+        public void SetInitialOutfit(string outfit)
+        {
+            Thread t = new Thread(() => PerformInit(outfit));
+
+            t.IsBackground = true;
+            t.Name = "Initial outfit thread";
+            t.Start();
+        }
+
+        void PerformInit(string initialOutfitName)
+        {
+            Logger.Log("Starting intial outfit thread (first login)", Helpers.LogLevel.Debug);
+            var outfitFolder = FindNodeMyName(Store.LibraryRootNode, initialOutfitName);
+
+            if (outfitFolder == null)
+            {
+                return;
+            }
+
+            CheckFolders();
+
+            UUID newClothingFolder = CopyFolder((InventoryFolder)outfitFolder.Data, Client.Inventory.FindFolderForType(AssetType.Clothing));
+
+            List<InventoryItem> newOutfit = new List<InventoryItem>();
+            foreach (var item in Store.GetContents(newClothingFolder))
+            {
+                if (item is InventoryWearable || item is InventoryAttachment || item is InventoryObject)
+                {
+                    newOutfit.Add((InventoryItem)item);
+                }
+            }
+
+            Instance.COF.ReplaceOutfit(newOutfit);
+            Logger.Log("Intial outfit thread (first login) exiting", Helpers.LogLevel.Debug);
+        }
+    }
+}
index 4dedc3f..95eb20a 100644 (file)
@@ -543,7 +543,7 @@ namespace Radegast
                 AddLink(item);
             }
 
-            Client.Appearance.ReplaceOutfit(outfit);
+            Client.Appearance.ReplaceOutfit(outfit, false);
             WorkPool.QueueUserWorkItem(sync =>
             {
                 Thread.Sleep(2000);
index f000fff..9ccce1e 100644 (file)
@@ -825,6 +825,13 @@ namespace Radegast
             UpdateStatus("OK");
             instance.TabConsole.DisplayNotificationInChat("Inventory update completed.");
 
+            if ((client.Network.LoginResponseData.FirstLogin) && !string.IsNullOrEmpty(client.Network.LoginResponseData.InitialOutfit))
+            {
+                client.Self.SetAgentAccess("A");
+                var initOufit = new InitialOutfit(instance);
+                initOufit.SetInitialOutfit(client.Network.LoginResponseData.InitialOutfit);
+            }
+
             // Updated labels on clothes that we are wearing
             UpdateWornLabels();