diff options
author | Mike Mazur | 2009-02-16 02:25:44 +0000 |
---|---|---|
committer | Mike Mazur | 2009-02-16 02:25:44 +0000 |
commit | 16fa7f516a484e9f21fac34262214b3d9d761823 (patch) | |
tree | 925c10831c04d053b707857ffa785482316d4dcb /OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs | |
parent | Added OpenSim asset frontend plugin. (diff) | |
download | opensim-SC_OLD-16fa7f516a484e9f21fac34262214b3d9d761823.zip opensim-SC_OLD-16fa7f516a484e9f21fac34262214b3d9d761823.tar.gz opensim-SC_OLD-16fa7f516a484e9f21fac34262214b3d9d761823.tar.bz2 opensim-SC_OLD-16fa7f516a484e9f21fac34262214b3d9d761823.tar.xz |
Converted to Linux newlines.
Diffstat (limited to 'OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs')
-rw-r--r-- | OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs | 1204 |
1 files changed, 602 insertions, 602 deletions
diff --git a/OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs b/OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs index f8acdea..c140965 100644 --- a/OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs +++ b/OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs | |||
@@ -1,602 +1,602 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Intel Corporation | 2 | * Copyright (c) 2008 Intel Corporation |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * Redistribution and use in source and binary forms, with or without | 4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions | 5 | * modification, are permitted provided that the following conditions |
6 | * are met: | 6 | * are met: |
7 | * | 7 | * |
8 | * -- Redistributions of source code must retain the above copyright | 8 | * -- Redistributions of source code must retain the above copyright |
9 | * notice, this list of conditions and the following disclaimer. | 9 | * notice, this list of conditions and the following disclaimer. |
10 | * -- Redistributions in binary form must reproduce the above copyright | 10 | * -- Redistributions in binary form must reproduce the above copyright |
11 | * notice, this list of conditions and the following disclaimer in the | 11 | * notice, this list of conditions and the following disclaimer in the |
12 | * documentation and/or other materials provided with the distribution. | 12 | * documentation and/or other materials provided with the distribution. |
13 | * -- Neither the name of the Intel Corporation nor the names of its | 13 | * -- Neither the name of the Intel Corporation nor the names of its |
14 | * contributors may be used to endorse or promote products derived from | 14 | * contributors may be used to endorse or promote products derived from |
15 | * this software without specific prior written permission. | 15 | * this software without specific prior written permission. |
16 | * | 16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
18 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 18 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
19 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | 19 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
20 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS | 20 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS |
21 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 21 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
22 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 22 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
24 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 24 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
25 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
26 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 26 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | */ | 28 | */ |
29 | 29 | ||
30 | using System; | 30 | using System; |
31 | using System.Collections.Generic; | 31 | using System.Collections.Generic; |
32 | using System.Net; | 32 | using System.Net; |
33 | using System.IO; | 33 | using System.IO; |
34 | using System.Text; | 34 | using System.Text; |
35 | using ExtensionLoader; | 35 | using ExtensionLoader; |
36 | using OpenMetaverse; | 36 | using OpenMetaverse; |
37 | using OpenMetaverse.StructuredData; | 37 | using OpenMetaverse.StructuredData; |
38 | 38 | ||
39 | namespace OpenSim.Grid.AssetInventoryServer.Extensions | 39 | namespace OpenSim.Grid.AssetInventoryServer.Extensions |
40 | { | 40 | { |
41 | public class SimpleInventory : IExtension<AssetInventoryServer>, IInventoryProvider | 41 | public class SimpleInventory : IExtension<AssetInventoryServer>, IInventoryProvider |
42 | { | 42 | { |
43 | const string EXTENSION_NAME = "SimpleInventory"; // Used for metrics reporting | 43 | const string EXTENSION_NAME = "SimpleInventory"; // Used for metrics reporting |
44 | const string DEFAULT_INVENTORY_DIR = "SimpleInventory"; | 44 | const string DEFAULT_INVENTORY_DIR = "SimpleInventory"; |
45 | 45 | ||
46 | AssetInventoryServer server; | 46 | AssetInventoryServer server; |
47 | Dictionary<Uri, InventoryCollection> inventories = new Dictionary<Uri, InventoryCollection>(); | 47 | Dictionary<Uri, InventoryCollection> inventories = new Dictionary<Uri, InventoryCollection>(); |
48 | Dictionary<Uri, List<InventoryItem>> activeGestures = new Dictionary<Uri, List<InventoryItem>>(); | 48 | Dictionary<Uri, List<InventoryItem>> activeGestures = new Dictionary<Uri, List<InventoryItem>>(); |
49 | Utils.InventoryItemSerializer itemSerializer = new Utils.InventoryItemSerializer(); | 49 | Utils.InventoryItemSerializer itemSerializer = new Utils.InventoryItemSerializer(); |
50 | Utils.InventoryFolderSerializer folderSerializer = new Utils.InventoryFolderSerializer(); | 50 | Utils.InventoryFolderSerializer folderSerializer = new Utils.InventoryFolderSerializer(); |
51 | 51 | ||
52 | public SimpleInventory() | 52 | public SimpleInventory() |
53 | { | 53 | { |
54 | } | 54 | } |
55 | 55 | ||
56 | #region Required Interfaces | 56 | #region Required Interfaces |
57 | 57 | ||
58 | public void Start(AssetInventoryServer server) | 58 | public void Start(AssetInventoryServer server) |
59 | { | 59 | { |
60 | this.server = server; | 60 | this.server = server; |
61 | 61 | ||
62 | LoadFiles(DEFAULT_INVENTORY_DIR); | 62 | LoadFiles(DEFAULT_INVENTORY_DIR); |
63 | 63 | ||
64 | Logger.Log.InfoFormat("Initialized the inventory index with data for {0} avatars", | 64 | Logger.Log.InfoFormat("Initialized the inventory index with data for {0} avatars", |
65 | inventories.Count); | 65 | inventories.Count); |
66 | } | 66 | } |
67 | 67 | ||
68 | public void Stop() | 68 | public void Stop() |
69 | { | 69 | { |
70 | } | 70 | } |
71 | 71 | ||
72 | public BackendResponse TryFetchItem(Uri owner, UUID itemID, out InventoryItem item) | 72 | public BackendResponse TryFetchItem(Uri owner, UUID itemID, out InventoryItem item) |
73 | { | 73 | { |
74 | item = null; | 74 | item = null; |
75 | BackendResponse ret; | 75 | BackendResponse ret; |
76 | 76 | ||
77 | InventoryCollection collection; | 77 | InventoryCollection collection; |
78 | if (inventories.TryGetValue(owner, out collection) && collection.Items.TryGetValue(itemID, out item)) | 78 | if (inventories.TryGetValue(owner, out collection) && collection.Items.TryGetValue(itemID, out item)) |
79 | ret = BackendResponse.Success; | 79 | ret = BackendResponse.Success; |
80 | else | 80 | else |
81 | ret = BackendResponse.NotFound; | 81 | ret = BackendResponse.NotFound; |
82 | 82 | ||
83 | server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now); | 83 | server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now); |
84 | return ret; | 84 | return ret; |
85 | } | 85 | } |
86 | 86 | ||
87 | public BackendResponse TryFetchFolder(Uri owner, UUID folderID, out InventoryFolder folder) | 87 | public BackendResponse TryFetchFolder(Uri owner, UUID folderID, out InventoryFolder folder) |
88 | { | 88 | { |
89 | folder = null; | 89 | folder = null; |
90 | BackendResponse ret; | 90 | BackendResponse ret; |
91 | 91 | ||
92 | InventoryCollection collection; | 92 | InventoryCollection collection; |
93 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) | 93 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) |
94 | ret = BackendResponse.Success; | 94 | ret = BackendResponse.Success; |
95 | else | 95 | else |
96 | ret = BackendResponse.NotFound; | 96 | ret = BackendResponse.NotFound; |
97 | 97 | ||
98 | server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now); | 98 | server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now); |
99 | return ret; | 99 | return ret; |
100 | } | 100 | } |
101 | 101 | ||
102 | public BackendResponse TryFetchFolderContents(Uri owner, UUID folderID, out InventoryCollection contents) | 102 | public BackendResponse TryFetchFolderContents(Uri owner, UUID folderID, out InventoryCollection contents) |
103 | { | 103 | { |
104 | contents = null; | 104 | contents = null; |
105 | BackendResponse ret; | 105 | BackendResponse ret; |
106 | 106 | ||
107 | InventoryCollection collection; | 107 | InventoryCollection collection; |
108 | InventoryFolder folder; | 108 | InventoryFolder folder; |
109 | 109 | ||
110 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) | 110 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) |
111 | { | 111 | { |
112 | contents = new InventoryCollection(); | 112 | contents = new InventoryCollection(); |
113 | contents.UserID = collection.UserID; | 113 | contents.UserID = collection.UserID; |
114 | contents.Folders = new Dictionary<UUID, InventoryFolder>(); | 114 | contents.Folders = new Dictionary<UUID, InventoryFolder>(); |
115 | contents.Items = new Dictionary<UUID, InventoryItem>(); | 115 | contents.Items = new Dictionary<UUID, InventoryItem>(); |
116 | 116 | ||
117 | foreach (InventoryBase invBase in folder.Children.Values) | 117 | foreach (InventoryBase invBase in folder.Children.Values) |
118 | { | 118 | { |
119 | if (invBase is InventoryItem) | 119 | if (invBase is InventoryItem) |
120 | { | 120 | { |
121 | InventoryItem invItem = invBase as InventoryItem; | 121 | InventoryItem invItem = invBase as InventoryItem; |
122 | contents.Items.Add(invItem.ID, invItem); | 122 | contents.Items.Add(invItem.ID, invItem); |
123 | } | 123 | } |
124 | else | 124 | else |
125 | { | 125 | { |
126 | InventoryFolder invFolder = invBase as InventoryFolder; | 126 | InventoryFolder invFolder = invBase as InventoryFolder; |
127 | contents.Folders.Add(invFolder.ID, invFolder); | 127 | contents.Folders.Add(invFolder.ID, invFolder); |
128 | } | 128 | } |
129 | } | 129 | } |
130 | 130 | ||
131 | ret = BackendResponse.Success; | 131 | ret = BackendResponse.Success; |
132 | } | 132 | } |
133 | else | 133 | else |
134 | { | 134 | { |
135 | ret = BackendResponse.NotFound; | 135 | ret = BackendResponse.NotFound; |
136 | } | 136 | } |
137 | 137 | ||
138 | server.MetricsProvider.LogInventoryFetchFolderContents(EXTENSION_NAME, ret, owner, folderID, DateTime.Now); | 138 | server.MetricsProvider.LogInventoryFetchFolderContents(EXTENSION_NAME, ret, owner, folderID, DateTime.Now); |
139 | return ret; | 139 | return ret; |
140 | } | 140 | } |
141 | 141 | ||
142 | public BackendResponse TryFetchFolderList(Uri owner, out List<InventoryFolder> folders) | 142 | public BackendResponse TryFetchFolderList(Uri owner, out List<InventoryFolder> folders) |
143 | { | 143 | { |
144 | folders = null; | 144 | folders = null; |
145 | BackendResponse ret; | 145 | BackendResponse ret; |
146 | 146 | ||
147 | InventoryCollection collection; | 147 | InventoryCollection collection; |
148 | if (inventories.TryGetValue(owner, out collection)) | 148 | if (inventories.TryGetValue(owner, out collection)) |
149 | { | 149 | { |
150 | folders = new List<InventoryFolder>(collection.Folders.Values); | 150 | folders = new List<InventoryFolder>(collection.Folders.Values); |
151 | return BackendResponse.Success; | 151 | return BackendResponse.Success; |
152 | } | 152 | } |
153 | else | 153 | else |
154 | { | 154 | { |
155 | ret = BackendResponse.NotFound; | 155 | ret = BackendResponse.NotFound; |
156 | } | 156 | } |
157 | 157 | ||
158 | server.MetricsProvider.LogInventoryFetchFolderList(EXTENSION_NAME, ret, owner, DateTime.Now); | 158 | server.MetricsProvider.LogInventoryFetchFolderList(EXTENSION_NAME, ret, owner, DateTime.Now); |
159 | return ret; | 159 | return ret; |
160 | } | 160 | } |
161 | 161 | ||
162 | public BackendResponse TryFetchInventory(Uri owner, out InventoryCollection inventory) | 162 | public BackendResponse TryFetchInventory(Uri owner, out InventoryCollection inventory) |
163 | { | 163 | { |
164 | inventory = null; | 164 | inventory = null; |
165 | BackendResponse ret; | 165 | BackendResponse ret; |
166 | 166 | ||
167 | if (inventories.TryGetValue(owner, out inventory)) | 167 | if (inventories.TryGetValue(owner, out inventory)) |
168 | ret = BackendResponse.Success; | 168 | ret = BackendResponse.Success; |
169 | else | 169 | else |
170 | ret = BackendResponse.NotFound; | 170 | ret = BackendResponse.NotFound; |
171 | 171 | ||
172 | server.MetricsProvider.LogInventoryFetchInventory(EXTENSION_NAME, ret, owner, DateTime.Now); | 172 | server.MetricsProvider.LogInventoryFetchInventory(EXTENSION_NAME, ret, owner, DateTime.Now); |
173 | return ret; | 173 | return ret; |
174 | } | 174 | } |
175 | 175 | ||
176 | public BackendResponse TryFetchActiveGestures(Uri owner, out List<InventoryItem> gestures) | 176 | public BackendResponse TryFetchActiveGestures(Uri owner, out List<InventoryItem> gestures) |
177 | { | 177 | { |
178 | gestures = null; | 178 | gestures = null; |
179 | BackendResponse ret; | 179 | BackendResponse ret; |
180 | 180 | ||
181 | if (activeGestures.TryGetValue(owner, out gestures)) | 181 | if (activeGestures.TryGetValue(owner, out gestures)) |
182 | ret = BackendResponse.Success; | 182 | ret = BackendResponse.Success; |
183 | else | 183 | else |
184 | ret = BackendResponse.NotFound; | 184 | ret = BackendResponse.NotFound; |
185 | 185 | ||
186 | server.MetricsProvider.LogInventoryFetchActiveGestures(EXTENSION_NAME, ret, owner, DateTime.Now); | 186 | server.MetricsProvider.LogInventoryFetchActiveGestures(EXTENSION_NAME, ret, owner, DateTime.Now); |
187 | return ret; | 187 | return ret; |
188 | } | 188 | } |
189 | 189 | ||
190 | public BackendResponse TryCreateItem(Uri owner, InventoryItem item) | 190 | public BackendResponse TryCreateItem(Uri owner, InventoryItem item) |
191 | { | 191 | { |
192 | BackendResponse ret; | 192 | BackendResponse ret; |
193 | 193 | ||
194 | InventoryCollection collection; | 194 | InventoryCollection collection; |
195 | if (inventories.TryGetValue(owner, out collection)) | 195 | if (inventories.TryGetValue(owner, out collection)) |
196 | { | 196 | { |
197 | // Delete this item first if it already exists | 197 | // Delete this item first if it already exists |
198 | InventoryItem oldItem; | 198 | InventoryItem oldItem; |
199 | if (collection.Items.TryGetValue(item.ID, out oldItem)) | 199 | if (collection.Items.TryGetValue(item.ID, out oldItem)) |
200 | TryDeleteItem(owner, item.ID); | 200 | TryDeleteItem(owner, item.ID); |
201 | 201 | ||
202 | try | 202 | try |
203 | { | 203 | { |
204 | // Create the file | 204 | // Create the file |
205 | SaveItem(item); | 205 | SaveItem(item); |
206 | 206 | ||
207 | // Add the item to the collection | 207 | // Add the item to the collection |
208 | lock (collection) collection.Items[item.ID] = item; | 208 | lock (collection) collection.Items[item.ID] = item; |
209 | 209 | ||
210 | // Add the item to its parent folder | 210 | // Add the item to its parent folder |
211 | InventoryFolder parent; | 211 | InventoryFolder parent; |
212 | if (collection.Folders.TryGetValue(item.Folder, out parent)) | 212 | if (collection.Folders.TryGetValue(item.Folder, out parent)) |
213 | lock (parent.Children) parent.Children.Add(item.ID, item); | 213 | lock (parent.Children) parent.Children.Add(item.ID, item); |
214 | 214 | ||
215 | // Add active gestures to our list | 215 | // Add active gestures to our list |
216 | if (item.InvType == (int)InventoryType.Gesture && item.Flags == 1) | 216 | if (item.InvType == (int)InventoryType.Gesture && item.Flags == 1) |
217 | { | 217 | { |
218 | lock (activeGestures) | 218 | lock (activeGestures) |
219 | activeGestures[owner].Add(item); | 219 | activeGestures[owner].Add(item); |
220 | } | 220 | } |
221 | 221 | ||
222 | ret = BackendResponse.Success; | 222 | ret = BackendResponse.Success; |
223 | } | 223 | } |
224 | catch (Exception ex) | 224 | catch (Exception ex) |
225 | { | 225 | { |
226 | Logger.Log.Error(ex.Message); | 226 | Logger.Log.Error(ex.Message); |
227 | ret = BackendResponse.Failure; | 227 | ret = BackendResponse.Failure; |
228 | } | 228 | } |
229 | } | 229 | } |
230 | else | 230 | else |
231 | { | 231 | { |
232 | return BackendResponse.NotFound; | 232 | return BackendResponse.NotFound; |
233 | } | 233 | } |
234 | 234 | ||
235 | server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, false, DateTime.Now); | 235 | server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, false, DateTime.Now); |
236 | return ret; | 236 | return ret; |
237 | } | 237 | } |
238 | 238 | ||
239 | public BackendResponse TryCreateFolder(Uri owner, InventoryFolder folder) | 239 | public BackendResponse TryCreateFolder(Uri owner, InventoryFolder folder) |
240 | { | 240 | { |
241 | BackendResponse ret; | 241 | BackendResponse ret; |
242 | 242 | ||
243 | InventoryCollection collection; | 243 | InventoryCollection collection; |
244 | if (inventories.TryGetValue(owner, out collection)) | 244 | if (inventories.TryGetValue(owner, out collection)) |
245 | { | 245 | { |
246 | // Delete this folder first if it already exists | 246 | // Delete this folder first if it already exists |
247 | InventoryFolder oldFolder; | 247 | InventoryFolder oldFolder; |
248 | if (collection.Folders.TryGetValue(folder.ID, out oldFolder)) | 248 | if (collection.Folders.TryGetValue(folder.ID, out oldFolder)) |
249 | TryDeleteFolder(owner, folder.ID); | 249 | TryDeleteFolder(owner, folder.ID); |
250 | 250 | ||
251 | try | 251 | try |
252 | { | 252 | { |
253 | // Create the file | 253 | // Create the file |
254 | SaveFolder(folder); | 254 | SaveFolder(folder); |
255 | 255 | ||
256 | // Add the folder to the collection | 256 | // Add the folder to the collection |
257 | lock (collection) collection.Folders[folder.ID] = folder; | 257 | lock (collection) collection.Folders[folder.ID] = folder; |
258 | 258 | ||
259 | // Add the folder to its parent folder | 259 | // Add the folder to its parent folder |
260 | InventoryFolder parent; | 260 | InventoryFolder parent; |
261 | if (collection.Folders.TryGetValue(folder.ParentID, out parent)) | 261 | if (collection.Folders.TryGetValue(folder.ParentID, out parent)) |
262 | lock (parent.Children) parent.Children.Add(folder.ID, folder); | 262 | lock (parent.Children) parent.Children.Add(folder.ID, folder); |
263 | 263 | ||
264 | ret = BackendResponse.Success; | 264 | ret = BackendResponse.Success; |
265 | } | 265 | } |
266 | catch (Exception ex) | 266 | catch (Exception ex) |
267 | { | 267 | { |
268 | Logger.Log.Error(ex.Message); | 268 | Logger.Log.Error(ex.Message); |
269 | ret = BackendResponse.Failure; | 269 | ret = BackendResponse.Failure; |
270 | } | 270 | } |
271 | } | 271 | } |
272 | else | 272 | else |
273 | { | 273 | { |
274 | ret = BackendResponse.NotFound; | 274 | ret = BackendResponse.NotFound; |
275 | } | 275 | } |
276 | 276 | ||
277 | server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, true, DateTime.Now); | 277 | server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, true, DateTime.Now); |
278 | return ret; | 278 | return ret; |
279 | } | 279 | } |
280 | 280 | ||
281 | public BackendResponse TryCreateInventory(Uri owner, InventoryFolder rootFolder) | 281 | public BackendResponse TryCreateInventory(Uri owner, InventoryFolder rootFolder) |
282 | { | 282 | { |
283 | BackendResponse ret; | 283 | BackendResponse ret; |
284 | 284 | ||
285 | lock (inventories) | 285 | lock (inventories) |
286 | { | 286 | { |
287 | if (!inventories.ContainsKey(owner)) | 287 | if (!inventories.ContainsKey(owner)) |
288 | { | 288 | { |
289 | InventoryCollection collection = new InventoryCollection(); | 289 | InventoryCollection collection = new InventoryCollection(); |
290 | collection.UserID = rootFolder.Owner; | 290 | collection.UserID = rootFolder.Owner; |
291 | collection.Folders = new Dictionary<UUID, InventoryFolder>(); | 291 | collection.Folders = new Dictionary<UUID, InventoryFolder>(); |
292 | collection.Folders.Add(rootFolder.ID, rootFolder); | 292 | collection.Folders.Add(rootFolder.ID, rootFolder); |
293 | collection.Items = new Dictionary<UUID, InventoryItem>(); | 293 | collection.Items = new Dictionary<UUID, InventoryItem>(); |
294 | 294 | ||
295 | inventories.Add(owner, collection); | 295 | inventories.Add(owner, collection); |
296 | 296 | ||
297 | ret = BackendResponse.Success; | 297 | ret = BackendResponse.Success; |
298 | } | 298 | } |
299 | else | 299 | else |
300 | { | 300 | { |
301 | ret = BackendResponse.Failure; | 301 | ret = BackendResponse.Failure; |
302 | } | 302 | } |
303 | } | 303 | } |
304 | 304 | ||
305 | if (ret == BackendResponse.Success) | 305 | if (ret == BackendResponse.Success) |
306 | { | 306 | { |
307 | string path = Path.Combine(DEFAULT_INVENTORY_DIR, rootFolder.Owner.ToString()); | 307 | string path = Path.Combine(DEFAULT_INVENTORY_DIR, rootFolder.Owner.ToString()); |
308 | try | 308 | try |
309 | { | 309 | { |
310 | // Create the directory for this agent | 310 | // Create the directory for this agent |
311 | Directory.CreateDirectory(path); | 311 | Directory.CreateDirectory(path); |
312 | 312 | ||
313 | // Create an index.txt containing the UUID and URI for this agent | 313 | // Create an index.txt containing the UUID and URI for this agent |
314 | string[] index = new string[] { rootFolder.Owner.ToString(), owner.ToString() }; | 314 | string[] index = new string[] { rootFolder.Owner.ToString(), owner.ToString() }; |
315 | File.WriteAllLines(Path.Combine(path, "index.txt"), index); | 315 | File.WriteAllLines(Path.Combine(path, "index.txt"), index); |
316 | 316 | ||
317 | // Create the root folder file | 317 | // Create the root folder file |
318 | SaveFolder(rootFolder); | 318 | SaveFolder(rootFolder); |
319 | } | 319 | } |
320 | catch (Exception ex) | 320 | catch (Exception ex) |
321 | { | 321 | { |
322 | Logger.Log.Error(ex.Message); | 322 | Logger.Log.Error(ex.Message); |
323 | ret = BackendResponse.Failure; | 323 | ret = BackendResponse.Failure; |
324 | } | 324 | } |
325 | } | 325 | } |
326 | 326 | ||
327 | server.MetricsProvider.LogInventoryCreateInventory(EXTENSION_NAME, ret, DateTime.Now); | 327 | server.MetricsProvider.LogInventoryCreateInventory(EXTENSION_NAME, ret, DateTime.Now); |
328 | return ret; | 328 | return ret; |
329 | } | 329 | } |
330 | 330 | ||
331 | public BackendResponse TryDeleteItem(Uri owner, UUID itemID) | 331 | public BackendResponse TryDeleteItem(Uri owner, UUID itemID) |
332 | { | 332 | { |
333 | BackendResponse ret; | 333 | BackendResponse ret; |
334 | 334 | ||
335 | InventoryCollection collection; | 335 | InventoryCollection collection; |
336 | InventoryItem item; | 336 | InventoryItem item; |
337 | if (inventories.TryGetValue(owner, out collection) && collection.Items.TryGetValue(itemID, out item)) | 337 | if (inventories.TryGetValue(owner, out collection) && collection.Items.TryGetValue(itemID, out item)) |
338 | { | 338 | { |
339 | // Remove the item from its parent folder | 339 | // Remove the item from its parent folder |
340 | InventoryFolder parent; | 340 | InventoryFolder parent; |
341 | if (collection.Folders.TryGetValue(item.Folder, out parent)) | 341 | if (collection.Folders.TryGetValue(item.Folder, out parent)) |
342 | lock (parent.Children) parent.Children.Remove(itemID); | 342 | lock (parent.Children) parent.Children.Remove(itemID); |
343 | 343 | ||
344 | // Remove the item from the collection | 344 | // Remove the item from the collection |
345 | lock (collection) collection.Items.Remove(itemID); | 345 | lock (collection) collection.Items.Remove(itemID); |
346 | 346 | ||
347 | // Remove from the active gestures list if applicable | 347 | // Remove from the active gestures list if applicable |
348 | if (item.InvType == (int)InventoryType.Gesture) | 348 | if (item.InvType == (int)InventoryType.Gesture) |
349 | { | 349 | { |
350 | lock (activeGestures) | 350 | lock (activeGestures) |
351 | { | 351 | { |
352 | for (int i = 0; i < activeGestures[owner].Count; i++) | 352 | for (int i = 0; i < activeGestures[owner].Count; i++) |
353 | { | 353 | { |
354 | if (activeGestures[owner][i].ID == itemID) | 354 | if (activeGestures[owner][i].ID == itemID) |
355 | { | 355 | { |
356 | activeGestures[owner].RemoveAt(i); | 356 | activeGestures[owner].RemoveAt(i); |
357 | break; | 357 | break; |
358 | } | 358 | } |
359 | } | 359 | } |
360 | } | 360 | } |
361 | } | 361 | } |
362 | 362 | ||
363 | // Delete the file. We don't know exactly what the file name is, | 363 | // Delete the file. We don't know exactly what the file name is, |
364 | // so search for it | 364 | // so search for it |
365 | string path = PathFromURI(owner); | 365 | string path = PathFromURI(owner); |
366 | string[] matches = Directory.GetFiles(path, String.Format("*{0}.item", itemID), SearchOption.TopDirectoryOnly); | 366 | string[] matches = Directory.GetFiles(path, String.Format("*{0}.item", itemID), SearchOption.TopDirectoryOnly); |
367 | foreach (string match in matches) | 367 | foreach (string match in matches) |
368 | { | 368 | { |
369 | try { File.Delete(match); } | 369 | try { File.Delete(match); } |
370 | catch (Exception ex) { Logger.Log.ErrorFormat("Failed to delete file {0}: {1}", match, ex.Message); } | 370 | catch (Exception ex) { Logger.Log.ErrorFormat("Failed to delete file {0}: {1}", match, ex.Message); } |
371 | } | 371 | } |
372 | 372 | ||
373 | ret = BackendResponse.Success; | 373 | ret = BackendResponse.Success; |
374 | } | 374 | } |
375 | else | 375 | else |
376 | { | 376 | { |
377 | ret = BackendResponse.NotFound; | 377 | ret = BackendResponse.NotFound; |
378 | } | 378 | } |
379 | 379 | ||
380 | server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now); | 380 | server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now); |
381 | return ret; | 381 | return ret; |
382 | } | 382 | } |
383 | 383 | ||
384 | public BackendResponse TryDeleteFolder(Uri owner, UUID folderID) | 384 | public BackendResponse TryDeleteFolder(Uri owner, UUID folderID) |
385 | { | 385 | { |
386 | BackendResponse ret; | 386 | BackendResponse ret; |
387 | 387 | ||
388 | InventoryCollection collection; | 388 | InventoryCollection collection; |
389 | InventoryFolder folder; | 389 | InventoryFolder folder; |
390 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) | 390 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) |
391 | { | 391 | { |
392 | // Remove the folder from its parent folder | 392 | // Remove the folder from its parent folder |
393 | InventoryFolder parent; | 393 | InventoryFolder parent; |
394 | if (collection.Folders.TryGetValue(folder.ParentID, out parent)) | 394 | if (collection.Folders.TryGetValue(folder.ParentID, out parent)) |
395 | lock (parent.Children) parent.Children.Remove(folderID); | 395 | lock (parent.Children) parent.Children.Remove(folderID); |
396 | 396 | ||
397 | // Remove the folder from the collection | 397 | // Remove the folder from the collection |
398 | lock (collection) collection.Items.Remove(folderID); | 398 | lock (collection) collection.Items.Remove(folderID); |
399 | 399 | ||
400 | // Delete the folder file. We don't know exactly what the file name is, | 400 | // Delete the folder file. We don't know exactly what the file name is, |
401 | // so search for it | 401 | // so search for it |
402 | string path = PathFromURI(owner); | 402 | string path = PathFromURI(owner); |
403 | string[] matches = Directory.GetFiles(path, String.Format("*{0}.folder", folderID), SearchOption.TopDirectoryOnly); | 403 | string[] matches = Directory.GetFiles(path, String.Format("*{0}.folder", folderID), SearchOption.TopDirectoryOnly); |
404 | foreach (string match in matches) | 404 | foreach (string match in matches) |
405 | { | 405 | { |
406 | try { File.Delete(match); } | 406 | try { File.Delete(match); } |
407 | catch (Exception ex) { Logger.Log.ErrorFormat("Failed to delete folder file {0}: {1}", match, ex.Message); } | 407 | catch (Exception ex) { Logger.Log.ErrorFormat("Failed to delete folder file {0}: {1}", match, ex.Message); } |
408 | } | 408 | } |
409 | 409 | ||
410 | ret = BackendResponse.Success; | 410 | ret = BackendResponse.Success; |
411 | } | 411 | } |
412 | else | 412 | else |
413 | { | 413 | { |
414 | ret = BackendResponse.NotFound; | 414 | ret = BackendResponse.NotFound; |
415 | } | 415 | } |
416 | 416 | ||
417 | server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now); | 417 | server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now); |
418 | return ret; | 418 | return ret; |
419 | } | 419 | } |
420 | 420 | ||
421 | public BackendResponse TryPurgeFolder(Uri owner, UUID folderID) | 421 | public BackendResponse TryPurgeFolder(Uri owner, UUID folderID) |
422 | { | 422 | { |
423 | BackendResponse ret; | 423 | BackendResponse ret; |
424 | 424 | ||
425 | InventoryCollection collection; | 425 | InventoryCollection collection; |
426 | InventoryFolder folder; | 426 | InventoryFolder folder; |
427 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) | 427 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) |
428 | { | 428 | { |
429 | // Delete all of the folder children | 429 | // Delete all of the folder children |
430 | foreach (InventoryBase obj in new List<InventoryBase>(folder.Children.Values)) | 430 | foreach (InventoryBase obj in new List<InventoryBase>(folder.Children.Values)) |
431 | { | 431 | { |
432 | if (obj is InventoryItem) | 432 | if (obj is InventoryItem) |
433 | { | 433 | { |
434 | TryDeleteItem(owner, (obj as InventoryItem).ID); | 434 | TryDeleteItem(owner, (obj as InventoryItem).ID); |
435 | } | 435 | } |
436 | else | 436 | else |
437 | { | 437 | { |
438 | InventoryFolder childFolder = obj as InventoryFolder; | 438 | InventoryFolder childFolder = obj as InventoryFolder; |
439 | TryPurgeFolder(owner, childFolder.ID); | 439 | TryPurgeFolder(owner, childFolder.ID); |
440 | TryDeleteFolder(owner, childFolder.ID); | 440 | TryDeleteFolder(owner, childFolder.ID); |
441 | } | 441 | } |
442 | } | 442 | } |
443 | 443 | ||
444 | ret = BackendResponse.Success; | 444 | ret = BackendResponse.Success; |
445 | } | 445 | } |
446 | else | 446 | else |
447 | { | 447 | { |
448 | ret = BackendResponse.NotFound; | 448 | ret = BackendResponse.NotFound; |
449 | } | 449 | } |
450 | 450 | ||
451 | server.MetricsProvider.LogInventoryPurgeFolder(EXTENSION_NAME, ret, owner, folderID, DateTime.Now); | 451 | server.MetricsProvider.LogInventoryPurgeFolder(EXTENSION_NAME, ret, owner, folderID, DateTime.Now); |
452 | return ret; | 452 | return ret; |
453 | } | 453 | } |
454 | 454 | ||
455 | #endregion Required Interfaces | 455 | #endregion Required Interfaces |
456 | 456 | ||
457 | void SaveItem(InventoryItem item) | 457 | void SaveItem(InventoryItem item) |
458 | { | 458 | { |
459 | string filename = String.Format("{0}-{1}.item", SanitizeFilename(item.Name), item.ID); | 459 | string filename = String.Format("{0}-{1}.item", SanitizeFilename(item.Name), item.ID); |
460 | 460 | ||
461 | string path = Path.Combine(DEFAULT_INVENTORY_DIR, item.Owner.ToString()); | 461 | string path = Path.Combine(DEFAULT_INVENTORY_DIR, item.Owner.ToString()); |
462 | path = Path.Combine(path, filename); | 462 | path = Path.Combine(path, filename); |
463 | 463 | ||
464 | using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write)) | 464 | using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write)) |
465 | { | 465 | { |
466 | itemSerializer.Serialize(stream, item); | 466 | itemSerializer.Serialize(stream, item); |
467 | stream.Flush(); | 467 | stream.Flush(); |
468 | } | 468 | } |
469 | } | 469 | } |
470 | 470 | ||
471 | void SaveFolder(InventoryFolder folder) | 471 | void SaveFolder(InventoryFolder folder) |
472 | { | 472 | { |
473 | string filename = String.Format("{0}-{1}.folder", SanitizeFilename(folder.Name), folder.ID); | 473 | string filename = String.Format("{0}-{1}.folder", SanitizeFilename(folder.Name), folder.ID); |
474 | 474 | ||
475 | string path = Path.Combine(DEFAULT_INVENTORY_DIR, folder.Owner.ToString()); | 475 | string path = Path.Combine(DEFAULT_INVENTORY_DIR, folder.Owner.ToString()); |
476 | path = Path.Combine(path, filename); | 476 | path = Path.Combine(path, filename); |
477 | 477 | ||
478 | using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write)) | 478 | using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write)) |
479 | { | 479 | { |
480 | folderSerializer.Serialize(stream, folder); | 480 | folderSerializer.Serialize(stream, folder); |
481 | stream.Flush(); | 481 | stream.Flush(); |
482 | } | 482 | } |
483 | } | 483 | } |
484 | 484 | ||
485 | string SanitizeFilename(string filename) | 485 | string SanitizeFilename(string filename) |
486 | { | 486 | { |
487 | string output = filename; | 487 | string output = filename; |
488 | 488 | ||
489 | if (output.Length > 64) | 489 | if (output.Length > 64) |
490 | output = output.Substring(0, 64); | 490 | output = output.Substring(0, 64); |
491 | 491 | ||
492 | foreach (char i in Path.GetInvalidFileNameChars()) | 492 | foreach (char i in Path.GetInvalidFileNameChars()) |
493 | output = output.Replace(i, '_'); | 493 | output = output.Replace(i, '_'); |
494 | 494 | ||
495 | return output; | 495 | return output; |
496 | } | 496 | } |
497 | 497 | ||
498 | static string PathFromURI(Uri uri) | 498 | static string PathFromURI(Uri uri) |
499 | { | 499 | { |
500 | byte[] hash = OpenMetaverse.Utils.SHA1(Encoding.UTF8.GetBytes(uri.ToString())); | 500 | byte[] hash = OpenMetaverse.Utils.SHA1(Encoding.UTF8.GetBytes(uri.ToString())); |
501 | StringBuilder digest = new StringBuilder(40); | 501 | StringBuilder digest = new StringBuilder(40); |
502 | 502 | ||
503 | // Convert the hash to a hex string | 503 | // Convert the hash to a hex string |
504 | foreach (byte b in hash) | 504 | foreach (byte b in hash) |
505 | digest.AppendFormat(OpenMetaverse.Utils.EnUsCulture, "{0:x2}", b); | 505 | digest.AppendFormat(OpenMetaverse.Utils.EnUsCulture, "{0:x2}", b); |
506 | 506 | ||
507 | return Path.Combine(DEFAULT_INVENTORY_DIR, digest.ToString()); | 507 | return Path.Combine(DEFAULT_INVENTORY_DIR, digest.ToString()); |
508 | } | 508 | } |
509 | 509 | ||
510 | void LoadFiles(string folder) | 510 | void LoadFiles(string folder) |
511 | { | 511 | { |
512 | // Try to create the directory if it doesn't already exist | 512 | // Try to create the directory if it doesn't already exist |
513 | if (!Directory.Exists(folder)) | 513 | if (!Directory.Exists(folder)) |
514 | { | 514 | { |
515 | try { Directory.CreateDirectory(folder); } | 515 | try { Directory.CreateDirectory(folder); } |
516 | catch (Exception ex) | 516 | catch (Exception ex) |
517 | { | 517 | { |
518 | Logger.Log.Warn(ex.Message); | 518 | Logger.Log.Warn(ex.Message); |
519 | return; | 519 | return; |
520 | } | 520 | } |
521 | } | 521 | } |
522 | 522 | ||
523 | try | 523 | try |
524 | { | 524 | { |
525 | string[] agentFolders = Directory.GetDirectories(DEFAULT_INVENTORY_DIR); | 525 | string[] agentFolders = Directory.GetDirectories(DEFAULT_INVENTORY_DIR); |
526 | 526 | ||
527 | for (int i = 0; i < agentFolders.Length; i++) | 527 | for (int i = 0; i < agentFolders.Length; i++) |
528 | { | 528 | { |
529 | string foldername = agentFolders[i]; | 529 | string foldername = agentFolders[i]; |
530 | string indexPath = Path.Combine(foldername, "index.txt"); | 530 | string indexPath = Path.Combine(foldername, "index.txt"); |
531 | UUID ownerID = UUID.Zero; | 531 | UUID ownerID = UUID.Zero; |
532 | Uri owner = null; | 532 | Uri owner = null; |
533 | 533 | ||
534 | try | 534 | try |
535 | { | 535 | { |
536 | string[] index = File.ReadAllLines(indexPath); | 536 | string[] index = File.ReadAllLines(indexPath); |
537 | ownerID = UUID.Parse(index[0]); | 537 | ownerID = UUID.Parse(index[0]); |
538 | owner = new Uri(index[1]); | 538 | owner = new Uri(index[1]); |
539 | } | 539 | } |
540 | catch (Exception ex) | 540 | catch (Exception ex) |
541 | { | 541 | { |
542 | Logger.Log.WarnFormat("Failed loading the index file {0}: {1}", indexPath, ex.Message); | 542 | Logger.Log.WarnFormat("Failed loading the index file {0}: {1}", indexPath, ex.Message); |
543 | } | 543 | } |
544 | 544 | ||
545 | if (ownerID != UUID.Zero && owner != null) | 545 | if (ownerID != UUID.Zero && owner != null) |
546 | { | 546 | { |
547 | // Initialize the active gestures list for this agent | 547 | // Initialize the active gestures list for this agent |
548 | activeGestures.Add(owner, new List<InventoryItem>()); | 548 | activeGestures.Add(owner, new List<InventoryItem>()); |
549 | 549 | ||
550 | InventoryCollection collection = new InventoryCollection(); | 550 | InventoryCollection collection = new InventoryCollection(); |
551 | collection.UserID = ownerID; | 551 | collection.UserID = ownerID; |
552 | 552 | ||
553 | // Load all of the folders for this agent | 553 | // Load all of the folders for this agent |
554 | string[] folders = Directory.GetFiles(foldername, "*.folder", SearchOption.TopDirectoryOnly); | 554 | string[] folders = Directory.GetFiles(foldername, "*.folder", SearchOption.TopDirectoryOnly); |
555 | collection.Folders = new Dictionary<UUID,InventoryFolder>(folders.Length); | 555 | collection.Folders = new Dictionary<UUID,InventoryFolder>(folders.Length); |
556 | 556 | ||
557 | for (int j = 0; j < folders.Length; j++) | 557 | for (int j = 0; j < folders.Length; j++) |
558 | { | 558 | { |
559 | InventoryFolder invFolder = (InventoryFolder)folderSerializer.Deserialize( | 559 | InventoryFolder invFolder = (InventoryFolder)folderSerializer.Deserialize( |
560 | new FileStream(folders[j], FileMode.Open, FileAccess.Read)); | 560 | new FileStream(folders[j], FileMode.Open, FileAccess.Read)); |
561 | collection.Folders[invFolder.ID] = invFolder; | 561 | collection.Folders[invFolder.ID] = invFolder; |
562 | } | 562 | } |
563 | 563 | ||
564 | // Iterate over the folders collection, adding children to their parents | 564 | // Iterate over the folders collection, adding children to their parents |
565 | foreach (InventoryFolder invFolder in collection.Folders.Values) | 565 | foreach (InventoryFolder invFolder in collection.Folders.Values) |
566 | { | 566 | { |
567 | InventoryFolder parent; | 567 | InventoryFolder parent; |
568 | if (collection.Folders.TryGetValue(invFolder.ParentID, out parent)) | 568 | if (collection.Folders.TryGetValue(invFolder.ParentID, out parent)) |
569 | parent.Children[invFolder.ID] = invFolder; | 569 | parent.Children[invFolder.ID] = invFolder; |
570 | } | 570 | } |
571 | 571 | ||
572 | // Load all of the items for this agent | 572 | // Load all of the items for this agent |
573 | string[] files = Directory.GetFiles(foldername, "*.item", SearchOption.TopDirectoryOnly); | 573 | string[] files = Directory.GetFiles(foldername, "*.item", SearchOption.TopDirectoryOnly); |
574 | collection.Items = new Dictionary<UUID, InventoryItem>(files.Length); | 574 | collection.Items = new Dictionary<UUID, InventoryItem>(files.Length); |
575 | 575 | ||
576 | for (int j = 0; j < files.Length; j++) | 576 | for (int j = 0; j < files.Length; j++) |
577 | { | 577 | { |
578 | InventoryItem invItem = (InventoryItem)itemSerializer.Deserialize( | 578 | InventoryItem invItem = (InventoryItem)itemSerializer.Deserialize( |
579 | new FileStream(files[j], FileMode.Open, FileAccess.Read)); | 579 | new FileStream(files[j], FileMode.Open, FileAccess.Read)); |
580 | collection.Items[invItem.ID] = invItem; | 580 | collection.Items[invItem.ID] = invItem; |
581 | 581 | ||
582 | // Add items to their parent folders | 582 | // Add items to their parent folders |
583 | InventoryFolder parent; | 583 | InventoryFolder parent; |
584 | if (collection.Folders.TryGetValue(invItem.Folder, out parent)) | 584 | if (collection.Folders.TryGetValue(invItem.Folder, out parent)) |
585 | parent.Children[invItem.ID] = invItem; | 585 | parent.Children[invItem.ID] = invItem; |
586 | 586 | ||
587 | // Add active gestures to our list | 587 | // Add active gestures to our list |
588 | if (invItem.InvType == (int)InventoryType.Gesture && invItem.Flags != 0) | 588 | if (invItem.InvType == (int)InventoryType.Gesture && invItem.Flags != 0) |
589 | activeGestures[owner].Add(invItem); | 589 | activeGestures[owner].Add(invItem); |
590 | } | 590 | } |
591 | 591 | ||
592 | inventories.Add(owner, collection); | 592 | inventories.Add(owner, collection); |
593 | } | 593 | } |
594 | } | 594 | } |
595 | } | 595 | } |
596 | catch (Exception ex) | 596 | catch (Exception ex) |
597 | { | 597 | { |
598 | Logger.Log.ErrorFormat("Failed loading inventory from {0}: {1}", folder, ex.Message); | 598 | Logger.Log.ErrorFormat("Failed loading inventory from {0}: {1}", folder, ex.Message); |
599 | } | 599 | } |
600 | } | 600 | } |
601 | } | 601 | } |
602 | } | 602 | } |