OSDN Git Service

Adjust to the introduction of FolderType ENUM in libomv
[radegast/radegast.git] / Radegast / Core / InitialOutfit.cs
1 // 
2 // Radegast Metaverse Client
3 // Copyright (c) 2009-2014, Radegast Development Team
4 // All rights reserved.
5 // 
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // 
9 //     * Redistributions of source code must retain the above copyright notice,
10 //       this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above copyright
12 //       notice, this list of conditions and the following disclaimer in the
13 //       documentation and/or other materials provided with the distribution.
14 //     * Neither the name of the application "Radegast", nor the names of its
15 //       contributors may be used to endorse or promote products derived from
16 //       this software without specific prior written permission.
17 // 
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 //
29
30 using System;
31 using System.Collections.Generic;
32 using System.Threading;
33 using OpenMetaverse;
34 using OpenMetaverse.StructuredData;
35
36 namespace Radegast
37 {
38     public class InitialOutfit
39     {
40
41         RadegastInstance Instance;
42         GridClient Client { get { return Instance.Client; }}
43         Inventory Store;
44
45         public InitialOutfit(RadegastInstance instance)
46         {
47             this.Instance = instance;
48             Store = Client.Inventory.Store;
49         }
50
51         public static InventoryNode FindNodeMyName(InventoryNode root, string name)
52         {
53             if (root.Data.Name == name)
54             {
55                 return root;
56             }
57
58             foreach (var node in root.Nodes.Values)
59             {
60                 var ret = FindNodeMyName(node, name);
61                 if (ret != null)
62                 {
63                     return ret;
64                 }
65             }
66
67             return null;
68         }
69
70         public UUID CreateFolder(UUID parent, string name, FolderType type)
71         {
72             UUID ret = UUID.Zero;
73             AutoResetEvent folderCreated = new AutoResetEvent(false);
74
75             EventHandler<InventoryObjectAddedEventArgs> handler = (object sender, InventoryObjectAddedEventArgs e) =>
76             {
77                 if (e.Obj.Name == name && e.Obj is InventoryFolder && ((InventoryFolder)e.Obj).PreferredType == type)
78                 {
79                     ret = e.Obj.UUID;
80                     folderCreated.Set();
81                     Logger.Log("Created folder " + e.Obj.Name, Helpers.LogLevel.Info);
82                 }
83             };
84
85             Client.Inventory.Store.InventoryObjectAdded += handler;
86             ret = Client.Inventory.CreateFolder(parent, name, type);
87             bool success = folderCreated.WaitOne(20 * 1000, false);
88             Client.Inventory.Store.InventoryObjectAdded -= handler;
89
90             if (success)
91             {
92                 return ret;
93             }
94             else
95             {
96                 return UUID.Zero;
97             }
98         }
99
100         List<InventoryBase> FetchFolder(InventoryFolder folder)
101         {
102             List<InventoryBase> ret = new List<InventoryBase>();
103
104             AutoResetEvent folderFetched = new AutoResetEvent(false);
105
106             EventHandler<FolderUpdatedEventArgs> handler = (object sender, FolderUpdatedEventArgs e) =>
107             {
108                 if (e.FolderID == folder.UUID)
109                 {
110                     ret = Store.GetContents(e.FolderID);
111                     folderFetched.Set();
112                 }
113             };
114
115             Client.Inventory.FolderUpdated += handler;
116             Client.Inventory.RequestFolderContents(folder.UUID, folder.OwnerID, true, true, InventorySortOrder.ByName);
117             bool success = folderFetched.WaitOne(20 * 1000, false);
118             Client.Inventory.FolderUpdated -= handler;
119             return ret;
120         }
121
122         public void CheckFolders()
123         {
124             // Check if we have clothing folder
125             var clothingID = Client.Inventory.FindFolderForType(FolderType.Clothing);
126             if (clothingID == Store.RootFolder.UUID)
127             {
128                 clothingID = CreateFolder(Store.RootFolder.UUID, "Clothing", FolderType.Clothing);
129             }
130
131             // Check if we have trash folder
132             var trashID = Client.Inventory.FindFolderForType(FolderType.Trash);
133             if (trashID == Store.RootFolder.UUID)
134             {
135                 trashID = CreateFolder(Store.RootFolder.UUID, "Trash", FolderType.Trash);
136             }
137         }
138
139         public UUID CopyFolder(InventoryFolder folder, UUID destination)
140         {
141             UUID newFolderID = CreateFolder(destination, folder.Name, folder.PreferredType);
142             //var newFolder = (InventoryFolder)Store[newFolderID];
143
144             var items = FetchFolder(folder);
145             foreach (var item in items)
146             {
147                 if (item is InventoryItem)
148                 {
149                     AutoResetEvent itemCopied = new AutoResetEvent(false);
150                     Client.Inventory.RequestCopyItem(item.UUID, newFolderID, item.Name, item.OwnerID, (newItem) =>
151                     {
152                         itemCopied.Set();
153                     });
154                     if (itemCopied.WaitOne(20 * 1000, false))
155                     {
156                         Logger.Log("Copied item " + item.Name, Helpers.LogLevel.Info);
157                     }
158                     else
159                     {
160                         Logger.Log("Failed to copy item " + item.Name, Helpers.LogLevel.Warning);
161                     }
162                 }
163                 else if (item is InventoryFolder)
164                 {
165                     CopyFolder((InventoryFolder)item, newFolderID);
166                 }
167             }
168
169             return newFolderID;
170         }
171
172         public void SetInitialOutfit(string outfit)
173         {
174             Thread t = new Thread(() => PerformInit(outfit));
175
176             t.IsBackground = true;
177             t.Name = "Initial outfit thread";
178             t.Start();
179         }
180
181         void PerformInit(string initialOutfitName)
182         {
183             Logger.Log("Starting intial outfit thread (first login)", Helpers.LogLevel.Debug);
184             var outfitFolder = FindNodeMyName(Store.LibraryRootNode, initialOutfitName);
185
186             if (outfitFolder == null)
187             {
188                 return;
189             }
190
191             CheckFolders();
192
193             UUID newClothingFolder = CopyFolder((InventoryFolder)outfitFolder.Data, Client.Inventory.FindFolderForType(AssetType.Clothing));
194
195             List<InventoryItem> newOutfit = new List<InventoryItem>();
196             foreach (var item in Store.GetContents(newClothingFolder))
197             {
198                 if (item is InventoryWearable || item is InventoryAttachment || item is InventoryObject)
199                 {
200                     newOutfit.Add((InventoryItem)item);
201                 }
202             }
203
204             Instance.COF.ReplaceOutfit(newOutfit);
205             Logger.Log("Intial outfit thread (first login) exiting", Helpers.LogLevel.Debug);
206         }
207     }
208 }