diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Scene.Inventory.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 2665 |
1 files changed, 2665 insertions, 0 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs new file mode 100644 index 0000000..e366c79 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | |||
@@ -0,0 +1,2665 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Reflection; | ||
31 | using System.Text; | ||
32 | using System.Timers; | ||
33 | using OpenMetaverse; | ||
34 | using log4net; | ||
35 | using OpenSim.Framework; | ||
36 | using OpenSim.Framework.Communications.Cache; | ||
37 | using OpenSim.Region.Framework; | ||
38 | using OpenSim.Region.Framework.Interfaces; | ||
39 | |||
40 | namespace OpenSim.Region.Framework.Scenes | ||
41 | { | ||
42 | public partial class Scene | ||
43 | { | ||
44 | private static readonly ILog m_log | ||
45 | = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
46 | |||
47 | /// <summary> | ||
48 | /// Allows asynchronous derezzing of objects from the scene into a client's inventory. | ||
49 | /// </summary> | ||
50 | protected AsyncSceneObjectGroupDeleter m_asyncSceneObjectDeleter; | ||
51 | |||
52 | /// <summary> | ||
53 | /// Start all the scripts in the scene which should be started. | ||
54 | /// </summary> | ||
55 | public void CreateScriptInstances() | ||
56 | { | ||
57 | m_log.Info("[PRIM INVENTORY]: Starting scripts in scene"); | ||
58 | |||
59 | foreach (EntityBase group in Entities) | ||
60 | { | ||
61 | if (group is SceneObjectGroup) | ||
62 | { | ||
63 | ((SceneObjectGroup) group).CreateScriptInstances(0, false, DefaultScriptEngine, 0); | ||
64 | } | ||
65 | } | ||
66 | } | ||
67 | |||
68 | public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item) | ||
69 | { | ||
70 | IMoneyModule money=RequestModuleInterface<IMoneyModule>(); | ||
71 | if (money != null) | ||
72 | { | ||
73 | money.ApplyUploadCharge(agentID); | ||
74 | } | ||
75 | |||
76 | AddInventoryItem(agentID, item); | ||
77 | } | ||
78 | |||
79 | public bool AddInventoryItemReturned(UUID AgentId, InventoryItemBase item) | ||
80 | { | ||
81 | CachedUserInfo userInfo | ||
82 | = CommsManager.UserProfileCacheService.GetUserDetails(AgentId); | ||
83 | if (userInfo != null) | ||
84 | { | ||
85 | userInfo.AddItem(item); | ||
86 | return true; | ||
87 | } | ||
88 | else | ||
89 | { | ||
90 | m_log.ErrorFormat( | ||
91 | "[AGENT INVENTORY]: Agent was not found for add of item {1} {2}", item.Name, item.ID); | ||
92 | |||
93 | return false; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | public void AddInventoryItem(UUID AgentID, InventoryItemBase item) | ||
98 | { | ||
99 | CachedUserInfo userInfo | ||
100 | = CommsManager.UserProfileCacheService.GetUserDetails(AgentID); | ||
101 | |||
102 | if (userInfo != null) | ||
103 | { | ||
104 | userInfo.AddItem(item); | ||
105 | |||
106 | int userlevel = 0; | ||
107 | if (Permissions.IsGod(AgentID)) | ||
108 | { | ||
109 | userlevel = 1; | ||
110 | } | ||
111 | // TODO: remove this cruft once MasterAvatar is fully deprecated | ||
112 | // | ||
113 | if (m_regInfo.MasterAvatarAssignedUUID == AgentID) | ||
114 | { | ||
115 | userlevel = 2; | ||
116 | } | ||
117 | EventManager.TriggerOnNewInventoryItemUploadComplete(AgentID, item.AssetID, item.Name, userlevel); | ||
118 | } | ||
119 | else | ||
120 | { | ||
121 | m_log.ErrorFormat( | ||
122 | "[AGENT INVENTORY]: Agent {1} was not found for add of item {2} {3}", | ||
123 | AgentID, item.Name, item.ID); | ||
124 | |||
125 | return; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | /// <summary> | ||
130 | /// Add an inventory item to an avatar's inventory. | ||
131 | /// </summary> | ||
132 | /// <param name="remoteClient">The remote client controlling the avatar</param> | ||
133 | /// <param name="item">The item. This structure contains all the item metadata, including the folder | ||
134 | /// in which the item is to be placed.</param> | ||
135 | public void AddInventoryItem(IClientAPI remoteClient, InventoryItemBase item) | ||
136 | { | ||
137 | CachedUserInfo userInfo | ||
138 | = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
139 | |||
140 | if (userInfo != null) | ||
141 | { | ||
142 | AddInventoryItem(remoteClient.AgentId, item); | ||
143 | remoteClient.SendInventoryItemCreateUpdate(item); | ||
144 | } | ||
145 | else | ||
146 | { | ||
147 | m_log.ErrorFormat( | ||
148 | "[AGENT INVENTORY]: Could not resolve user {0} for adding an inventory item", | ||
149 | remoteClient.AgentId); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | /// <summary> | ||
154 | /// Capability originating call to update the asset of an item in an agent's inventory | ||
155 | /// </summary> | ||
156 | /// <param name="remoteClient"></param> | ||
157 | /// <param name="itemID"></param> | ||
158 | /// <param name="data"></param> | ||
159 | /// <returns></returns> | ||
160 | public virtual UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data) | ||
161 | { | ||
162 | CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
163 | if (userInfo != null) | ||
164 | { | ||
165 | if (userInfo.RootFolder != null) | ||
166 | { | ||
167 | InventoryItemBase item = userInfo.RootFolder.FindItem(itemID); | ||
168 | |||
169 | if (item != null) | ||
170 | { | ||
171 | if ((InventoryType)item.InvType == InventoryType.Notecard) | ||
172 | { | ||
173 | if (!Permissions.CanEditNotecard(itemID, UUID.Zero, remoteClient.AgentId)) | ||
174 | { | ||
175 | remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false); | ||
176 | return UUID.Zero; | ||
177 | } | ||
178 | |||
179 | remoteClient.SendAgentAlertMessage("Notecard saved", false); | ||
180 | } | ||
181 | else if ((InventoryType)item.InvType == InventoryType.LSL) | ||
182 | { | ||
183 | if (!Permissions.CanEditScript(itemID, UUID.Zero, remoteClient.AgentId)) | ||
184 | { | ||
185 | remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false); | ||
186 | return UUID.Zero; | ||
187 | } | ||
188 | |||
189 | remoteClient.SendAgentAlertMessage("Script saved", false); | ||
190 | } | ||
191 | |||
192 | AssetBase asset = | ||
193 | CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data); | ||
194 | AssetCache.AddAsset(asset); | ||
195 | |||
196 | item.AssetID = asset.Metadata.FullID; | ||
197 | userInfo.UpdateItem(item); | ||
198 | |||
199 | // remoteClient.SendInventoryItemCreateUpdate(item); | ||
200 | return (asset.Metadata.FullID); | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | else | ||
205 | { | ||
206 | m_log.ErrorFormat( | ||
207 | "[AGENT INVENTORY]: Could not resolve user {0} for caps inventory update", | ||
208 | remoteClient.AgentId); | ||
209 | } | ||
210 | |||
211 | return UUID.Zero; | ||
212 | } | ||
213 | |||
214 | /// <summary> | ||
215 | /// <see>CapsUpdatedInventoryItemAsset(IClientAPI, UUID, byte[])</see> | ||
216 | /// </summary> | ||
217 | public UUID CapsUpdateInventoryItemAsset(UUID avatarId, UUID itemID, byte[] data) | ||
218 | { | ||
219 | ScenePresence avatar; | ||
220 | |||
221 | if (TryGetAvatar(avatarId, out avatar)) | ||
222 | { | ||
223 | return CapsUpdateInventoryItemAsset(avatar.ControllingClient, itemID, data); | ||
224 | } | ||
225 | else | ||
226 | { | ||
227 | m_log.ErrorFormat( | ||
228 | "[AGENT INVENTORY]: " + | ||
229 | "Avatar {0} cannot be found to update its inventory item asset", | ||
230 | avatarId); | ||
231 | } | ||
232 | |||
233 | return UUID.Zero; | ||
234 | } | ||
235 | |||
236 | /// <summary> | ||
237 | /// Capability originating call to update the asset of a script in a prim's (task's) inventory | ||
238 | /// </summary> | ||
239 | /// <param name="remoteClient"></param> | ||
240 | /// <param name="itemID"></param> | ||
241 | /// <param name="primID">The prim which contains the item to update</param> | ||
242 | /// <param name="isScriptRunning">Indicates whether the script to update is currently running</param> | ||
243 | /// <param name="data"></param> | ||
244 | public void CapsUpdateTaskInventoryScriptAsset(IClientAPI remoteClient, UUID itemId, | ||
245 | UUID primId, bool isScriptRunning, byte[] data) | ||
246 | { | ||
247 | if (!Permissions.CanEditScript(itemId, primId, remoteClient.AgentId)) | ||
248 | { | ||
249 | remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false); | ||
250 | return; | ||
251 | } | ||
252 | |||
253 | // Retrieve group | ||
254 | SceneObjectPart part = GetSceneObjectPart(primId); | ||
255 | SceneObjectGroup group = part.ParentGroup; | ||
256 | if (null == group) | ||
257 | { | ||
258 | m_log.ErrorFormat( | ||
259 | "[PRIM INVENTORY]: " + | ||
260 | "Prim inventory update requested for item ID {0} in prim ID {1} but this prim does not exist", | ||
261 | itemId, primId); | ||
262 | |||
263 | return; | ||
264 | } | ||
265 | |||
266 | // Retrieve item | ||
267 | TaskInventoryItem item = group.GetInventoryItem(part.LocalId, itemId); | ||
268 | |||
269 | if (null == item) | ||
270 | { | ||
271 | m_log.ErrorFormat( | ||
272 | "[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for caps script update " | ||
273 | + " but the item does not exist in this inventory", | ||
274 | itemId, part.Name, part.UUID); | ||
275 | |||
276 | return; | ||
277 | } | ||
278 | |||
279 | AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)AssetType.LSLText, data); | ||
280 | AssetCache.AddAsset(asset); | ||
281 | |||
282 | if (isScriptRunning) | ||
283 | { | ||
284 | part.Inventory.RemoveScriptInstance(item.ItemID); | ||
285 | } | ||
286 | |||
287 | // Update item with new asset | ||
288 | item.AssetID = asset.Metadata.FullID; | ||
289 | group.UpdateInventoryItem(item); | ||
290 | part.GetProperties(remoteClient); | ||
291 | |||
292 | // Trigger rerunning of script (use TriggerRezScript event, see RezScript) | ||
293 | if (isScriptRunning) | ||
294 | { | ||
295 | // Needs to determine which engine was running it and use that | ||
296 | // | ||
297 | part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); | ||
298 | } | ||
299 | else | ||
300 | { | ||
301 | remoteClient.SendAgentAlertMessage("Script saved", false); | ||
302 | } | ||
303 | } | ||
304 | |||
305 | /// <summary> | ||
306 | /// <see>CapsUpdateTaskInventoryScriptAsset(IClientAPI, UUID, UUID, bool, byte[])</see> | ||
307 | /// </summary> | ||
308 | public void CapsUpdateTaskInventoryScriptAsset(UUID avatarId, UUID itemId, | ||
309 | UUID primId, bool isScriptRunning, byte[] data) | ||
310 | { | ||
311 | ScenePresence avatar; | ||
312 | |||
313 | if (TryGetAvatar(avatarId, out avatar)) | ||
314 | { | ||
315 | CapsUpdateTaskInventoryScriptAsset( | ||
316 | avatar.ControllingClient, itemId, primId, isScriptRunning, data); | ||
317 | } | ||
318 | else | ||
319 | { | ||
320 | m_log.ErrorFormat( | ||
321 | "[PRIM INVENTORY]: " + | ||
322 | "Avatar {0} cannot be found to update its prim item asset", | ||
323 | avatarId); | ||
324 | } | ||
325 | } | ||
326 | |||
327 | /// <summary> | ||
328 | /// Update an item which is either already in the client's inventory or is within | ||
329 | /// a transaction | ||
330 | /// </summary> | ||
331 | /// <param name="remoteClient"></param> | ||
332 | /// <param name="transactionID">The transaction ID. If this is UUID.Zero we will | ||
333 | /// assume that we are not in a transaction</param> | ||
334 | /// <param name="itemID">The ID of the updated item</param> | ||
335 | /// <param name="name">The name of the updated item</param> | ||
336 | /// <param name="description">The description of the updated item</param> | ||
337 | /// <param name="nextOwnerMask">The permissions of the updated item</param> | ||
338 | /* public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID, | ||
339 | UUID itemID, string name, string description, | ||
340 | uint nextOwnerMask)*/ | ||
341 | public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID, | ||
342 | UUID itemID, InventoryItemBase itemUpd) | ||
343 | { | ||
344 | CachedUserInfo userInfo | ||
345 | = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
346 | |||
347 | if (userInfo != null && userInfo.RootFolder != null) | ||
348 | { | ||
349 | InventoryItemBase item = userInfo.RootFolder.FindItem(itemID); | ||
350 | |||
351 | if (item != null) | ||
352 | { | ||
353 | if (UUID.Zero == transactionID) | ||
354 | { | ||
355 | item.Name = itemUpd.Name; | ||
356 | item.Description = itemUpd.Description; | ||
357 | item.NextPermissions = itemUpd.NextPermissions; | ||
358 | item.CurrentPermissions |= 8; // Slam! | ||
359 | item.EveryOnePermissions = itemUpd.EveryOnePermissions; | ||
360 | item.GroupPermissions = itemUpd.GroupPermissions; | ||
361 | |||
362 | item.GroupID = itemUpd.GroupID; | ||
363 | item.GroupOwned = itemUpd.GroupOwned; | ||
364 | item.CreationDate = itemUpd.CreationDate; | ||
365 | // The client sends zero if its newly created? | ||
366 | |||
367 | if (itemUpd.CreationDate == 0) | ||
368 | item.CreationDate = Util.UnixTimeSinceEpoch(); | ||
369 | else | ||
370 | item.CreationDate = itemUpd.CreationDate; | ||
371 | |||
372 | // TODO: Check if folder changed and move item | ||
373 | //item.NextPermissions = itemUpd.Folder; | ||
374 | item.InvType = itemUpd.InvType; | ||
375 | item.SalePrice = itemUpd.SalePrice; | ||
376 | item.SaleType = itemUpd.SaleType; | ||
377 | item.Flags = itemUpd.Flags; | ||
378 | |||
379 | userInfo.UpdateItem(item); | ||
380 | } | ||
381 | else | ||
382 | { | ||
383 | IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); | ||
384 | if (agentTransactions != null) | ||
385 | { | ||
386 | agentTransactions.HandleItemUpdateFromTransaction( | ||
387 | remoteClient, transactionID, item); | ||
388 | } | ||
389 | } | ||
390 | } | ||
391 | else | ||
392 | { | ||
393 | m_log.Error( | ||
394 | "[AGENTINVENTORY]: Item ID " + itemID + " not found for an inventory item update."); | ||
395 | } | ||
396 | } | ||
397 | else | ||
398 | { | ||
399 | m_log.Error( | ||
400 | "[AGENT INVENTORY]: Agent ID " + remoteClient.AgentId + " not found for an inventory item update."); | ||
401 | } | ||
402 | } | ||
403 | |||
404 | /// <summary> | ||
405 | /// Give an inventory item from one user to another | ||
406 | /// </summary> | ||
407 | /// <param name="recipientClient"></param> | ||
408 | /// <param name="senderId">ID of the sender of the item</param> | ||
409 | /// <param name="itemId"></param> | ||
410 | public virtual void GiveInventoryItem(IClientAPI recipientClient, UUID senderId, UUID itemId) | ||
411 | { | ||
412 | InventoryItemBase itemCopy = GiveInventoryItem(recipientClient.AgentId, senderId, itemId); | ||
413 | |||
414 | if (itemCopy != null) | ||
415 | recipientClient.SendBulkUpdateInventory(itemCopy); | ||
416 | } | ||
417 | |||
418 | /// <summary> | ||
419 | /// Give an inventory item from one user to another | ||
420 | /// </summary> | ||
421 | /// <param name="recipient"></param> | ||
422 | /// <param name="senderId">ID of the sender of the item</param> | ||
423 | /// <param name="itemId"></param> | ||
424 | /// <returns>The inventory item copy given, null if the give was unsuccessful</returns> | ||
425 | public virtual InventoryItemBase GiveInventoryItem(UUID recipient, UUID senderId, UUID itemId) | ||
426 | { | ||
427 | return GiveInventoryItem(recipient, senderId, itemId, UUID.Zero); | ||
428 | } | ||
429 | |||
430 | /// <summary> | ||
431 | /// Give an inventory item from one user to another | ||
432 | /// </summary> | ||
433 | /// <param name="recipient"></param> | ||
434 | /// <param name="senderId">ID of the sender of the item</param> | ||
435 | /// <param name="itemId"></param> | ||
436 | /// <param name="recipientFolderId"> | ||
437 | /// The id of the folder in which the copy item should go. If UUID.Zero then the item is placed in the most | ||
438 | /// appropriate default folder. | ||
439 | /// </param> | ||
440 | /// <returns> | ||
441 | /// The inventory item copy given, null if the give was unsuccessful | ||
442 | /// </returns> | ||
443 | public virtual InventoryItemBase GiveInventoryItem( | ||
444 | UUID recipient, UUID senderId, UUID itemId, UUID recipientFolderId) | ||
445 | { | ||
446 | // Retrieve the item from the sender | ||
447 | CachedUserInfo senderUserInfo = CommsManager.UserProfileCacheService.GetUserDetails(senderId); | ||
448 | |||
449 | if (senderUserInfo == null) | ||
450 | { | ||
451 | m_log.ErrorFormat( | ||
452 | "[AGENT INVENTORY]: Failed to find sending user {0} for item {1}", senderId, itemId); | ||
453 | |||
454 | return null; | ||
455 | } | ||
456 | |||
457 | if (senderUserInfo.RootFolder != null) | ||
458 | { | ||
459 | InventoryItemBase item = senderUserInfo.RootFolder.FindItem(itemId); | ||
460 | |||
461 | if (item != null) | ||
462 | { | ||
463 | if (!Permissions.BypassPermissions()) | ||
464 | { | ||
465 | if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) | ||
466 | return null; | ||
467 | } | ||
468 | |||
469 | CachedUserInfo recipientUserInfo | ||
470 | = CommsManager.UserProfileCacheService.GetUserDetails(recipient); | ||
471 | |||
472 | if (recipientUserInfo != null) | ||
473 | { | ||
474 | if (!recipientUserInfo.HasReceivedInventory) | ||
475 | CommsManager.UserProfileCacheService.RequestInventoryForUser(recipient); | ||
476 | |||
477 | // Insert a copy of the item into the recipient | ||
478 | InventoryItemBase itemCopy = new InventoryItemBase(); | ||
479 | itemCopy.Owner = recipient; | ||
480 | itemCopy.Creator = item.Creator; | ||
481 | itemCopy.ID = UUID.Random(); | ||
482 | itemCopy.AssetID = item.AssetID; | ||
483 | itemCopy.Description = item.Description; | ||
484 | itemCopy.Name = item.Name; | ||
485 | itemCopy.AssetType = item.AssetType; | ||
486 | itemCopy.InvType = item.InvType; | ||
487 | itemCopy.Folder = recipientFolderId; | ||
488 | |||
489 | if (Permissions.PropagatePermissions()) | ||
490 | { | ||
491 | if (item.InvType == 6) | ||
492 | { | ||
493 | itemCopy.BasePermissions &= ~(uint)(PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); | ||
494 | itemCopy.BasePermissions |= (item.CurrentPermissions & 7) << 13; | ||
495 | } | ||
496 | else | ||
497 | { | ||
498 | itemCopy.BasePermissions = item.BasePermissions & item.NextPermissions; | ||
499 | } | ||
500 | |||
501 | itemCopy.CurrentPermissions = itemCopy.BasePermissions; | ||
502 | if ((item.CurrentPermissions & 8) != 0) // Propagate slam bit | ||
503 | { | ||
504 | itemCopy.BasePermissions &= item.NextPermissions; | ||
505 | itemCopy.CurrentPermissions = itemCopy.BasePermissions; | ||
506 | itemCopy.CurrentPermissions |= 8; | ||
507 | } | ||
508 | |||
509 | itemCopy.NextPermissions = item.NextPermissions; | ||
510 | itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions; | ||
511 | itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions; | ||
512 | } | ||
513 | else | ||
514 | { | ||
515 | itemCopy.CurrentPermissions = item.CurrentPermissions; | ||
516 | itemCopy.NextPermissions = item.NextPermissions; | ||
517 | itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions; | ||
518 | itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions; | ||
519 | itemCopy.BasePermissions = item.BasePermissions; | ||
520 | } | ||
521 | itemCopy.GroupID = UUID.Zero; | ||
522 | itemCopy.GroupOwned = false; | ||
523 | itemCopy.Flags = item.Flags; | ||
524 | itemCopy.SalePrice = item.SalePrice; | ||
525 | itemCopy.SaleType = item.SaleType; | ||
526 | |||
527 | itemCopy.CreationDate = item.CreationDate; | ||
528 | |||
529 | recipientUserInfo.AddItem(itemCopy); | ||
530 | |||
531 | if (!Permissions.BypassPermissions()) | ||
532 | { | ||
533 | if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) | ||
534 | senderUserInfo.DeleteItem(itemId); | ||
535 | } | ||
536 | |||
537 | return itemCopy; | ||
538 | } | ||
539 | else | ||
540 | { | ||
541 | m_log.ErrorFormat( | ||
542 | "[AGENT INVENTORY]: Could not find userinfo for recipient user {0} of item {1}, {2} from {3}", | ||
543 | recipient, item.Name, | ||
544 | item.ID, senderId); | ||
545 | } | ||
546 | } | ||
547 | else | ||
548 | { | ||
549 | m_log.ErrorFormat( | ||
550 | "[AGENT INVENTORY]: Failed to find item {0} to give to {1}", itemId, senderId); | ||
551 | |||
552 | return null; | ||
553 | } | ||
554 | } | ||
555 | else | ||
556 | { | ||
557 | m_log.Error("[AGENT INVENTORY]: Failed to find item " + itemId.ToString() + ", no root folder"); | ||
558 | return null; | ||
559 | } | ||
560 | |||
561 | return null; | ||
562 | } | ||
563 | |||
564 | /// <summary> | ||
565 | /// Give an entire inventory folder from one user to another. The entire contents (including all descendent | ||
566 | /// folders) is given. | ||
567 | /// </summary> | ||
568 | /// <param name="recipientId"></param> | ||
569 | /// <param name="senderId">ID of the sender of the item</param> | ||
570 | /// <param name="folderId"></param> | ||
571 | /// <param name="recipientParentFolderId"> | ||
572 | /// The id of the receipient folder in which the send folder should be placed. If UUID.Zero then the | ||
573 | /// recipient folder is the root folder | ||
574 | /// </param> | ||
575 | /// <returns> | ||
576 | /// The inventory folder copy given, null if the copy was unsuccessful | ||
577 | /// </returns> | ||
578 | public virtual InventoryFolderImpl GiveInventoryFolder( | ||
579 | UUID recipientId, UUID senderId, UUID folderId, UUID recipientParentFolderId) | ||
580 | { | ||
581 | // Retrieve the folder from the sender | ||
582 | CachedUserInfo senderUserInfo = CommsManager.UserProfileCacheService.GetUserDetails(senderId); | ||
583 | |||
584 | if (null == senderUserInfo) | ||
585 | { | ||
586 | m_log.ErrorFormat( | ||
587 | "[AGENT INVENTORY]: Failed to find sending user {0} for folder {1}", senderId, folderId); | ||
588 | |||
589 | return null; | ||
590 | } | ||
591 | |||
592 | if (!senderUserInfo.HasReceivedInventory) | ||
593 | { | ||
594 | m_log.DebugFormat( | ||
595 | "[AGENT INVENTORY]: Could not give inventory folder - have not yet received inventory for {0}", | ||
596 | senderId); | ||
597 | |||
598 | return null; | ||
599 | } | ||
600 | |||
601 | InventoryFolderImpl folder = senderUserInfo.RootFolder.FindFolder(folderId); | ||
602 | |||
603 | if (null == folder) | ||
604 | { | ||
605 | m_log.ErrorFormat( | ||
606 | "[AGENT INVENTORY]: Could not find inventory folder {0} to give", folderId); | ||
607 | |||
608 | return null; | ||
609 | } | ||
610 | |||
611 | CachedUserInfo recipientUserInfo | ||
612 | = CommsManager.UserProfileCacheService.GetUserDetails(recipientId); | ||
613 | |||
614 | if (null == recipientUserInfo) | ||
615 | { | ||
616 | m_log.ErrorFormat( | ||
617 | "[AGENT INVENTORY]: Failed to find receiving user {0} for folder {1}", recipientId, folderId); | ||
618 | |||
619 | return null; | ||
620 | } | ||
621 | |||
622 | if (recipientParentFolderId == UUID.Zero) | ||
623 | recipientParentFolderId = recipientUserInfo.RootFolder.ID; | ||
624 | |||
625 | UUID newFolderId = UUID.Random(); | ||
626 | recipientUserInfo.CreateFolder(folder.Name, newFolderId, (ushort)folder.Type, recipientParentFolderId); | ||
627 | |||
628 | // XXX: Messy - we should really get this back in the CreateFolder call | ||
629 | InventoryFolderImpl copiedFolder = recipientUserInfo.RootFolder.FindFolder(newFolderId); | ||
630 | |||
631 | // Give all the subfolders | ||
632 | List<InventoryFolderImpl> subFolders = folder.RequestListOfFolderImpls(); | ||
633 | foreach (InventoryFolderImpl childFolder in subFolders) | ||
634 | { | ||
635 | GiveInventoryFolder(recipientId, senderId, childFolder.ID, copiedFolder.ID); | ||
636 | } | ||
637 | |||
638 | // Give all the items | ||
639 | List<InventoryItemBase> items = folder.RequestListOfItems(); | ||
640 | foreach (InventoryItemBase item in items) | ||
641 | { | ||
642 | GiveInventoryItem(recipientId, senderId, item.ID, copiedFolder.ID); | ||
643 | } | ||
644 | |||
645 | return copiedFolder; | ||
646 | } | ||
647 | |||
648 | public void CopyInventoryItem(IClientAPI remoteClient, uint callbackID, UUID oldAgentID, UUID oldItemID, | ||
649 | UUID newFolderID, string newName) | ||
650 | { | ||
651 | m_log.DebugFormat( | ||
652 | "[AGENT INVENTORY]: CopyInventoryItem received by {0} with oldAgentID {1}, oldItemID {2}, new FolderID {3}, newName {4}", | ||
653 | remoteClient.AgentId, oldAgentID, oldItemID, newFolderID, newName); | ||
654 | |||
655 | InventoryItemBase item = CommsManager.UserProfileCacheService.LibraryRoot.FindItem(oldItemID); | ||
656 | |||
657 | if (item == null) | ||
658 | { | ||
659 | CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(oldAgentID); | ||
660 | if (userInfo == null) | ||
661 | { | ||
662 | m_log.Error("[AGENT INVENTORY]: Failed to find user " + oldAgentID.ToString()); | ||
663 | return; | ||
664 | } | ||
665 | |||
666 | if (userInfo.RootFolder != null) | ||
667 | { | ||
668 | item = userInfo.RootFolder.FindItem(oldItemID); | ||
669 | |||
670 | if (item == null) | ||
671 | { | ||
672 | m_log.Error("[AGENT INVENTORY]: Failed to find item " + oldItemID.ToString()); | ||
673 | return; | ||
674 | } | ||
675 | } | ||
676 | else | ||
677 | { | ||
678 | m_log.Error("[AGENT INVENTORY]: Failed to find item " + oldItemID.ToString()); | ||
679 | return; | ||
680 | } | ||
681 | } | ||
682 | |||
683 | AssetBase asset | ||
684 | = AssetCache.GetAsset( | ||
685 | item.AssetID, (item.AssetType == (int)AssetType.Texture ? true : false)); | ||
686 | |||
687 | if (asset != null) | ||
688 | { | ||
689 | if (newName != String.Empty) | ||
690 | { | ||
691 | asset.Metadata.Name = newName; | ||
692 | } | ||
693 | else | ||
694 | { | ||
695 | newName = item.Name; | ||
696 | } | ||
697 | |||
698 | if (remoteClient.AgentId == oldAgentID) | ||
699 | { | ||
700 | CreateNewInventoryItem( | ||
701 | remoteClient, newFolderID, newName, item.Flags, callbackID, asset, (sbyte)item.InvType, | ||
702 | item.BasePermissions, item.CurrentPermissions, item.EveryOnePermissions, item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch()); | ||
703 | } | ||
704 | else | ||
705 | { | ||
706 | CreateNewInventoryItem( | ||
707 | remoteClient, newFolderID, newName, item.Flags, callbackID, asset, (sbyte)item.InvType, | ||
708 | item.NextPermissions, item.NextPermissions, item.EveryOnePermissions & item.NextPermissions, item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch()); | ||
709 | } | ||
710 | } | ||
711 | else | ||
712 | { | ||
713 | m_log.ErrorFormat( | ||
714 | "[AGENT INVENTORY]: Could not copy item {0} since asset {1} could not be found", | ||
715 | item.Name, item.AssetID); | ||
716 | } | ||
717 | } | ||
718 | |||
719 | /// <summary> | ||
720 | /// Create a new asset data structure. | ||
721 | /// </summary> | ||
722 | /// <param name="name"></param> | ||
723 | /// <param name="description"></param> | ||
724 | /// <param name="invType"></param> | ||
725 | /// <param name="assetType"></param> | ||
726 | /// <param name="data"></param> | ||
727 | /// <returns></returns> | ||
728 | private AssetBase CreateAsset(string name, string description, sbyte assetType, byte[] data) | ||
729 | { | ||
730 | AssetBase asset = new AssetBase(); | ||
731 | asset.Metadata.Name = name; | ||
732 | asset.Metadata.Description = description; | ||
733 | asset.Metadata.Type = assetType; | ||
734 | asset.Metadata.FullID = UUID.Random(); | ||
735 | asset.Data = (data == null) ? new byte[1] : data; | ||
736 | |||
737 | return asset; | ||
738 | } | ||
739 | |||
740 | /// <summary> | ||
741 | /// Move an item within the agent's inventory. | ||
742 | /// </summary> | ||
743 | /// <param name="remoteClient"></param> | ||
744 | /// <param name="folderID"></param> | ||
745 | /// <param name="itemID"></param> | ||
746 | /// <param name="length"></param> | ||
747 | /// <param name="newName"></param> | ||
748 | public void MoveInventoryItem(IClientAPI remoteClient, UUID folderID, UUID itemID, int length, | ||
749 | string newName) | ||
750 | { | ||
751 | m_log.DebugFormat( | ||
752 | "[AGENT INVENTORY]: Moving item {0} to {1} for {2}", itemID, folderID, remoteClient.AgentId); | ||
753 | |||
754 | CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
755 | |||
756 | if (userInfo == null) | ||
757 | { | ||
758 | m_log.Error("[AGENT INVENTORY]: Failed to find user " + remoteClient.AgentId.ToString()); | ||
759 | |||
760 | return; | ||
761 | } | ||
762 | |||
763 | if (userInfo.RootFolder != null) | ||
764 | { | ||
765 | InventoryItemBase item = userInfo.RootFolder.FindItem(itemID); | ||
766 | |||
767 | if (item != null) | ||
768 | { | ||
769 | if (newName != String.Empty) | ||
770 | { | ||
771 | item.Name = newName; | ||
772 | } | ||
773 | item.Folder = folderID; | ||
774 | |||
775 | userInfo.DeleteItem(item.ID); | ||
776 | |||
777 | AddInventoryItem(remoteClient, item); | ||
778 | } | ||
779 | else | ||
780 | { | ||
781 | m_log.Error("[AGENT INVENTORY]: Failed to find item " + itemID.ToString()); | ||
782 | |||
783 | return; | ||
784 | } | ||
785 | } | ||
786 | else | ||
787 | { | ||
788 | m_log.Error("[AGENT INVENTORY]: Failed to find item " + itemID.ToString() + ", no root folder"); | ||
789 | |||
790 | return; | ||
791 | } | ||
792 | } | ||
793 | |||
794 | /// <summary> | ||
795 | /// Create a new inventory item. | ||
796 | /// </summary> | ||
797 | /// <param name="remoteClient"></param> | ||
798 | /// <param name="folderID"></param> | ||
799 | /// <param name="callbackID"></param> | ||
800 | /// <param name="asset"></param> | ||
801 | /// <param name="invType"></param> | ||
802 | /// <param name="nextOwnerMask"></param> | ||
803 | private void CreateNewInventoryItem(IClientAPI remoteClient, UUID folderID, string name, uint flags, uint callbackID, | ||
804 | AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate) | ||
805 | { | ||
806 | CreateNewInventoryItem( | ||
807 | remoteClient, folderID, name, flags, callbackID, asset, invType, | ||
808 | (uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate); | ||
809 | } | ||
810 | |||
811 | /// <summary> | ||
812 | /// Create a new Inventory Item | ||
813 | /// </summary> | ||
814 | /// <param name="remoteClient"></param> | ||
815 | /// <param name="folderID"></param> | ||
816 | /// <param name="callbackID"></param> | ||
817 | /// <param name="asset"></param> | ||
818 | /// <param name="invType"></param> | ||
819 | /// <param name="nextOwnerMask"></param> | ||
820 | /// <param name="creationDate"></param> | ||
821 | private void CreateNewInventoryItem( | ||
822 | IClientAPI remoteClient, UUID folderID, string name, uint flags, uint callbackID, AssetBase asset, sbyte invType, | ||
823 | uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate) | ||
824 | { | ||
825 | CachedUserInfo userInfo | ||
826 | = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
827 | |||
828 | if (userInfo != null) | ||
829 | { | ||
830 | InventoryItemBase item = new InventoryItemBase(); | ||
831 | item.Owner = remoteClient.AgentId; | ||
832 | item.Creator = remoteClient.AgentId; | ||
833 | item.ID = UUID.Random(); | ||
834 | item.AssetID = asset.Metadata.FullID; | ||
835 | item.Description = asset.Metadata.Description; | ||
836 | item.Name = name; | ||
837 | item.Flags = flags; | ||
838 | item.AssetType = asset.Metadata.Type; | ||
839 | item.InvType = invType; | ||
840 | item.Folder = folderID; | ||
841 | item.CurrentPermissions = currentMask; | ||
842 | item.NextPermissions = nextOwnerMask; | ||
843 | item.EveryOnePermissions = everyoneMask; | ||
844 | item.GroupPermissions = groupMask; | ||
845 | item.BasePermissions = baseMask; | ||
846 | item.CreationDate = creationDate; | ||
847 | |||
848 | userInfo.AddItem(item); | ||
849 | remoteClient.SendInventoryItemCreateUpdate(item); | ||
850 | } | ||
851 | else | ||
852 | { | ||
853 | m_log.WarnFormat( | ||
854 | "No user details associated with client {0} uuid {1} in CreateNewInventoryItem!", | ||
855 | remoteClient.Name, remoteClient.AgentId); | ||
856 | } | ||
857 | } | ||
858 | |||
859 | /// <summary> | ||
860 | /// Create a new inventory item. Called when the client creates a new item directly within their | ||
861 | /// inventory (e.g. by selecting a context inventory menu option). | ||
862 | /// </summary> | ||
863 | /// <param name="remoteClient"></param> | ||
864 | /// <param name="transactionID"></param> | ||
865 | /// <param name="folderID"></param> | ||
866 | /// <param name="callbackID"></param> | ||
867 | /// <param name="description"></param> | ||
868 | /// <param name="name"></param> | ||
869 | /// <param name="invType"></param> | ||
870 | /// <param name="type"></param> | ||
871 | /// <param name="wearableType"></param> | ||
872 | /// <param name="nextOwnerMask"></param> | ||
873 | public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID, | ||
874 | uint callbackID, string description, string name, sbyte invType, | ||
875 | sbyte assetType, | ||
876 | byte wearableType, uint nextOwnerMask, int creationDate) | ||
877 | { | ||
878 | m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item {0} in folder {1}", name, folderID); | ||
879 | |||
880 | if (!Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) | ||
881 | return; | ||
882 | |||
883 | if (transactionID == UUID.Zero) | ||
884 | { | ||
885 | CachedUserInfo userInfo | ||
886 | = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
887 | |||
888 | if (userInfo != null) | ||
889 | { | ||
890 | ScenePresence presence; | ||
891 | TryGetAvatar(remoteClient.AgentId, out presence); | ||
892 | byte[] data = null; | ||
893 | |||
894 | if (invType == 3 && presence != null) // OpenMetaverse.asset.assettype.landmark = 3 - needs to be turned into an enum | ||
895 | { | ||
896 | Vector3 pos = presence.AbsolutePosition; | ||
897 | string strdata = String.Format( | ||
898 | "Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\n", | ||
899 | presence.Scene.RegionInfo.RegionID, | ||
900 | pos.X, pos.Y, pos.Z, | ||
901 | presence.RegionHandle); | ||
902 | data = Encoding.ASCII.GetBytes(strdata); | ||
903 | } | ||
904 | |||
905 | AssetBase asset = CreateAsset(name, description, assetType, data); | ||
906 | AssetCache.AddAsset(asset); | ||
907 | |||
908 | CreateNewInventoryItem(remoteClient, folderID, asset.Metadata.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate); | ||
909 | } | ||
910 | else | ||
911 | { | ||
912 | m_log.ErrorFormat( | ||
913 | "userInfo for agent uuid {0} unexpectedly null in CreateNewInventoryItem", | ||
914 | remoteClient.AgentId); | ||
915 | } | ||
916 | } | ||
917 | else | ||
918 | { | ||
919 | IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); | ||
920 | if (agentTransactions != null) | ||
921 | { | ||
922 | agentTransactions.HandleItemCreationFromTransaction( | ||
923 | remoteClient, transactionID, folderID, callbackID, description, | ||
924 | name, invType, assetType, wearableType, nextOwnerMask); | ||
925 | } | ||
926 | } | ||
927 | } | ||
928 | |||
929 | /// <summary> | ||
930 | /// Remove an inventory item for the client's inventory | ||
931 | /// </summary> | ||
932 | /// <param name="remoteClient"></param> | ||
933 | /// <param name="itemID"></param> | ||
934 | private void RemoveInventoryItem(IClientAPI remoteClient, UUID itemID) | ||
935 | { | ||
936 | CachedUserInfo userInfo | ||
937 | = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
938 | |||
939 | if (userInfo == null) | ||
940 | { | ||
941 | m_log.WarnFormat( | ||
942 | "[AGENT INVENTORY]: Failed to find user {0} {1} to delete inventory item {2}", | ||
943 | remoteClient.Name, remoteClient.AgentId, itemID); | ||
944 | |||
945 | return; | ||
946 | } | ||
947 | |||
948 | userInfo.DeleteItem(itemID); | ||
949 | } | ||
950 | |||
951 | /// <summary> | ||
952 | /// Removes an inventory folder. Although there is a packet in the Linden protocol for this, it may be | ||
953 | /// legacy and not currently used (purge folder is used to remove folders from trash instead). | ||
954 | /// </summary> | ||
955 | /// <param name="remoteClient"></param> | ||
956 | /// <param name="folderID"></param> | ||
957 | private void RemoveInventoryFolder(IClientAPI remoteClient, UUID folderID) | ||
958 | { | ||
959 | CachedUserInfo userInfo | ||
960 | = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
961 | |||
962 | if (userInfo == null) | ||
963 | { | ||
964 | m_log.Warn("[AGENT INVENTORY]: Failed to find user " + remoteClient.AgentId.ToString()); | ||
965 | return; | ||
966 | } | ||
967 | |||
968 | if (userInfo.RootFolder != null) | ||
969 | { | ||
970 | InventoryItemBase folder = userInfo.RootFolder.FindItem(folderID); | ||
971 | |||
972 | if (folder != null) | ||
973 | { | ||
974 | m_log.WarnFormat( | ||
975 | "[AGENT INVENTORY]: Remove folder not implemented in request by {0} {1} for {2}", | ||
976 | remoteClient.Name, remoteClient.AgentId, folderID); | ||
977 | |||
978 | // doesn't work just yet, commented out. will fix in next patch. | ||
979 | // userInfo.DeleteItem(folder); | ||
980 | } | ||
981 | } | ||
982 | } | ||
983 | |||
984 | private SceneObjectGroup GetGroupByPrim(uint localID) | ||
985 | { | ||
986 | List<EntityBase> EntityList = GetEntities(); | ||
987 | |||
988 | foreach (EntityBase ent in EntityList) | ||
989 | { | ||
990 | if (ent is SceneObjectGroup) | ||
991 | { | ||
992 | if (((SceneObjectGroup) ent).HasChildPrim(localID)) | ||
993 | return (SceneObjectGroup) ent; | ||
994 | } | ||
995 | } | ||
996 | return null; | ||
997 | } | ||
998 | |||
999 | /// <summary> | ||
1000 | /// Send the details of a prim's inventory to the client. | ||
1001 | /// </summary> | ||
1002 | /// <param name="remoteClient"></param> | ||
1003 | /// <param name="primLocalID"></param> | ||
1004 | public void RequestTaskInventory(IClientAPI remoteClient, uint primLocalID) | ||
1005 | { | ||
1006 | SceneObjectGroup group = GetGroupByPrim(primLocalID); | ||
1007 | if (group != null) | ||
1008 | { | ||
1009 | bool fileChange = group.GetPartInventoryFileName(remoteClient, primLocalID); | ||
1010 | if (fileChange) | ||
1011 | { | ||
1012 | if (XferManager != null) | ||
1013 | { | ||
1014 | group.RequestInventoryFile(remoteClient, primLocalID, XferManager); | ||
1015 | } | ||
1016 | } | ||
1017 | } | ||
1018 | else | ||
1019 | { | ||
1020 | m_log.ErrorFormat( | ||
1021 | "[PRIM INVENTORY]: Inventory requested of prim {0} which doesn't exist", primLocalID); | ||
1022 | } | ||
1023 | } | ||
1024 | |||
1025 | /// <summary> | ||
1026 | /// Remove an item from a prim (task) inventory | ||
1027 | /// </summary> | ||
1028 | /// <param name="remoteClient">Unused at the moment but retained since the avatar ID might | ||
1029 | /// be necessary for a permissions check at some stage.</param> | ||
1030 | /// <param name="itemID"></param> | ||
1031 | /// <param name="localID"></param> | ||
1032 | public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) | ||
1033 | { | ||
1034 | SceneObjectPart part = GetSceneObjectPart(localID); | ||
1035 | SceneObjectGroup group = part.ParentGroup; | ||
1036 | if (group != null) | ||
1037 | { | ||
1038 | TaskInventoryItem item = group.GetInventoryItem(localID, itemID); | ||
1039 | if (item == null) | ||
1040 | return; | ||
1041 | |||
1042 | if (item.Type == 10) | ||
1043 | { | ||
1044 | EventManager.TriggerRemoveScript(localID, itemID); | ||
1045 | } | ||
1046 | group.RemoveInventoryItem(localID, itemID); | ||
1047 | part.GetProperties(remoteClient); | ||
1048 | } | ||
1049 | else | ||
1050 | { | ||
1051 | m_log.ErrorFormat( | ||
1052 | "[PRIM INVENTORY]: " + | ||
1053 | "Removal of item {0} requested of prim {1} but this prim does not exist", | ||
1054 | itemID, | ||
1055 | localID); | ||
1056 | } | ||
1057 | } | ||
1058 | |||
1059 | private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId) | ||
1060 | { | ||
1061 | TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(itemId); | ||
1062 | |||
1063 | if (null == taskItem) | ||
1064 | { | ||
1065 | m_log.ErrorFormat( | ||
1066 | "[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for creating an avatar" | ||
1067 | + " inventory item from a prim's inventory item " | ||
1068 | + " but the required item does not exist in the prim's inventory", | ||
1069 | itemId, part.Name, part.UUID); | ||
1070 | |||
1071 | return null; | ||
1072 | } | ||
1073 | |||
1074 | if ((destAgent != taskItem.OwnerID) && ((taskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) | ||
1075 | { | ||
1076 | return null; | ||
1077 | } | ||
1078 | |||
1079 | InventoryItemBase agentItem = new InventoryItemBase(); | ||
1080 | |||
1081 | agentItem.ID = UUID.Random(); | ||
1082 | agentItem.Creator = taskItem.CreatorID; | ||
1083 | agentItem.Owner = destAgent; | ||
1084 | agentItem.AssetID = taskItem.AssetID; | ||
1085 | agentItem.Description = taskItem.Description; | ||
1086 | agentItem.Name = taskItem.Name; | ||
1087 | agentItem.AssetType = taskItem.Type; | ||
1088 | agentItem.InvType = taskItem.InvType; | ||
1089 | agentItem.Flags = taskItem.Flags; | ||
1090 | |||
1091 | if ((part.OwnerID != destAgent) && Permissions.PropagatePermissions()) | ||
1092 | { | ||
1093 | if (taskItem.InvType == 6) | ||
1094 | agentItem.BasePermissions = taskItem.BasePermissions & ((taskItem.CurrentPermissions & 7) << 13); | ||
1095 | else | ||
1096 | agentItem.BasePermissions = taskItem.BasePermissions; | ||
1097 | agentItem.BasePermissions &= taskItem.NextPermissions; | ||
1098 | agentItem.CurrentPermissions = agentItem.BasePermissions | 8; | ||
1099 | agentItem.NextPermissions = taskItem.NextPermissions; | ||
1100 | agentItem.EveryOnePermissions = taskItem.EveryonePermissions & taskItem.NextPermissions; | ||
1101 | agentItem.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions; | ||
1102 | } | ||
1103 | else | ||
1104 | { | ||
1105 | agentItem.BasePermissions = taskItem.BasePermissions; | ||
1106 | agentItem.CurrentPermissions = taskItem.CurrentPermissions; | ||
1107 | agentItem.NextPermissions = taskItem.NextPermissions; | ||
1108 | agentItem.EveryOnePermissions = taskItem.EveryonePermissions; | ||
1109 | agentItem.GroupPermissions = taskItem.GroupPermissions; | ||
1110 | } | ||
1111 | |||
1112 | if (!Permissions.BypassPermissions()) | ||
1113 | { | ||
1114 | if ((taskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0) | ||
1115 | part.Inventory.RemoveInventoryItem(itemId); | ||
1116 | } | ||
1117 | |||
1118 | return agentItem; | ||
1119 | } | ||
1120 | |||
1121 | /// <summary> | ||
1122 | /// Move the given item in the given prim to a folder in the client's inventory | ||
1123 | /// </summary> | ||
1124 | /// <param name="remoteClient"></param> | ||
1125 | /// <param name="folderID"></param> | ||
1126 | /// <param name="part"></param> | ||
1127 | /// <param name="itemID"></param> | ||
1128 | public InventoryItemBase MoveTaskInventoryItem(IClientAPI remoteClient, UUID folderId, SceneObjectPart part, UUID itemId) | ||
1129 | { | ||
1130 | InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(remoteClient.AgentId, part, itemId); | ||
1131 | |||
1132 | if (agentItem == null) | ||
1133 | return null; | ||
1134 | |||
1135 | agentItem.Folder = folderId; | ||
1136 | AddInventoryItem(remoteClient, agentItem); | ||
1137 | return agentItem; | ||
1138 | } | ||
1139 | |||
1140 | /// <summary> | ||
1141 | /// <see>ClientMoveTaskInventoryItem</see> | ||
1142 | /// </summary> | ||
1143 | /// <param name="remoteClient"></param> | ||
1144 | /// <param name="folderID"></param> | ||
1145 | /// <param name="primLocalID"></param> | ||
1146 | /// <param name="itemID"></param> | ||
1147 | public void ClientMoveTaskInventoryItem(IClientAPI remoteClient, UUID folderId, uint primLocalId, UUID itemId) | ||
1148 | { | ||
1149 | SceneObjectPart part = GetSceneObjectPart(primLocalId); | ||
1150 | |||
1151 | if (null == part) | ||
1152 | { | ||
1153 | m_log.WarnFormat( | ||
1154 | "[PRIM INVENTORY]: " + | ||
1155 | "Move of inventory item {0} from prim with local id {1} failed because the prim could not be found", | ||
1156 | itemId, primLocalId); | ||
1157 | |||
1158 | return; | ||
1159 | } | ||
1160 | |||
1161 | TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(itemId); | ||
1162 | |||
1163 | if (null == taskItem) | ||
1164 | { | ||
1165 | m_log.WarnFormat("[PRIM INVENTORY]: Move of inventory item {0} from prim with local id {1} failed" | ||
1166 | + " because the inventory item could not be found", | ||
1167 | itemId, primLocalId); | ||
1168 | |||
1169 | return; | ||
1170 | } | ||
1171 | |||
1172 | // Only owner can copy | ||
1173 | if (remoteClient.AgentId != taskItem.OwnerID) | ||
1174 | return; | ||
1175 | |||
1176 | MoveTaskInventoryItem(remoteClient, folderId, part, itemId); | ||
1177 | } | ||
1178 | |||
1179 | /// <summary> | ||
1180 | /// <see>MoveTaskInventoryItem</see> | ||
1181 | /// </summary> | ||
1182 | /// <param name="remoteClient"></param> | ||
1183 | /// <param name="folderID"></param> | ||
1184 | /// <param name="part"></param> | ||
1185 | /// <param name="itemID"></param> | ||
1186 | public InventoryItemBase MoveTaskInventoryItem(UUID avatarId, UUID folderId, SceneObjectPart part, UUID itemId) | ||
1187 | { | ||
1188 | ScenePresence avatar; | ||
1189 | |||
1190 | if (TryGetAvatar(avatarId, out avatar)) | ||
1191 | { | ||
1192 | return MoveTaskInventoryItem(avatar.ControllingClient, folderId, part, itemId); | ||
1193 | } | ||
1194 | else | ||
1195 | { | ||
1196 | CachedUserInfo profile = CommsManager.UserProfileCacheService.GetUserDetails(avatarId); | ||
1197 | if (profile == null || profile.RootFolder == null) | ||
1198 | { | ||
1199 | m_log.ErrorFormat( | ||
1200 | "[PRIM INVENTORY]: " + | ||
1201 | "Avatar {0} cannot be found to add item", | ||
1202 | avatarId); | ||
1203 | } | ||
1204 | if (!profile.HasReceivedInventory) | ||
1205 | CommsManager.UserProfileCacheService.RequestInventoryForUser(avatarId); | ||
1206 | InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(avatarId, part, itemId); | ||
1207 | |||
1208 | if (agentItem == null) | ||
1209 | return null; | ||
1210 | |||
1211 | agentItem.Folder = folderId; | ||
1212 | |||
1213 | AddInventoryItem(avatarId, agentItem); | ||
1214 | |||
1215 | return agentItem; | ||
1216 | } | ||
1217 | } | ||
1218 | |||
1219 | /// <summary> | ||
1220 | /// Copy a task (prim) inventory item to another task (prim) | ||
1221 | /// </summary> | ||
1222 | /// <param name="destId"></param> | ||
1223 | /// <param name="part"></param> | ||
1224 | /// <param name="itemId"></param> | ||
1225 | public void MoveTaskInventoryItem(UUID destId, SceneObjectPart part, UUID itemId) | ||
1226 | { | ||
1227 | TaskInventoryItem srcTaskItem = part.Inventory.GetInventoryItem(itemId); | ||
1228 | |||
1229 | if (srcTaskItem == null) | ||
1230 | { | ||
1231 | m_log.ErrorFormat( | ||
1232 | "[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for moving" | ||
1233 | + " but the item does not exist in this inventory", | ||
1234 | itemId, part.Name, part.UUID); | ||
1235 | |||
1236 | return; | ||
1237 | } | ||
1238 | |||
1239 | SceneObjectPart destPart = GetSceneObjectPart(destId); | ||
1240 | |||
1241 | if (destPart == null) | ||
1242 | { | ||
1243 | m_log.ErrorFormat( | ||
1244 | "[PRIM INVENTORY]: " + | ||
1245 | "Could not find prim for ID {0}", | ||
1246 | destId); | ||
1247 | return; | ||
1248 | } | ||
1249 | |||
1250 | // Can't transfer this | ||
1251 | // | ||
1252 | if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) | ||
1253 | return; | ||
1254 | |||
1255 | if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) | ||
1256 | { | ||
1257 | // object cannot copy items to an object owned by a different owner | ||
1258 | // unless llAllowInventoryDrop has been called | ||
1259 | |||
1260 | return; | ||
1261 | } | ||
1262 | |||
1263 | // must have both move and modify permission to put an item in an object | ||
1264 | if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) | ||
1265 | { | ||
1266 | return; | ||
1267 | } | ||
1268 | |||
1269 | TaskInventoryItem destTaskItem = new TaskInventoryItem(); | ||
1270 | |||
1271 | destTaskItem.ItemID = UUID.Random(); | ||
1272 | destTaskItem.CreatorID = srcTaskItem.CreatorID; | ||
1273 | destTaskItem.AssetID = srcTaskItem.AssetID; | ||
1274 | destTaskItem.GroupID = destPart.GroupID; | ||
1275 | destTaskItem.OwnerID = destPart.OwnerID; | ||
1276 | destTaskItem.ParentID = destPart.UUID; | ||
1277 | destTaskItem.ParentPartID = destPart.UUID; | ||
1278 | |||
1279 | destTaskItem.BasePermissions = srcTaskItem.BasePermissions; | ||
1280 | destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions; | ||
1281 | destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions; | ||
1282 | destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions; | ||
1283 | destTaskItem.NextPermissions = srcTaskItem.NextPermissions; | ||
1284 | destTaskItem.Flags = srcTaskItem.Flags; | ||
1285 | |||
1286 | if (destPart.OwnerID != part.OwnerID) | ||
1287 | { | ||
1288 | if (Permissions.PropagatePermissions()) | ||
1289 | { | ||
1290 | destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions & | ||
1291 | srcTaskItem.NextPermissions; | ||
1292 | destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions & | ||
1293 | srcTaskItem.NextPermissions; | ||
1294 | destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions & | ||
1295 | srcTaskItem.NextPermissions; | ||
1296 | destTaskItem.BasePermissions = srcTaskItem.BasePermissions & | ||
1297 | srcTaskItem.NextPermissions; | ||
1298 | destTaskItem.CurrentPermissions |= 8; // Slam! | ||
1299 | } | ||
1300 | } | ||
1301 | |||
1302 | destTaskItem.Description = srcTaskItem.Description; | ||
1303 | destTaskItem.Name = srcTaskItem.Name; | ||
1304 | destTaskItem.InvType = srcTaskItem.InvType; | ||
1305 | destTaskItem.Type = srcTaskItem.Type; | ||
1306 | |||
1307 | destPart.Inventory.AddInventoryItem(destTaskItem, part.OwnerID != destPart.OwnerID); | ||
1308 | |||
1309 | if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0) | ||
1310 | part.Inventory.RemoveInventoryItem(itemId); | ||
1311 | |||
1312 | ScenePresence avatar; | ||
1313 | |||
1314 | if (TryGetAvatar(srcTaskItem.OwnerID, out avatar)) | ||
1315 | { | ||
1316 | destPart.GetProperties(avatar.ControllingClient); | ||
1317 | } | ||
1318 | } | ||
1319 | |||
1320 | public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) | ||
1321 | { | ||
1322 | CachedUserInfo profile = CommsManager.UserProfileCacheService.GetUserDetails(destID); | ||
1323 | if (profile == null || profile.RootFolder == null) | ||
1324 | { | ||
1325 | m_log.ErrorFormat( | ||
1326 | "[PRIM INVENTORY]: " + | ||
1327 | "Avatar {0} cannot be found to add items", | ||
1328 | destID); | ||
1329 | return UUID.Zero; | ||
1330 | } | ||
1331 | |||
1332 | UUID newFolderID = UUID.Random(); | ||
1333 | |||
1334 | profile.CreateFolder(category, newFolderID, 0xffff, profile.RootFolder.ID); | ||
1335 | |||
1336 | foreach (UUID itemID in items) | ||
1337 | { | ||
1338 | InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(destID, host, itemID); | ||
1339 | |||
1340 | if (agentItem != null) | ||
1341 | { | ||
1342 | agentItem.Folder = newFolderID; | ||
1343 | |||
1344 | AddInventoryItem(destID, agentItem); | ||
1345 | } | ||
1346 | } | ||
1347 | |||
1348 | ScenePresence avatar; | ||
1349 | |||
1350 | if (TryGetAvatar(destID, out avatar)) | ||
1351 | { | ||
1352 | profile.SendInventoryDecendents(avatar.ControllingClient, | ||
1353 | profile.RootFolder.ID, true, false); | ||
1354 | profile.SendInventoryDecendents(avatar.ControllingClient, | ||
1355 | newFolderID, false, true); | ||
1356 | } | ||
1357 | |||
1358 | return newFolderID; | ||
1359 | } | ||
1360 | |||
1361 | /// <summary> | ||
1362 | /// Update an item in a prim (task) inventory. | ||
1363 | /// This method does not handle scripts, <see>RezScript(IClientAPI, UUID, unit)</see> | ||
1364 | /// </summary> | ||
1365 | /// <param name="remoteClient"></param> | ||
1366 | /// <param name="transactionID"></param> | ||
1367 | /// <param name="itemInfo"></param> | ||
1368 | /// <param name="primLocalID"></param> | ||
1369 | public void UpdateTaskInventory(IClientAPI remoteClient, UUID transactionID, TaskInventoryItem itemInfo, | ||
1370 | uint primLocalID) | ||
1371 | { | ||
1372 | UUID itemID = itemInfo.ItemID; | ||
1373 | |||
1374 | // Find the prim we're dealing with | ||
1375 | SceneObjectPart part = GetSceneObjectPart(primLocalID); | ||
1376 | |||
1377 | if (part != null) | ||
1378 | { | ||
1379 | TaskInventoryItem currentItem = part.Inventory.GetInventoryItem(itemID); | ||
1380 | bool allowInventoryDrop = (part.GetEffectiveObjectFlags() | ||
1381 | & (uint)PrimFlags.AllowInventoryDrop) != 0; | ||
1382 | |||
1383 | // Explicity allow anyone to add to the inventory if the | ||
1384 | // AllowInventoryDrop flag has been set. Don't however let | ||
1385 | // them update an item unless they pass the external checks | ||
1386 | // | ||
1387 | if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId) | ||
1388 | && (currentItem != null || !allowInventoryDrop)) | ||
1389 | return; | ||
1390 | |||
1391 | if (currentItem == null) | ||
1392 | { | ||
1393 | UUID copyID = UUID.Random(); | ||
1394 | if (itemID != UUID.Zero) | ||
1395 | { | ||
1396 | CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
1397 | |||
1398 | if (userInfo != null && userInfo.RootFolder != null) | ||
1399 | { | ||
1400 | InventoryItemBase item = userInfo.RootFolder.FindItem(itemID); | ||
1401 | |||
1402 | // Try library | ||
1403 | // XXX clumsy, possibly should be one call | ||
1404 | if (null == item) | ||
1405 | { | ||
1406 | item = CommsManager.UserProfileCacheService.LibraryRoot.FindItem(itemID); | ||
1407 | } | ||
1408 | |||
1409 | if (item != null) | ||
1410 | { | ||
1411 | part.ParentGroup.AddInventoryItem(remoteClient, primLocalID, item, copyID); | ||
1412 | m_log.InfoFormat( | ||
1413 | "[PRIM INVENTORY]: Update with item {0} requested of prim {1} for {2}", | ||
1414 | item.Name, primLocalID, remoteClient.Name); | ||
1415 | part.GetProperties(remoteClient); | ||
1416 | if (!Permissions.BypassPermissions()) | ||
1417 | { | ||
1418 | if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) | ||
1419 | RemoveInventoryItem(remoteClient, itemID); | ||
1420 | } | ||
1421 | } | ||
1422 | else | ||
1423 | { | ||
1424 | m_log.ErrorFormat( | ||
1425 | "[PRIM INVENTORY]: Could not find inventory item {0} to update for {1}!", | ||
1426 | itemID, remoteClient.Name); | ||
1427 | } | ||
1428 | } | ||
1429 | } | ||
1430 | } | ||
1431 | else // Updating existing item with new perms etc | ||
1432 | { | ||
1433 | IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); | ||
1434 | if (agentTransactions != null) | ||
1435 | { | ||
1436 | agentTransactions.HandleTaskItemUpdateFromTransaction( | ||
1437 | remoteClient, part, transactionID, currentItem); | ||
1438 | } | ||
1439 | if (part.Inventory.UpdateInventoryItem(itemInfo)) | ||
1440 | part.GetProperties(remoteClient); | ||
1441 | } | ||
1442 | } | ||
1443 | else | ||
1444 | { | ||
1445 | m_log.WarnFormat( | ||
1446 | "[PRIM INVENTORY]: " + | ||
1447 | "Update with item {0} requested of prim {1} for {2} but this prim does not exist", | ||
1448 | itemID, primLocalID, remoteClient.Name); | ||
1449 | } | ||
1450 | } | ||
1451 | |||
1452 | /// <summary> | ||
1453 | /// Rez a script into a prim's inventory, either ex nihilo or from an existing avatar inventory | ||
1454 | /// </summary> | ||
1455 | /// <param name="remoteClient"></param> | ||
1456 | /// <param name="itemID"> </param> | ||
1457 | /// <param name="localID"></param> | ||
1458 | public void RezScript(IClientAPI remoteClient, InventoryItemBase itemBase, UUID transactionID, uint localID) | ||
1459 | { | ||
1460 | UUID itemID = itemBase.ID; | ||
1461 | UUID copyID = UUID.Random(); | ||
1462 | |||
1463 | if (itemID != UUID.Zero) // transferred from an avatar inventory to the prim's inventory | ||
1464 | { | ||
1465 | CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
1466 | |||
1467 | if (userInfo != null && userInfo.RootFolder != null) | ||
1468 | { | ||
1469 | InventoryItemBase item = userInfo.RootFolder.FindItem(itemID); | ||
1470 | |||
1471 | // Try library | ||
1472 | // XXX clumsy, possibly should be one call | ||
1473 | if (null == item) | ||
1474 | { | ||
1475 | item = CommsManager.UserProfileCacheService.LibraryRoot.FindItem(itemID); | ||
1476 | } | ||
1477 | |||
1478 | if (item != null) | ||
1479 | { | ||
1480 | SceneObjectPart part = GetSceneObjectPart(localID); | ||
1481 | if (part != null) | ||
1482 | { | ||
1483 | if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) | ||
1484 | return; | ||
1485 | |||
1486 | part.ParentGroup.AddInventoryItem(remoteClient, localID, item, copyID); | ||
1487 | // TODO: switch to posting on_rez here when scripts | ||
1488 | // have state in inventory | ||
1489 | part.Inventory.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0); | ||
1490 | |||
1491 | // m_log.InfoFormat("[PRIMINVENTORY]: " + | ||
1492 | // "Rezzed script {0} into prim local ID {1} for user {2}", | ||
1493 | // item.inventoryName, localID, remoteClient.Name); | ||
1494 | part.GetProperties(remoteClient); | ||
1495 | } | ||
1496 | else | ||
1497 | { | ||
1498 | m_log.ErrorFormat( | ||
1499 | "[PRIM INVENTORY]: " + | ||
1500 | "Could not rez script {0} into prim local ID {1} for user {2}" | ||
1501 | + " because the prim could not be found in the region!", | ||
1502 | item.Name, localID, remoteClient.Name); | ||
1503 | } | ||
1504 | } | ||
1505 | else | ||
1506 | { | ||
1507 | m_log.ErrorFormat( | ||
1508 | "[PRIM INVENTORY]: Could not find script inventory item {0} to rez for {1}!", | ||
1509 | itemID, remoteClient.Name); | ||
1510 | } | ||
1511 | } | ||
1512 | } | ||
1513 | else // script has been rezzed directly into a prim's inventory | ||
1514 | { | ||
1515 | SceneObjectPart part = GetSceneObjectPart(itemBase.Folder); | ||
1516 | if (part == null) | ||
1517 | return; | ||
1518 | |||
1519 | if (part.OwnerID != remoteClient.AgentId) | ||
1520 | return; | ||
1521 | |||
1522 | if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) | ||
1523 | return; | ||
1524 | |||
1525 | if (!Permissions.CanCreateObjectInventory( | ||
1526 | itemBase.InvType, part.UUID, remoteClient.AgentId)) | ||
1527 | return; | ||
1528 | |||
1529 | AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}")); | ||
1530 | AssetCache.AddAsset(asset); | ||
1531 | |||
1532 | TaskInventoryItem taskItem = new TaskInventoryItem(); | ||
1533 | |||
1534 | taskItem.ResetIDs(itemBase.Folder); | ||
1535 | taskItem.ParentID = itemBase.Folder; | ||
1536 | taskItem.CreationDate = (uint)itemBase.CreationDate; | ||
1537 | taskItem.Name = itemBase.Name; | ||
1538 | taskItem.Description = itemBase.Description; | ||
1539 | taskItem.Type = itemBase.AssetType; | ||
1540 | taskItem.InvType = itemBase.InvType; | ||
1541 | taskItem.OwnerID = itemBase.Owner; | ||
1542 | taskItem.CreatorID = itemBase.Creator; | ||
1543 | taskItem.BasePermissions = itemBase.BasePermissions; | ||
1544 | taskItem.CurrentPermissions = itemBase.CurrentPermissions; | ||
1545 | taskItem.EveryonePermissions = itemBase.EveryOnePermissions; | ||
1546 | taskItem.GroupPermissions = itemBase.GroupPermissions; | ||
1547 | taskItem.NextPermissions = itemBase.NextPermissions; | ||
1548 | taskItem.GroupID = itemBase.GroupID; | ||
1549 | taskItem.GroupPermissions = 0; | ||
1550 | taskItem.Flags = itemBase.Flags; | ||
1551 | taskItem.PermsGranter = UUID.Zero; | ||
1552 | taskItem.PermsMask = 0; | ||
1553 | taskItem.AssetID = asset.Metadata.FullID; | ||
1554 | |||
1555 | part.Inventory.AddInventoryItem(taskItem, false); | ||
1556 | part.GetProperties(remoteClient); | ||
1557 | |||
1558 | part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0); | ||
1559 | } | ||
1560 | } | ||
1561 | |||
1562 | /// <summary> | ||
1563 | /// Rez a script into a prim's inventory from another prim | ||
1564 | /// </summary> | ||
1565 | /// <param name="remoteClient"></param> | ||
1566 | /// <param name="itemID"> </param> | ||
1567 | /// <param name="localID"></param> | ||
1568 | public void RezScript(UUID srcId, SceneObjectPart srcPart, UUID destId, int pin, int running, int start_param) | ||
1569 | { | ||
1570 | TaskInventoryItem srcTaskItem = srcPart.Inventory.GetInventoryItem(srcId); | ||
1571 | |||
1572 | if (srcTaskItem == null) | ||
1573 | { | ||
1574 | m_log.ErrorFormat( | ||
1575 | "[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for rezzing a script but the " | ||
1576 | + " item does not exist in this inventory", | ||
1577 | srcId, srcPart.Name, srcPart.UUID); | ||
1578 | |||
1579 | return; | ||
1580 | } | ||
1581 | |||
1582 | SceneObjectPart destPart = GetSceneObjectPart(destId); | ||
1583 | |||
1584 | if (destPart == null) | ||
1585 | { | ||
1586 | m_log.ErrorFormat( | ||
1587 | "[PRIM INVENTORY]: " + | ||
1588 | "Could not find script for ID {0}", | ||
1589 | destId); | ||
1590 | return; | ||
1591 | } | ||
1592 | |||
1593 | // Must own the object, and have modify rights | ||
1594 | if (srcPart.OwnerID != destPart.OwnerID) | ||
1595 | return; | ||
1596 | |||
1597 | if ((destPart.OwnerMask & (uint)PermissionMask.Modify) == 0) | ||
1598 | return; | ||
1599 | |||
1600 | if (destPart.ScriptAccessPin != pin) | ||
1601 | { | ||
1602 | m_log.WarnFormat( | ||
1603 | "[PRIM INVENTORY]: " + | ||
1604 | "Script in object {0} : {1}, attempted to load script {2} : {3} into object {4} : {5} with invalid pin {6}", | ||
1605 | srcPart.Name, srcId, srcTaskItem.Name, srcTaskItem.ItemID, destPart.Name, destId, pin); | ||
1606 | // the LSL Wiki says we are supposed to shout on the DEBUG_CHANNEL - | ||
1607 | // "Object: Task Object trying to illegally load script onto task Other_Object!" | ||
1608 | // How do we shout from in here? | ||
1609 | return; | ||
1610 | } | ||
1611 | |||
1612 | TaskInventoryItem destTaskItem = new TaskInventoryItem(); | ||
1613 | |||
1614 | destTaskItem.ItemID = UUID.Random(); | ||
1615 | destTaskItem.CreatorID = srcTaskItem.CreatorID; | ||
1616 | destTaskItem.AssetID = srcTaskItem.AssetID; | ||
1617 | destTaskItem.GroupID = destPart.GroupID; | ||
1618 | destTaskItem.OwnerID = destPart.OwnerID; | ||
1619 | destTaskItem.ParentID = destPart.UUID; | ||
1620 | destTaskItem.ParentPartID = destPart.UUID; | ||
1621 | |||
1622 | destTaskItem.BasePermissions = srcTaskItem.BasePermissions; | ||
1623 | destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions; | ||
1624 | destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions; | ||
1625 | destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions; | ||
1626 | destTaskItem.NextPermissions = srcTaskItem.NextPermissions; | ||
1627 | destTaskItem.Flags = srcTaskItem.Flags; | ||
1628 | |||
1629 | if (destPart.OwnerID != srcPart.OwnerID) | ||
1630 | { | ||
1631 | if (Permissions.PropagatePermissions()) | ||
1632 | { | ||
1633 | destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions & | ||
1634 | srcTaskItem.NextPermissions; | ||
1635 | destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions & | ||
1636 | srcTaskItem.NextPermissions; | ||
1637 | destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions & | ||
1638 | srcTaskItem.NextPermissions; | ||
1639 | destTaskItem.BasePermissions = srcTaskItem.BasePermissions & | ||
1640 | srcTaskItem.NextPermissions; | ||
1641 | destTaskItem.CurrentPermissions |= 8; // Slam! | ||
1642 | } | ||
1643 | } | ||
1644 | |||
1645 | destTaskItem.Description = srcTaskItem.Description; | ||
1646 | destTaskItem.Name = srcTaskItem.Name; | ||
1647 | destTaskItem.InvType = srcTaskItem.InvType; | ||
1648 | destTaskItem.Type = srcTaskItem.Type; | ||
1649 | |||
1650 | destPart.Inventory.AddInventoryItemExclusive(destTaskItem, false); | ||
1651 | |||
1652 | if (running > 0) | ||
1653 | { | ||
1654 | destPart.Inventory.CreateScriptInstance(destTaskItem, 0, false, DefaultScriptEngine, 0); | ||
1655 | } | ||
1656 | |||
1657 | ScenePresence avatar; | ||
1658 | |||
1659 | if (TryGetAvatar(srcTaskItem.OwnerID, out avatar)) | ||
1660 | { | ||
1661 | destPart.GetProperties(avatar.ControllingClient); | ||
1662 | } | ||
1663 | } | ||
1664 | |||
1665 | /// <summary> | ||
1666 | /// Called when an object is removed from the environment into inventory. | ||
1667 | /// </summary> | ||
1668 | /// <param name="remoteClient"></param> | ||
1669 | /// <param name="localID"></param> | ||
1670 | /// <param name="groupID"></param> | ||
1671 | /// <param name="action"></param> | ||
1672 | /// <param name="destinationID"></param> | ||
1673 | public virtual void DeRezObject(IClientAPI remoteClient, uint localID, | ||
1674 | UUID groupID, DeRezAction action, UUID destinationID) | ||
1675 | { | ||
1676 | SceneObjectPart part = GetSceneObjectPart(localID); | ||
1677 | if (part == null) | ||
1678 | return; | ||
1679 | |||
1680 | if (part.ParentGroup == null || part.ParentGroup.IsDeleted) | ||
1681 | return; | ||
1682 | |||
1683 | // Can't delete child prims | ||
1684 | if (part != part.ParentGroup.RootPart) | ||
1685 | return; | ||
1686 | |||
1687 | SceneObjectGroup grp = part.ParentGroup; | ||
1688 | |||
1689 | //force a database backup/update on this SceneObjectGroup | ||
1690 | //So that we know the database is upto date, for when deleting the object from it | ||
1691 | ForceSceneObjectBackup(grp); | ||
1692 | |||
1693 | bool permissionToTake = false; | ||
1694 | bool permissionToDelete = false; | ||
1695 | |||
1696 | if (action == DeRezAction.SaveToExistingUserInventoryItem) | ||
1697 | { | ||
1698 | if (grp.OwnerID == remoteClient.AgentId && grp.RootPart.FromUserInventoryItemID != UUID.Zero) | ||
1699 | { | ||
1700 | permissionToTake = true; | ||
1701 | permissionToDelete = false; | ||
1702 | } | ||
1703 | } | ||
1704 | else if (action == DeRezAction.TakeCopy) | ||
1705 | { | ||
1706 | permissionToTake = | ||
1707 | Permissions.CanTakeCopyObject( | ||
1708 | grp.UUID, | ||
1709 | remoteClient.AgentId); | ||
1710 | } | ||
1711 | else if (action == DeRezAction.GodTakeCopy) | ||
1712 | { | ||
1713 | permissionToTake = | ||
1714 | Permissions.IsGod( | ||
1715 | remoteClient.AgentId); | ||
1716 | } | ||
1717 | else if (action == DeRezAction.Take) | ||
1718 | { | ||
1719 | permissionToTake = | ||
1720 | Permissions.CanTakeObject( | ||
1721 | grp.UUID, | ||
1722 | remoteClient.AgentId); | ||
1723 | |||
1724 | //If they can take, they can delete! | ||
1725 | permissionToDelete = permissionToTake; | ||
1726 | } | ||
1727 | else if (action == DeRezAction.Delete) | ||
1728 | { | ||
1729 | permissionToTake = | ||
1730 | Permissions.CanDeleteObject( | ||
1731 | grp.UUID, | ||
1732 | remoteClient.AgentId); | ||
1733 | permissionToDelete = permissionToTake; | ||
1734 | } | ||
1735 | else if (action == DeRezAction.Return) | ||
1736 | { | ||
1737 | if (remoteClient != null) | ||
1738 | { | ||
1739 | permissionToTake = | ||
1740 | Permissions.CanReturnObject( | ||
1741 | grp.UUID, | ||
1742 | remoteClient.AgentId); | ||
1743 | permissionToDelete = permissionToTake; | ||
1744 | |||
1745 | if (permissionToDelete) | ||
1746 | { | ||
1747 | AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return"); | ||
1748 | } | ||
1749 | } | ||
1750 | else // Auto return passes through here with null agent | ||
1751 | { | ||
1752 | permissionToTake = true; | ||
1753 | permissionToDelete = true; | ||
1754 | } | ||
1755 | } | ||
1756 | else | ||
1757 | { | ||
1758 | m_log.DebugFormat( | ||
1759 | "[AGENT INVENTORY]: Ignoring unexpected derez action {0} for {1}", action, remoteClient.Name); | ||
1760 | return; | ||
1761 | } | ||
1762 | |||
1763 | if (permissionToTake) | ||
1764 | { | ||
1765 | m_asyncSceneObjectDeleter.DeleteToInventory( | ||
1766 | action, destinationID, grp, remoteClient, | ||
1767 | permissionToDelete); | ||
1768 | } | ||
1769 | else if (permissionToDelete) | ||
1770 | { | ||
1771 | DeleteSceneObject(grp, false); | ||
1772 | } | ||
1773 | } | ||
1774 | |||
1775 | private bool WaitForInventory(CachedUserInfo info) | ||
1776 | { | ||
1777 | // 200 Seconds wait. This is called in the context of the | ||
1778 | // background delete thread, so we can afford to waste time | ||
1779 | // here. | ||
1780 | // | ||
1781 | int count = 200; | ||
1782 | |||
1783 | while (count > 0) | ||
1784 | { | ||
1785 | System.Threading.Thread.Sleep(100); | ||
1786 | count--; | ||
1787 | if (info.HasReceivedInventory) | ||
1788 | return true; | ||
1789 | } | ||
1790 | m_log.DebugFormat("Timed out waiting for inventory of user {0}", | ||
1791 | info.UserProfile.ID.ToString()); | ||
1792 | return false; | ||
1793 | } | ||
1794 | |||
1795 | /// <summary> | ||
1796 | /// Delete a scene object from a scene and place in the given avatar's inventory. | ||
1797 | /// Returns the UUID of the newly created asset. | ||
1798 | /// </summary> | ||
1799 | /// <param name="action"></param> | ||
1800 | /// <param name="folderID"></param> | ||
1801 | /// <param name="objectGroup"></param> | ||
1802 | /// <param name="remoteClient"> </param> | ||
1803 | public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, | ||
1804 | SceneObjectGroup objectGroup, IClientAPI remoteClient) | ||
1805 | { | ||
1806 | UUID assetID = UUID.Zero; | ||
1807 | |||
1808 | string sceneObjectXml = objectGroup.ToXmlString(); | ||
1809 | |||
1810 | // Get the user info of the item destination | ||
1811 | // | ||
1812 | CachedUserInfo userInfo; | ||
1813 | |||
1814 | if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || | ||
1815 | action == DeRezAction.SaveToExistingUserInventoryItem) | ||
1816 | { | ||
1817 | // Take or take copy require a taker | ||
1818 | // Saving changes requires a local user | ||
1819 | // | ||
1820 | if (remoteClient == null) | ||
1821 | return UUID.Zero; | ||
1822 | |||
1823 | userInfo = CommsManager.UserProfileCacheService.GetUserDetails( | ||
1824 | remoteClient.AgentId); | ||
1825 | } | ||
1826 | else | ||
1827 | { | ||
1828 | // All returns / deletes go to the object owner | ||
1829 | // | ||
1830 | userInfo = CommsManager.UserProfileCacheService.GetUserDetails( | ||
1831 | objectGroup.RootPart.OwnerID); | ||
1832 | } | ||
1833 | |||
1834 | if (userInfo == null) // Can't proceed | ||
1835 | { | ||
1836 | return UUID.Zero; | ||
1837 | } | ||
1838 | |||
1839 | if (!userInfo.HasReceivedInventory) | ||
1840 | { | ||
1841 | // Async inventory requests will queue, but they will never | ||
1842 | // execute unless inventory is actually fetched | ||
1843 | // | ||
1844 | CommsManager.UserProfileCacheService.RequestInventoryForUser( | ||
1845 | userInfo.UserProfile.ID); | ||
1846 | } | ||
1847 | |||
1848 | if (userInfo != null) | ||
1849 | { | ||
1850 | // If we're returning someone's item, it goes back to the | ||
1851 | // owner's Lost And Found folder. | ||
1852 | // Delete is treated like return in this case | ||
1853 | // Deleting your own items makes them go to trash | ||
1854 | // | ||
1855 | |||
1856 | InventoryFolderBase folder = null; | ||
1857 | InventoryItemBase item = null; | ||
1858 | |||
1859 | if (DeRezAction.SaveToExistingUserInventoryItem == action) | ||
1860 | { | ||
1861 | item = userInfo.RootFolder.FindItem( | ||
1862 | objectGroup.RootPart.FromUserInventoryItemID); | ||
1863 | |||
1864 | if (null == item) | ||
1865 | { | ||
1866 | m_log.DebugFormat( | ||
1867 | "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", | ||
1868 | objectGroup.Name, objectGroup.UUID); | ||
1869 | return UUID.Zero; | ||
1870 | } | ||
1871 | } | ||
1872 | else | ||
1873 | { | ||
1874 | // Folder magic | ||
1875 | // | ||
1876 | if (action == DeRezAction.Delete) | ||
1877 | { | ||
1878 | // Deleting someone else's item | ||
1879 | // | ||
1880 | if (remoteClient == null || | ||
1881 | objectGroup.OwnerID != remoteClient.AgentId) | ||
1882 | { | ||
1883 | // Folder skeleton may not be loaded and we | ||
1884 | // have to wait for the inventory to find | ||
1885 | // the destination folder | ||
1886 | // | ||
1887 | if (!WaitForInventory(userInfo)) | ||
1888 | return UUID.Zero; | ||
1889 | folder = userInfo.FindFolderForType( | ||
1890 | (int)AssetType.LostAndFoundFolder); | ||
1891 | } | ||
1892 | else | ||
1893 | { | ||
1894 | // Assume inventory skeleton was loaded during login | ||
1895 | // and all folders can be found | ||
1896 | // | ||
1897 | folder = userInfo.FindFolderForType( | ||
1898 | (int)AssetType.TrashFolder); | ||
1899 | } | ||
1900 | } | ||
1901 | else if (action == DeRezAction.Return) | ||
1902 | { | ||
1903 | // Wait if needed | ||
1904 | // | ||
1905 | if (!userInfo.HasReceivedInventory) | ||
1906 | { | ||
1907 | if (!WaitForInventory(userInfo)) | ||
1908 | return UUID.Zero; | ||
1909 | } | ||
1910 | |||
1911 | // Dump to lost + found unconditionally | ||
1912 | // | ||
1913 | folder = userInfo.FindFolderForType( | ||
1914 | (int)AssetType.LostAndFoundFolder); | ||
1915 | } | ||
1916 | |||
1917 | if (folderID == UUID.Zero && folder == null) | ||
1918 | { | ||
1919 | // Catch all. Use lost & found | ||
1920 | // | ||
1921 | if (!userInfo.HasReceivedInventory) | ||
1922 | { | ||
1923 | if (!WaitForInventory(userInfo)) | ||
1924 | return UUID.Zero; | ||
1925 | } | ||
1926 | |||
1927 | folder = userInfo.FindFolderForType( | ||
1928 | (int)AssetType.LostAndFoundFolder); | ||
1929 | } | ||
1930 | |||
1931 | if (folder == null) // None of the above | ||
1932 | { | ||
1933 | folder = userInfo.RootFolder.FindFolder(folderID); | ||
1934 | |||
1935 | if (folder == null) // Nowhere to put it | ||
1936 | { | ||
1937 | return UUID.Zero; | ||
1938 | } | ||
1939 | } | ||
1940 | |||
1941 | item = new InventoryItemBase(); | ||
1942 | item.Creator = objectGroup.RootPart.CreatorID; | ||
1943 | item.ID = UUID.Random(); | ||
1944 | item.InvType = (int)InventoryType.Object; | ||
1945 | item.Folder = folder.ID; | ||
1946 | item.Owner = userInfo.UserProfile.ID; | ||
1947 | |||
1948 | } | ||
1949 | |||
1950 | AssetBase asset = CreateAsset( | ||
1951 | objectGroup.GetPartName(objectGroup.RootPart.LocalId), | ||
1952 | objectGroup.GetPartDescription(objectGroup.RootPart.LocalId), | ||
1953 | (sbyte)AssetType.Object, | ||
1954 | Utils.StringToBytes(sceneObjectXml)); | ||
1955 | AssetCache.AddAsset(asset); | ||
1956 | assetID = asset.Metadata.FullID; | ||
1957 | |||
1958 | if (DeRezAction.SaveToExistingUserInventoryItem == action) | ||
1959 | { | ||
1960 | item.AssetID = asset.Metadata.FullID; | ||
1961 | userInfo.UpdateItem(item); | ||
1962 | } | ||
1963 | else | ||
1964 | { | ||
1965 | item.AssetID = asset.Metadata.FullID; | ||
1966 | |||
1967 | if (remoteClient != null && (remoteClient.AgentId != objectGroup.RootPart.OwnerID) && Permissions.PropagatePermissions()) | ||
1968 | { | ||
1969 | uint perms=objectGroup.GetEffectivePermissions(); | ||
1970 | uint nextPerms=(perms & 7) << 13; | ||
1971 | if ((nextPerms & (uint)PermissionMask.Copy) == 0) | ||
1972 | perms &= ~(uint)PermissionMask.Copy; | ||
1973 | if ((nextPerms & (uint)PermissionMask.Transfer) == 0) | ||
1974 | perms &= ~(uint)PermissionMask.Transfer; | ||
1975 | if ((nextPerms & (uint)PermissionMask.Modify) == 0) | ||
1976 | perms &= ~(uint)PermissionMask.Modify; | ||
1977 | |||
1978 | item.BasePermissions = perms & objectGroup.RootPart.NextOwnerMask; | ||
1979 | item.CurrentPermissions = item.BasePermissions; | ||
1980 | item.NextPermissions = objectGroup.RootPart.NextOwnerMask; | ||
1981 | item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask & objectGroup.RootPart.NextOwnerMask; | ||
1982 | item.GroupPermissions = objectGroup.RootPart.GroupMask & objectGroup.RootPart.NextOwnerMask; | ||
1983 | item.CurrentPermissions |= 8; // Slam! | ||
1984 | } | ||
1985 | else | ||
1986 | { | ||
1987 | item.BasePermissions = objectGroup.GetEffectivePermissions(); | ||
1988 | item.CurrentPermissions = objectGroup.GetEffectivePermissions(); | ||
1989 | item.NextPermissions = objectGroup.RootPart.NextOwnerMask; | ||
1990 | item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask; | ||
1991 | item.GroupPermissions = objectGroup.RootPart.GroupMask; | ||
1992 | |||
1993 | item.CurrentPermissions |= 8; // Slam! | ||
1994 | } | ||
1995 | |||
1996 | // TODO: add the new fields (Flags, Sale info, etc) | ||
1997 | item.CreationDate = Util.UnixTimeSinceEpoch(); | ||
1998 | item.Description = asset.Metadata.Description; | ||
1999 | item.Name = asset.Metadata.Name; | ||
2000 | item.AssetType = asset.Metadata.Type; | ||
2001 | |||
2002 | userInfo.AddItem(item); | ||
2003 | |||
2004 | if (remoteClient != null && item.Owner == remoteClient.AgentId) | ||
2005 | { | ||
2006 | remoteClient.SendInventoryItemCreateUpdate(item); | ||
2007 | } | ||
2008 | else | ||
2009 | { | ||
2010 | ScenePresence notifyUser = GetScenePresence(item.Owner); | ||
2011 | if (notifyUser != null) | ||
2012 | { | ||
2013 | notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item); | ||
2014 | } | ||
2015 | } | ||
2016 | } | ||
2017 | } | ||
2018 | |||
2019 | return assetID; | ||
2020 | } | ||
2021 | |||
2022 | public void updateKnownAsset(IClientAPI remoteClient, SceneObjectGroup grp, UUID assetID, UUID agentID) | ||
2023 | { | ||
2024 | SceneObjectGroup objectGroup = grp; | ||
2025 | if (objectGroup != null) | ||
2026 | { | ||
2027 | if (!grp.HasGroupChanged) | ||
2028 | { | ||
2029 | m_log.InfoFormat("[ATTACHMENT]: Save request for {0} which is unchanged", grp.UUID); | ||
2030 | return; | ||
2031 | } | ||
2032 | |||
2033 | m_log.InfoFormat( | ||
2034 | "[ATTACHMENT]: Updating asset for attachment {0}, attachpoint {1}", | ||
2035 | grp.UUID, grp.GetAttachmentPoint()); | ||
2036 | |||
2037 | string sceneObjectXml = objectGroup.ToXmlString(); | ||
2038 | |||
2039 | CachedUserInfo userInfo = | ||
2040 | CommsManager.UserProfileCacheService.GetUserDetails(agentID); | ||
2041 | if (userInfo != null && userInfo.RootFolder != null) | ||
2042 | { | ||
2043 | Queue<InventoryFolderImpl> searchfolders = new Queue<InventoryFolderImpl>(); | ||
2044 | searchfolders.Enqueue(userInfo.RootFolder); | ||
2045 | |||
2046 | UUID foundFolder = UUID.Zero; | ||
2047 | InventoryItemBase item = null; | ||
2048 | |||
2049 | // search through folders to find the asset. | ||
2050 | while (searchfolders.Count > 0) | ||
2051 | { | ||
2052 | InventoryFolderImpl fld = searchfolders.Dequeue(); | ||
2053 | lock (fld) | ||
2054 | { | ||
2055 | if (fld != null) | ||
2056 | { | ||
2057 | if (fld.Items.ContainsKey(assetID)) | ||
2058 | { | ||
2059 | item = fld.Items[assetID]; | ||
2060 | foundFolder = fld.ID; | ||
2061 | searchfolders.Clear(); | ||
2062 | break; | ||
2063 | } | ||
2064 | else | ||
2065 | { | ||
2066 | foreach (InventoryFolderImpl subfld in fld.RequestListOfFolderImpls()) | ||
2067 | { | ||
2068 | searchfolders.Enqueue(subfld); | ||
2069 | } | ||
2070 | } | ||
2071 | } | ||
2072 | } | ||
2073 | } | ||
2074 | |||
2075 | if (foundFolder != UUID.Zero && item != null) | ||
2076 | { | ||
2077 | AssetBase asset = CreateAsset( | ||
2078 | objectGroup.GetPartName(objectGroup.LocalId), | ||
2079 | objectGroup.GetPartDescription(objectGroup.LocalId), | ||
2080 | (sbyte)AssetType.Object, | ||
2081 | Utils.StringToBytes(sceneObjectXml)); | ||
2082 | AssetCache.AddAsset(asset); | ||
2083 | |||
2084 | item.AssetID = asset.Metadata.FullID; | ||
2085 | item.Description = asset.Metadata.Description; | ||
2086 | item.Name = asset.Metadata.Name; | ||
2087 | item.AssetType = asset.Metadata.Type; | ||
2088 | item.InvType = (int)InventoryType.Object; | ||
2089 | item.Folder = foundFolder; | ||
2090 | |||
2091 | userInfo.UpdateItem(item); | ||
2092 | |||
2093 | // this gets called when the agent loggs off! | ||
2094 | if (remoteClient != null) | ||
2095 | { | ||
2096 | remoteClient.SendInventoryItemCreateUpdate(item); | ||
2097 | } | ||
2098 | } | ||
2099 | } | ||
2100 | } | ||
2101 | } | ||
2102 | |||
2103 | public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID) | ||
2104 | { | ||
2105 | itemID = UUID.Zero; | ||
2106 | if (grp != null) | ||
2107 | { | ||
2108 | string sceneObjectXml = grp.ToXmlString(); | ||
2109 | |||
2110 | CachedUserInfo userInfo = | ||
2111 | CommsManager.UserProfileCacheService.GetUserDetails(AgentId); | ||
2112 | if (userInfo != null) | ||
2113 | { | ||
2114 | AssetBase asset = CreateAsset( | ||
2115 | grp.GetPartName(grp.LocalId), | ||
2116 | grp.GetPartDescription(grp.LocalId), | ||
2117 | (sbyte)AssetType.Object, | ||
2118 | Utils.StringToBytes(sceneObjectXml)); | ||
2119 | AssetCache.AddAsset(asset); | ||
2120 | |||
2121 | InventoryItemBase item = new InventoryItemBase(); | ||
2122 | item.Creator = grp.RootPart.CreatorID; | ||
2123 | item.Owner = remoteClient.AgentId; | ||
2124 | item.ID = UUID.Random(); | ||
2125 | item.AssetID = asset.Metadata.FullID; | ||
2126 | item.Description = asset.Metadata.Description; | ||
2127 | item.Name = asset.Metadata.Name; | ||
2128 | item.AssetType = asset.Metadata.Type; | ||
2129 | item.InvType = (int)InventoryType.Object; | ||
2130 | |||
2131 | item.Folder = UUID.Zero; // Objects folder! | ||
2132 | |||
2133 | if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions()) | ||
2134 | { | ||
2135 | item.BasePermissions = grp.RootPart.NextOwnerMask; | ||
2136 | item.CurrentPermissions = grp.RootPart.NextOwnerMask; | ||
2137 | item.NextPermissions = grp.RootPart.NextOwnerMask; | ||
2138 | item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask; | ||
2139 | item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask; | ||
2140 | } | ||
2141 | else | ||
2142 | { | ||
2143 | item.BasePermissions = grp.RootPart.BaseMask; | ||
2144 | item.CurrentPermissions = grp.RootPart.OwnerMask; | ||
2145 | item.NextPermissions = grp.RootPart.NextOwnerMask; | ||
2146 | item.EveryOnePermissions = grp.RootPart.EveryoneMask; | ||
2147 | item.GroupPermissions = grp.RootPart.GroupMask; | ||
2148 | } | ||
2149 | item.CreationDate = Util.UnixTimeSinceEpoch(); | ||
2150 | |||
2151 | // sets assetID so client can show asset as 'attached' in inventory | ||
2152 | grp.SetFromAssetID(item.ID); | ||
2153 | |||
2154 | userInfo.AddItem(item); | ||
2155 | remoteClient.SendInventoryItemCreateUpdate(item); | ||
2156 | |||
2157 | itemID = item.ID; | ||
2158 | return item.AssetID; | ||
2159 | } | ||
2160 | return UUID.Zero; | ||
2161 | } | ||
2162 | return UUID.Zero; | ||
2163 | } | ||
2164 | |||
2165 | /// <summary> | ||
2166 | /// Event Handler Rez an object into a scene | ||
2167 | /// Calls the non-void event handler | ||
2168 | /// </summary> | ||
2169 | /// <param name="remoteClient"></param> | ||
2170 | /// <param name="itemID"></param> | ||
2171 | /// <param name="RayEnd"></param> | ||
2172 | /// <param name="RayStart"></param> | ||
2173 | /// <param name="RayTargetID"></param> | ||
2174 | /// <param name="BypassRayCast"></param> | ||
2175 | /// <param name="RayEndIsIntersection"></param> | ||
2176 | /// <param name="EveryoneMask"></param> | ||
2177 | /// <param name="GroupMask"></param> | ||
2178 | /// <param name="RezSelected"></param> | ||
2179 | /// <param name="RemoveItem"></param> | ||
2180 | /// <param name="fromTaskID"></param> | ||
2181 | public virtual void RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, | ||
2182 | UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, | ||
2183 | bool RezSelected, bool RemoveItem, UUID fromTaskID) | ||
2184 | { | ||
2185 | RezObject( | ||
2186 | remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, | ||
2187 | RezSelected, RemoveItem, fromTaskID, false); | ||
2188 | } | ||
2189 | |||
2190 | /// <summary> | ||
2191 | /// Rez an object into the scene from the user's inventory | ||
2192 | /// </summary> | ||
2193 | /// <param name="remoteClient"></param> | ||
2194 | /// <param name="itemID"></param> | ||
2195 | /// <param name="RayEnd"></param> | ||
2196 | /// <param name="RayStart"></param> | ||
2197 | /// <param name="RayTargetID"></param> | ||
2198 | /// <param name="BypassRayCast"></param> | ||
2199 | /// <param name="RayEndIsIntersection"></param> | ||
2200 | /// <param name="RezSelected"></param> | ||
2201 | /// <param name="RemoveItem"></param> | ||
2202 | /// <param name="fromTaskID"></param> | ||
2203 | /// <param name="attachment"></param> | ||
2204 | /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns> | ||
2205 | public virtual SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, | ||
2206 | UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, | ||
2207 | bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) | ||
2208 | { | ||
2209 | // Work out position details | ||
2210 | byte bRayEndIsIntersection = (byte)0; | ||
2211 | |||
2212 | if (RayEndIsIntersection) | ||
2213 | { | ||
2214 | bRayEndIsIntersection = (byte)1; | ||
2215 | } | ||
2216 | else | ||
2217 | { | ||
2218 | bRayEndIsIntersection = (byte)0; | ||
2219 | } | ||
2220 | |||
2221 | Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); | ||
2222 | |||
2223 | |||
2224 | Vector3 pos = GetNewRezLocation( | ||
2225 | RayStart, RayEnd, RayTargetID, Quaternion.Identity, | ||
2226 | BypassRayCast, bRayEndIsIntersection,true,scale, false); | ||
2227 | |||
2228 | // Rez object | ||
2229 | CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
2230 | if (userInfo != null) | ||
2231 | { | ||
2232 | // Do NOT use HasReceivedInventory here, this is called | ||
2233 | // from within ItemReceive during login for attachments. | ||
2234 | // Using HasReceivedInventory here will break attachment | ||
2235 | // persistence! | ||
2236 | // | ||
2237 | if (userInfo.RootFolder != null) | ||
2238 | { | ||
2239 | InventoryItemBase item = userInfo.RootFolder.FindItem(itemID); | ||
2240 | |||
2241 | if (item != null) | ||
2242 | { | ||
2243 | AssetBase rezAsset = AssetCache.GetAsset(item.AssetID, false); | ||
2244 | |||
2245 | if (rezAsset != null) | ||
2246 | { | ||
2247 | UUID itemId = UUID.Zero; | ||
2248 | |||
2249 | // If we have permission to copy then link the rezzed object back to the user inventory | ||
2250 | // item that it came from. This allows us to enable 'save object to inventory' | ||
2251 | if (!Permissions.BypassPermissions()) | ||
2252 | { | ||
2253 | if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy) | ||
2254 | { | ||
2255 | itemId = item.ID; | ||
2256 | } | ||
2257 | } | ||
2258 | |||
2259 | string xmlData = Utils.BytesToString(rezAsset.Data); | ||
2260 | SceneObjectGroup group = new SceneObjectGroup(itemId, xmlData, true); | ||
2261 | |||
2262 | if (!Permissions.CanRezObject( | ||
2263 | group.Children.Count, remoteClient.AgentId, pos) | ||
2264 | && !attachment) | ||
2265 | { | ||
2266 | return null; | ||
2267 | } | ||
2268 | |||
2269 | group.ResetIDs(); | ||
2270 | |||
2271 | AddNewSceneObject(group, true); | ||
2272 | |||
2273 | // if attachment we set it's asset id so object updates can reflect that | ||
2274 | // if not, we set it's position in world. | ||
2275 | if (!attachment) | ||
2276 | { | ||
2277 | pos = GetNewRezLocation( | ||
2278 | RayStart, RayEnd, RayTargetID, Quaternion.Identity, | ||
2279 | BypassRayCast, bRayEndIsIntersection, true, group.GroupScale(), false); | ||
2280 | group.AbsolutePosition = pos; | ||
2281 | } | ||
2282 | else | ||
2283 | { | ||
2284 | group.SetFromAssetID(itemID); | ||
2285 | } | ||
2286 | |||
2287 | SceneObjectPart rootPart = null; | ||
2288 | try | ||
2289 | { | ||
2290 | rootPart = group.GetChildPart(group.UUID); | ||
2291 | } | ||
2292 | catch (NullReferenceException) | ||
2293 | { | ||
2294 | string isAttachment = ""; | ||
2295 | |||
2296 | if (attachment) | ||
2297 | isAttachment = " Object was an attachment"; | ||
2298 | |||
2299 | m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment); | ||
2300 | } | ||
2301 | |||
2302 | // Since renaming the item in the inventory does not affect the name stored | ||
2303 | // in the serialization, transfer the correct name from the inventory to the | ||
2304 | // object itself before we rez. | ||
2305 | rootPart.Name = item.Name; | ||
2306 | rootPart.Description = item.Description; | ||
2307 | |||
2308 | List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values); | ||
2309 | |||
2310 | group.SetGroup(remoteClient.ActiveGroupId, remoteClient); | ||
2311 | if (rootPart.OwnerID != item.Owner) | ||
2312 | { | ||
2313 | //Need to kill the for sale here | ||
2314 | rootPart.ObjectSaleType = 0; | ||
2315 | rootPart.SalePrice = 10; | ||
2316 | |||
2317 | if (Permissions.PropagatePermissions()) | ||
2318 | { | ||
2319 | if ((item.CurrentPermissions & 8) != 0) | ||
2320 | { | ||
2321 | foreach (SceneObjectPart part in partList) | ||
2322 | { | ||
2323 | part.EveryoneMask = item.EveryOnePermissions; | ||
2324 | part.NextOwnerMask = item.NextPermissions; | ||
2325 | part.GroupMask = 0; // DO NOT propagate here | ||
2326 | } | ||
2327 | } | ||
2328 | group.ApplyNextOwnerPermissions(); | ||
2329 | } | ||
2330 | } | ||
2331 | |||
2332 | foreach (SceneObjectPart part in partList) | ||
2333 | { | ||
2334 | if (part.OwnerID != item.Owner) | ||
2335 | { | ||
2336 | part.LastOwnerID = part.OwnerID; | ||
2337 | part.OwnerID = item.Owner; | ||
2338 | part.Inventory.ChangeInventoryOwner(item.Owner); | ||
2339 | } | ||
2340 | else if (((item.CurrentPermissions & 8) != 0) && (!attachment)) // Slam! | ||
2341 | { | ||
2342 | part.EveryoneMask = item.EveryOnePermissions; | ||
2343 | part.NextOwnerMask = item.NextPermissions; | ||
2344 | |||
2345 | part.GroupMask = 0; // DO NOT propagate here | ||
2346 | } | ||
2347 | } | ||
2348 | |||
2349 | rootPart.TrimPermissions(); | ||
2350 | |||
2351 | if (!attachment) | ||
2352 | { | ||
2353 | if (group.RootPart.Shape.PCode == (byte)PCode.Prim) | ||
2354 | { | ||
2355 | group.ClearPartAttachmentData(); | ||
2356 | } | ||
2357 | } | ||
2358 | |||
2359 | if (!attachment) | ||
2360 | { | ||
2361 | // Fire on_rez | ||
2362 | group.CreateScriptInstances(0, true, DefaultScriptEngine, 0); | ||
2363 | |||
2364 | rootPart.ScheduleFullUpdate(); | ||
2365 | } | ||
2366 | |||
2367 | if (!Permissions.BypassPermissions()) | ||
2368 | { | ||
2369 | if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) | ||
2370 | { | ||
2371 | // If this is done on attachments, no | ||
2372 | // copy ones will be lost, so avoid it | ||
2373 | // | ||
2374 | if (!attachment) | ||
2375 | userInfo.DeleteItem(item.ID); | ||
2376 | } | ||
2377 | } | ||
2378 | |||
2379 | return rootPart.ParentGroup; | ||
2380 | } | ||
2381 | } | ||
2382 | } | ||
2383 | else | ||
2384 | m_log.WarnFormat("[AGENT INVENTORY]: Root folder not found in {0}", RegionInfo.RegionName); | ||
2385 | } | ||
2386 | else | ||
2387 | m_log.WarnFormat("[AGENT INVENTORY]: User profile not found in {0}", RegionInfo.RegionName); | ||
2388 | |||
2389 | return null; | ||
2390 | } | ||
2391 | |||
2392 | /// <summary> | ||
2393 | /// Rez an object into the scene from a prim's inventory. | ||
2394 | /// </summary> | ||
2395 | /// <param name="sourcePart"></param> | ||
2396 | /// <param name="item"></param> | ||
2397 | /// <param name="pos"></param> | ||
2398 | /// <param name="rot"></param> | ||
2399 | /// <param name="vel"></param> | ||
2400 | /// <param name="param"></param> | ||
2401 | /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> | ||
2402 | public virtual SceneObjectGroup RezObject( | ||
2403 | SceneObjectPart sourcePart, TaskInventoryItem item, | ||
2404 | Vector3 pos, Quaternion rot, Vector3 vel, int param) | ||
2405 | { | ||
2406 | // Rez object | ||
2407 | if (item != null) | ||
2408 | { | ||
2409 | UUID ownerID = item.OwnerID; | ||
2410 | |||
2411 | AssetBase rezAsset = AssetCache.GetAsset(item.AssetID, false); | ||
2412 | |||
2413 | if (rezAsset != null) | ||
2414 | { | ||
2415 | string xmlData = Utils.BytesToString(rezAsset.Data); | ||
2416 | SceneObjectGroup group = new SceneObjectGroup(xmlData, true); | ||
2417 | |||
2418 | if (!Permissions.CanRezObject(group.Children.Count, ownerID, pos)) | ||
2419 | { | ||
2420 | return null; | ||
2421 | } | ||
2422 | group.ResetIDs(); | ||
2423 | |||
2424 | AddNewSceneObject(group, true); | ||
2425 | |||
2426 | // we set it's position in world. | ||
2427 | group.AbsolutePosition = pos; | ||
2428 | |||
2429 | SceneObjectPart rootPart = group.GetChildPart(group.UUID); | ||
2430 | |||
2431 | // Since renaming the item in the inventory does not affect the name stored | ||
2432 | // in the serialization, transfer the correct name from the inventory to the | ||
2433 | // object itself before we rez. | ||
2434 | rootPart.Name = item.Name; | ||
2435 | rootPart.Description = item.Description; | ||
2436 | |||
2437 | List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values); | ||
2438 | |||
2439 | group.SetGroup(sourcePart.GroupID, null); | ||
2440 | |||
2441 | if (rootPart.OwnerID != item.OwnerID) | ||
2442 | { | ||
2443 | if (Permissions.PropagatePermissions()) | ||
2444 | { | ||
2445 | if ((item.CurrentPermissions & 8) != 0) | ||
2446 | { | ||
2447 | foreach (SceneObjectPart part in partList) | ||
2448 | { | ||
2449 | part.EveryoneMask = item.EveryonePermissions; | ||
2450 | part.NextOwnerMask = item.NextPermissions; | ||
2451 | } | ||
2452 | } | ||
2453 | group.ApplyNextOwnerPermissions(); | ||
2454 | } | ||
2455 | } | ||
2456 | |||
2457 | foreach (SceneObjectPart part in partList) | ||
2458 | { | ||
2459 | if (part.OwnerID != item.OwnerID) | ||
2460 | { | ||
2461 | part.LastOwnerID = part.OwnerID; | ||
2462 | part.OwnerID = item.OwnerID; | ||
2463 | part.Inventory.ChangeInventoryOwner(item.OwnerID); | ||
2464 | } | ||
2465 | else if ((item.CurrentPermissions & 8) != 0) // Slam! | ||
2466 | { | ||
2467 | part.EveryoneMask = item.EveryonePermissions; | ||
2468 | part.NextOwnerMask = item.NextPermissions; | ||
2469 | } | ||
2470 | } | ||
2471 | rootPart.TrimPermissions(); | ||
2472 | if (group.RootPart.Shape.PCode == (byte)PCode.Prim) | ||
2473 | { | ||
2474 | group.ClearPartAttachmentData(); | ||
2475 | } | ||
2476 | group.UpdateGroupRotation(rot); | ||
2477 | //group.ApplyPhysics(m_physicalPrim); | ||
2478 | if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero) | ||
2479 | { | ||
2480 | group.RootPart.ApplyImpulse((vel * group.GetMass()), false); | ||
2481 | group.Velocity = vel; | ||
2482 | rootPart.ScheduleFullUpdate(); | ||
2483 | } | ||
2484 | group.CreateScriptInstances(param, true, DefaultScriptEngine, 2); | ||
2485 | rootPart.ScheduleFullUpdate(); | ||
2486 | |||
2487 | if (!Permissions.BypassPermissions()) | ||
2488 | { | ||
2489 | if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) | ||
2490 | sourcePart.Inventory.RemoveInventoryItem(item.ItemID); | ||
2491 | } | ||
2492 | return rootPart.ParentGroup; | ||
2493 | } | ||
2494 | } | ||
2495 | |||
2496 | return null; | ||
2497 | } | ||
2498 | |||
2499 | public virtual bool returnObjects(SceneObjectGroup[] returnobjects, UUID AgentId) | ||
2500 | { | ||
2501 | foreach (SceneObjectGroup grp in returnobjects) | ||
2502 | { | ||
2503 | AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return"); | ||
2504 | DeRezObject(null, grp.RootPart.LocalId, | ||
2505 | grp.RootPart.GroupID, DeRezAction.Return, UUID.Zero); | ||
2506 | } | ||
2507 | |||
2508 | return true; | ||
2509 | } | ||
2510 | |||
2511 | public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) | ||
2512 | { | ||
2513 | SceneObjectPart part = GetSceneObjectPart(objectID); | ||
2514 | if (part == null) | ||
2515 | return; | ||
2516 | |||
2517 | if (running) | ||
2518 | EventManager.TriggerStartScript(part.LocalId, itemID); | ||
2519 | else | ||
2520 | EventManager.TriggerStopScript(part.LocalId, itemID); | ||
2521 | } | ||
2522 | |||
2523 | public UUID RezSingleAttachment(IClientAPI remoteClient, UUID itemID, | ||
2524 | uint AttachmentPt) | ||
2525 | { | ||
2526 | SceneObjectGroup att = m_sceneGraph.RezSingleAttachment(remoteClient, itemID, AttachmentPt); | ||
2527 | |||
2528 | if (att == null) | ||
2529 | { | ||
2530 | DetachSingleAttachmentToInv(itemID, remoteClient); | ||
2531 | return UUID.Zero; | ||
2532 | } | ||
2533 | |||
2534 | return RezSingleAttachment(att, remoteClient, itemID, AttachmentPt); | ||
2535 | } | ||
2536 | |||
2537 | public UUID RezSingleAttachment(SceneObjectGroup att, | ||
2538 | IClientAPI remoteClient, UUID itemID, uint AttachmentPt) | ||
2539 | { | ||
2540 | if (!att.IsDeleted) | ||
2541 | AttachmentPt = att.RootPart.AttachmentPoint; | ||
2542 | |||
2543 | ScenePresence presence; | ||
2544 | if (TryGetAvatar(remoteClient.AgentId, out presence)) | ||
2545 | { | ||
2546 | presence.Appearance.SetAttachment((int)AttachmentPt, itemID, att.UUID); | ||
2547 | IAvatarFactory ava = RequestModuleInterface<IAvatarFactory>(); | ||
2548 | if (ava != null) | ||
2549 | { | ||
2550 | ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance); | ||
2551 | } | ||
2552 | |||
2553 | } | ||
2554 | return att.UUID; | ||
2555 | } | ||
2556 | |||
2557 | public void AttachObject(IClientAPI controllingClient, uint localID, uint attachPoint, Quaternion rot, Vector3 pos, bool silent) | ||
2558 | { | ||
2559 | m_sceneGraph.AttachObject(controllingClient, localID, attachPoint, rot, pos, silent); | ||
2560 | } | ||
2561 | |||
2562 | public void AttachObject(IClientAPI remoteClient, uint AttachmentPt, UUID itemID, SceneObjectGroup att) | ||
2563 | { | ||
2564 | if (UUID.Zero == itemID) | ||
2565 | { | ||
2566 | m_log.Error("[SCENE INVENTORY]: Unable to save attachment. Error inventory item ID."); | ||
2567 | return; | ||
2568 | } | ||
2569 | |||
2570 | if (0 == AttachmentPt) | ||
2571 | { | ||
2572 | m_log.Error("[SCENE INVENTORY]: Unable to save attachment. Error attachment point."); | ||
2573 | return; | ||
2574 | } | ||
2575 | |||
2576 | if (null == att.RootPart) | ||
2577 | { | ||
2578 | m_log.Error("[SCENE INVENTORY]: Unable to save attachment for a prim without the rootpart!"); | ||
2579 | return; | ||
2580 | } | ||
2581 | |||
2582 | ScenePresence presence; | ||
2583 | if (TryGetAvatar(remoteClient.AgentId, out presence)) | ||
2584 | { | ||
2585 | presence.Appearance.SetAttachment((int)AttachmentPt, itemID, att.UUID); | ||
2586 | IAvatarFactory ava = RequestModuleInterface<IAvatarFactory>(); | ||
2587 | if (ava != null) | ||
2588 | { | ||
2589 | m_log.InfoFormat("[SCENE INVENTORY]: Saving avatar attachment. AgentID:{0} ItemID:{1} AttachmentPoint:{2}", remoteClient.AgentId, itemID, AttachmentPt); | ||
2590 | ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance); | ||
2591 | } | ||
2592 | } | ||
2593 | } | ||
2594 | |||
2595 | public void DetachSingleAttachmentToGround(UUID itemID, IClientAPI remoteClient) | ||
2596 | { | ||
2597 | SceneObjectPart part = GetSceneObjectPart(itemID); | ||
2598 | if (part == null || part.ParentGroup == null) | ||
2599 | return; | ||
2600 | |||
2601 | UUID inventoryID = part.ParentGroup.GetFromAssetID(); | ||
2602 | |||
2603 | ScenePresence presence; | ||
2604 | if (TryGetAvatar(remoteClient.AgentId, out presence)) | ||
2605 | { | ||
2606 | if (!Permissions.CanRezObject(part.ParentGroup.Children.Count, remoteClient.AgentId, presence.AbsolutePosition)) | ||
2607 | return; | ||
2608 | |||
2609 | presence.Appearance.DetachAttachment(itemID); | ||
2610 | IAvatarFactory ava = RequestModuleInterface<IAvatarFactory>(); | ||
2611 | if (ava != null) | ||
2612 | { | ||
2613 | ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance); | ||
2614 | } | ||
2615 | part.ParentGroup.DetachToGround(); | ||
2616 | CachedUserInfo userInfo = | ||
2617 | CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
2618 | if (userInfo != null) | ||
2619 | { | ||
2620 | userInfo.DeleteItem(inventoryID); | ||
2621 | remoteClient.SendRemoveInventoryItem(inventoryID); | ||
2622 | } | ||
2623 | } | ||
2624 | } | ||
2625 | |||
2626 | public void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient) | ||
2627 | { | ||
2628 | ScenePresence presence; | ||
2629 | if (TryGetAvatar(remoteClient.AgentId, out presence)) | ||
2630 | { | ||
2631 | presence.Appearance.DetachAttachment(itemID); | ||
2632 | IAvatarFactory ava = RequestModuleInterface<IAvatarFactory>(); | ||
2633 | if (ava != null) | ||
2634 | { | ||
2635 | ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance); | ||
2636 | } | ||
2637 | |||
2638 | } | ||
2639 | |||
2640 | m_sceneGraph.DetachSingleAttachmentToInv(itemID, remoteClient); | ||
2641 | } | ||
2642 | |||
2643 | public void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID) | ||
2644 | { | ||
2645 | EventManager.TriggerGetScriptRunning(controllingClient, objectID, itemID); | ||
2646 | } | ||
2647 | |||
2648 | void ObjectOwner(IClientAPI remoteClient, UUID ownerID, UUID groupID, List<uint> localIDs) | ||
2649 | { | ||
2650 | if (!Permissions.IsGod(remoteClient.AgentId)) | ||
2651 | return; | ||
2652 | |||
2653 | foreach (uint localID in localIDs) | ||
2654 | { | ||
2655 | SceneObjectPart part = GetSceneObjectPart(localID); | ||
2656 | if (part != null && part.ParentGroup != null) | ||
2657 | { | ||
2658 | part.ParentGroup.SetOwnerId(ownerID); | ||
2659 | part.Inventory.ChangeInventoryOwner(ownerID); | ||
2660 | part.ParentGroup.SetGroup(groupID, remoteClient); | ||
2661 | } | ||
2662 | } | ||
2663 | } | ||
2664 | } | ||
2665 | } | ||