aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
diff options
context:
space:
mode:
authorDr Scofield2009-02-06 16:55:34 +0000
committerDr Scofield2009-02-06 16:55:34 +0000
commit9b66108081a8c8cf79faaa6c541554091c40850e (patch)
tree095a232ae5a9de3a9244bcd34da08294f61eeea5 /OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
parent* removed superfluous constants class (diff)
downloadopensim-SC-9b66108081a8c8cf79faaa6c541554091c40850e.zip
opensim-SC-9b66108081a8c8cf79faaa6c541554091c40850e.tar.gz
opensim-SC-9b66108081a8c8cf79faaa6c541554091c40850e.tar.bz2
opensim-SC-9b66108081a8c8cf79faaa6c541554091c40850e.tar.xz
This changeset is the step 1 of 2 in refactoring
OpenSim.Region.Environment into a "framework" part and a modules only part. This first changeset refactors OpenSim.Region.Environment.Scenes, OpenSim.Region.Environment.Interfaces, and OpenSim.Region.Interfaces into OpenSim.Region.Framework.{Interfaces,Scenes} leaving only region modules in OpenSim.Region.Environment. The next step will be to move region modules up from OpenSim.Region.Environment.Modules to OpenSim.Region.CoreModules and then sort out which modules are really core modules and which should move out to forge. I've been very careful to NOT BREAK anything. i hope i've succeeded. as this is the work of a whole week i hope i managed to keep track with the applied patches of the last week --- could any of you that did check in stuff have a look at whether it survived? thx!
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Scene.Inventory.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs2665
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
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text;
32using System.Timers;
33using OpenMetaverse;
34using log4net;
35using OpenSim.Framework;
36using OpenSim.Framework.Communications.Cache;
37using OpenSim.Region.Framework;
38using OpenSim.Region.Framework.Interfaces;
39
40namespace 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}