aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJustin Clarke Casey2008-12-04 19:57:36 +0000
committerJustin Clarke Casey2008-12-04 19:57:36 +0000
commit38ca31b37a6ac8fe74b77e4488112eb77d612827 (patch)
tree01c75a28b9f34667910f0992d8f817a5c5a1e5b3
parentMinor formatting cleanup. (diff)
downloadopensim-SC_OLD-38ca31b37a6ac8fe74b77e4488112eb77d612827.zip
opensim-SC_OLD-38ca31b37a6ac8fe74b77e4488112eb77d612827.tar.gz
opensim-SC_OLD-38ca31b37a6ac8fe74b77e4488112eb77d612827.tar.bz2
opensim-SC_OLD-38ca31b37a6ac8fe74b77e4488112eb77d612827.tar.xz
* Put in the code necessary to allow inventory transfer of whole folders (and their contents) between agents, not just single items
* However, this is not currently activated since it's not absolutely fully tested and there's a bug lurking in there to do with the sending of the BulkInventoryUpdate packets
-rw-r--r--OpenSim/Framework/Communications/Cache/CachedUserInfo.cs5
-rw-r--r--OpenSim/Framework/Communications/Cache/InventoryFolderImpl.cs4
-rw-r--r--OpenSim/Framework/IClientAPI.cs7
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs148
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs127
-rw-r--r--OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs3
-rw-r--r--OpenSim/Region/Environment/Scenes/Scene.Inventory.cs119
-rw-r--r--OpenSim/Region/Environment/Scenes/Tests/TestClient.cs5
-rw-r--r--OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs3
9 files changed, 380 insertions, 41 deletions
diff --git a/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs b/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs
index 4212fbc..b4e7bfa 100644
--- a/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs
+++ b/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs
@@ -556,8 +556,10 @@ namespace OpenSim.Framework.Communications.Cache
556 } 556 }
557 557
558 /// <summary> 558 /// <summary>
559 /// Add an item to the user's inventory 559 /// Add an item to the user's inventory.
560 /// </summary> 560 /// </summary>
561 /// If the item has no folder set (i.e. it is UUID.Zero), then it is placed in the most appropriate folder
562 /// for that type.
561 /// <param name="itemInfo"></param> 563 /// <param name="itemInfo"></param>
562 public void AddItem(InventoryItemBase item) 564 public void AddItem(InventoryItemBase item)
563 { 565 {
@@ -572,6 +574,7 @@ namespace OpenSim.Framework.Communications.Cache
572 item.Folder = RootFolder.ID; 574 item.Folder = RootFolder.ID;
573 } 575 }
574 ItemReceive(item, null); 576 ItemReceive(item, null);
577
575 if (m_commsManager.SecureInventoryService != null) 578 if (m_commsManager.SecureInventoryService != null)
576 { 579 {
577 m_commsManager.SecureInventoryService.AddItem(item, m_session_id); 580 m_commsManager.SecureInventoryService.AddItem(item, m_session_id);
diff --git a/OpenSim/Framework/Communications/Cache/InventoryFolderImpl.cs b/OpenSim/Framework/Communications/Cache/InventoryFolderImpl.cs
index 8e624f9..0704232 100644
--- a/OpenSim/Framework/Communications/Cache/InventoryFolderImpl.cs
+++ b/OpenSim/Framework/Communications/Cache/InventoryFolderImpl.cs
@@ -358,6 +358,10 @@ namespace OpenSim.Framework.Communications.Cache
358 return folderList; 358 return folderList;
359 } 359 }
360 360
361 /// <value>
362 /// The total number of items in this folder and in the immediate child folders (though not from other
363 /// descendants).
364 /// </value>
361 public int TotalCount 365 public int TotalCount
362 { 366 {
363 get 367 get
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 15a89d3..8a3c4b6 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -829,6 +829,13 @@ namespace OpenSim.Framework
829 void SendTaskInventory(UUID taskID, short serial, byte[] fileName); 829 void SendTaskInventory(UUID taskID, short serial, byte[] fileName);
830 830
831 /// <summary> 831 /// <summary>
832 /// Used by the server to inform the client of new inventory items. Will transfer the contents of the folder
833 /// (including all descendent folders) as well as the folder itself.
834 /// </summary>
835 /// <param name="folder"></param>
836 void SendBulkUpdateInventory(InventoryFolderBase folder);
837
838 /// <summary>
832 /// Used by the server to inform the client of a new inventory item. Used when transferring items 839 /// Used by the server to inform the client of a new inventory item. Used when transferring items
833 /// between avatars, possibly among other things. 840 /// between avatars, possibly among other things.
834 /// </summary> 841 /// </summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 74bf7e5..42f190f 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -1144,6 +1144,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1144 msg.MessageBlock.Message = Utils.StringToBytes(message); 1144 msg.MessageBlock.Message = Utils.StringToBytes(message);
1145 msg.MessageBlock.BinaryBucket = binaryBucket; 1145 msg.MessageBlock.BinaryBucket = binaryBucket;
1146 1146
1147 System.Console.WriteLine("SendInstantMessage: " + msg);
1147 OutPacket(msg, ThrottleOutPacketType.Task); 1148 OutPacket(msg, ThrottleOutPacketType.Task);
1148 } 1149 }
1149 } 1150 }
@@ -1763,6 +1764,153 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1763 inventoryReply.Header.Zerocoded = true; 1764 inventoryReply.Header.Zerocoded = true;
1764 OutPacket(inventoryReply, ThrottleOutPacketType.Asset); 1765 OutPacket(inventoryReply, ThrottleOutPacketType.Asset);
1765 } 1766 }
1767
1768 /// <see>IClientAPI.SendBulkUpdateInventory(InventoryFolderBase)</see>
1769 public void SendBulkUpdateInventory(InventoryFolderBase folderBase)
1770 {
1771 // XXX: Nasty temporary move that will be resolved shortly
1772 InventoryFolderImpl folder = (InventoryFolderImpl)folderBase;
1773
1774 // We will use the same transaction id for all the separate packets to be sent out in this update.
1775 UUID transactionId = UUID.Random();
1776
1777 List<BulkUpdateInventoryPacket.FolderDataBlock> folderDataBlocks
1778 = new List<BulkUpdateInventoryPacket.FolderDataBlock>();
1779
1780 SendBulkUpdateInventoryRecursive(folder, ref folderDataBlocks, transactionId);
1781
1782 if (folderDataBlocks.Count > 0)
1783 {
1784 // We'll end up with some unsent folder blocks if there were some empty folders at the end of the list
1785 // Send these now
1786 BulkUpdateInventoryPacket bulkUpdate
1787 = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory);
1788 bulkUpdate.Header.Zerocoded = true;
1789
1790 bulkUpdate.AgentData.AgentID = AgentId;
1791 bulkUpdate.AgentData.TransactionID = transactionId;
1792 bulkUpdate.FolderData = folderDataBlocks.ToArray();
1793
1794 Console.WriteLine("SendBulkUpdateInventory :" + bulkUpdate);
1795 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
1796 }
1797 }
1798
1799 /// <summary>
1800 /// Recursively construct bulk update packets to send folders and items
1801 /// </summary>
1802 /// <param name="folder"></param>
1803 /// <param name="folderDataBlocks"></param>
1804 /// <param name="transactionId"></param>
1805 private void SendBulkUpdateInventoryRecursive(
1806 InventoryFolderImpl folder, ref List<BulkUpdateInventoryPacket.FolderDataBlock> folderDataBlocks,
1807 UUID transactionId)
1808 {
1809 folderDataBlocks.Add(GenerateBulkUpdateFolderDataBlock(folder));
1810
1811 const int MAX_ITEMS_PER_PACKET = 5;
1812
1813 // If there are any items then we have to start sending them off in this packet - the next folder will have
1814 // to be in its own bulk update packet. Also, we can only fit 5 items in a packet (at least this was the limit
1815 // being used on the Linden grid at 20081203).
1816 List<InventoryItemBase> items = folder.RequestListOfItems();
1817 while (items.Count > 0)
1818 {
1819 BulkUpdateInventoryPacket bulkUpdate
1820 = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory);
1821 bulkUpdate.Header.Zerocoded = true;
1822
1823 bulkUpdate.AgentData.AgentID = AgentId;
1824 bulkUpdate.AgentData.TransactionID = transactionId;
1825 bulkUpdate.FolderData = folderDataBlocks.ToArray();
1826
1827 int itemsToSend = (items.Count > MAX_ITEMS_PER_PACKET ? MAX_ITEMS_PER_PACKET : items.Count);
1828 bulkUpdate.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[itemsToSend];
1829
1830 for (int i = 0; i < itemsToSend; i++)
1831 {
1832 // Remove from the end of the list so that we don't incur a performance penalty
1833 bulkUpdate.ItemData[i] = GenerateBulkUpdateItemDataBlock(items[items.Count - 1]);
1834 items.RemoveAt(items.Count - 1);
1835 }
1836
1837 Console.WriteLine("SendBulkUpdateInventoryRecursive :" + bulkUpdate);
1838 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
1839
1840 folderDataBlocks = new List<BulkUpdateInventoryPacket.FolderDataBlock>();
1841
1842 // If we're going to be sending another items packet then it needs to contain just the folder to which those
1843 // items belong.
1844 if (items.Count > 0)
1845 folderDataBlocks.Add(GenerateBulkUpdateFolderDataBlock(folder));
1846 }
1847
1848 List<InventoryFolderImpl> subFolders = folder.RequestListOfFolderImpls();
1849 foreach (InventoryFolderImpl subFolder in subFolders)
1850 {
1851 SendBulkUpdateInventoryRecursive(subFolder, ref folderDataBlocks, transactionId);
1852 }
1853 }
1854
1855 /// <summary>
1856 /// Generate a bulk update inventory data block for the given folder
1857 /// </summary>
1858 /// <param name="folder"></param>
1859 /// <returns></returns>
1860 private BulkUpdateInventoryPacket.FolderDataBlock GenerateBulkUpdateFolderDataBlock(InventoryFolderBase folder)
1861 {
1862 BulkUpdateInventoryPacket.FolderDataBlock folderBlock = new BulkUpdateInventoryPacket.FolderDataBlock();
1863
1864 folderBlock.FolderID = folder.ID;
1865 folderBlock.ParentID = folder.ParentID;
1866 folderBlock.Type = -1;
1867 folderBlock.Name = Utils.StringToBytes(folder.Name);
1868
1869 return folderBlock;
1870 }
1871
1872 /// <summary>
1873 /// Generate a bulk update inventory data block for the given item
1874 /// </summary>
1875 /// <param name="item"></param>
1876 /// <returns></returns>
1877 private BulkUpdateInventoryPacket.ItemDataBlock GenerateBulkUpdateItemDataBlock(InventoryItemBase item)
1878 {
1879 BulkUpdateInventoryPacket.ItemDataBlock itemBlock = new BulkUpdateInventoryPacket.ItemDataBlock();
1880
1881 itemBlock.ItemID = item.ID;
1882 itemBlock.AssetID = item.AssetID;
1883 itemBlock.CreatorID = item.Creator;
1884 itemBlock.BaseMask = item.BasePermissions;
1885 itemBlock.Description = Utils.StringToBytes(item.Description);
1886 itemBlock.EveryoneMask = item.EveryOnePermissions;
1887 itemBlock.FolderID = item.Folder;
1888 itemBlock.InvType = (sbyte)item.InvType;
1889 itemBlock.Name = Utils.StringToBytes(item.Name);
1890 itemBlock.NextOwnerMask = item.NextPermissions;
1891 itemBlock.OwnerID = item.Owner;
1892 itemBlock.OwnerMask = item.CurrentPermissions;
1893 itemBlock.Type = (sbyte)item.AssetType;
1894 itemBlock.GroupID = item.GroupID;
1895 itemBlock.GroupOwned = item.GroupOwned;
1896 itemBlock.GroupMask = item.GroupPermissions;
1897 itemBlock.Flags = item.Flags;
1898 itemBlock.SalePrice = item.SalePrice;
1899 itemBlock.SaleType = item.SaleType;
1900 itemBlock.CreationDate = item.CreationDate;
1901
1902 itemBlock.CRC =
1903 Helpers.InventoryCRC(
1904 1000, 0, itemBlock.InvType,
1905 itemBlock.Type, itemBlock.AssetID,
1906 itemBlock.GroupID, 100,
1907 itemBlock.OwnerID, itemBlock.CreatorID,
1908 itemBlock.ItemID, itemBlock.FolderID,
1909 (uint)PermissionMask.All, 1, (uint)PermissionMask.All, (uint)PermissionMask.All,
1910 (uint)PermissionMask.All);
1911
1912 return itemBlock;
1913 }
1766 1914
1767 /// <see>IClientAPI.SendBulkUpdateInventory(InventoryItemBase)</see> 1915 /// <see>IClientAPI.SendBulkUpdateInventory(InventoryItemBase)</see>
1768 public void SendBulkUpdateInventory(InventoryItemBase item) 1916 public void SendBulkUpdateInventory(InventoryItemBase item)
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index 73f1761..b41c36f 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -136,42 +136,85 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer
136 136
137 if (im.dialog == (byte) InstantMessageDialog.InventoryOffered) 137 if (im.dialog == (byte) InstantMessageDialog.InventoryOffered)
138 { 138 {
139 ScenePresence user = 139 m_log.DebugFormat("Asset type {0}", ((AssetType)im.binaryBucket[0]));
140 scene.GetScenePresence(new UUID(im.toAgentID)); 140
141 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
142 UUID copyID;
141 143
142 // First byte of the array is probably the item type 144 // First byte is the asset type
143 // Next 16 bytes are the UUID 145 AssetType assetType = (AssetType)im.binaryBucket[0];
146
147 // Temporarily disabled pending test of complex transfers (folders within folders, lots of items,
148 // empty folders, etc.)
149 if (AssetType.Folder == assetType)
150 return;
151
152 if (AssetType.Folder == assetType)
153 {
154 UUID folderID = new UUID(im.binaryBucket, 1);
155
156 m_log.DebugFormat("[AGENT INVENTORY]: Inserting original folder {0} "+
157 "into agent {1}'s inventory",
158 folderID, new UUID(im.toAgentID));
159
160 InventoryFolderImpl folderCopy
161 = scene.GiveInventoryFolder(new UUID(im.toAgentID), client.AgentId, folderID, UUID.Zero);
162
163 if (folderCopy == null)
164 {
165 client.SendAgentAlertMessage("Can't find folder to give. Nothing given.", false);
166 return;
167 }
168
169 // The outgoing binary bucket should contain only the byte which signals an asset folder is
170 // being copied and the following bytes for the copied folder's UUID
171 copyID = folderCopy.ID;
172 byte[] copyIDBytes = copyID.GetBytes();
173 im.binaryBucket = new byte[1 + copyIDBytes.Length];
174 im.binaryBucket[0] = (byte)AssetType.Folder;
175 Array.Copy(copyIDBytes, 0, im.binaryBucket, 1, copyIDBytes.Length);
176
177 if (user != null && !user.IsChildAgent)
178 {
179 user.ControllingClient.SendBulkUpdateInventory(folderCopy);
180 }
181 }
182 else
183 {
184 // First byte of the array is probably the item type
185 // Next 16 bytes are the UUID
144 186
145 UUID itemID = new UUID(im.binaryBucket, 1); 187 UUID itemID = new UUID(im.binaryBucket, 1);
146 188
147 m_log.DebugFormat("[AGENT INVENTORY]: Inserting item {0} "+ 189 m_log.DebugFormat("[AGENT INVENTORY]: Inserting item {0} "+
148 "into agent {1}'s inventory", 190 "into agent {1}'s inventory",
149 itemID, new UUID(im.toAgentID)); 191 itemID, new UUID(im.toAgentID));
150 192
151 InventoryItemBase itemCopy = scene.GiveInventoryItem( 193 InventoryItemBase itemCopy = scene.GiveInventoryItem(
152 new UUID(im.toAgentID), 194 new UUID(im.toAgentID),
153 client.AgentId, itemID); 195 client.AgentId, itemID);
154 196
155 if (itemCopy == null) 197 if (itemCopy == null)
156 { 198 {
157 client.SendAgentAlertMessage("Can't find item to give. Nothing given.", false); 199 client.SendAgentAlertMessage("Can't find item to give. Nothing given.", false);
158 return; 200 return;
201 }
202
203 copyID = itemCopy.ID;
204 Array.Copy(copyID.GetBytes(), 0, im.binaryBucket, 1, 16);
205
206 if (user != null && !user.IsChildAgent)
207 {
208 user.ControllingClient.SendBulkUpdateInventory(itemCopy);
209 }
159 } 210 }
160 211
161 byte[] itemCopyID = itemCopy.ID.GetBytes();
162
163 Array.Copy(itemCopyID, 0, im.binaryBucket, 1, 16);
164
165 // Send the IM to the recipient. The item is already 212 // Send the IM to the recipient. The item is already
166 // in their inventory, so it will not be lost if 213 // in their inventory, so it will not be lost if
167 // they are offline. 214 // they are offline.
168 // 215 //
169 if (user != null && !user.IsChildAgent) 216 if (user != null && !user.IsChildAgent)
170 { 217 {
171 // User is online. So, let's make the item visible
172 //
173 user.ControllingClient.SendBulkUpdateInventory(itemCopy);
174
175 // And notify. Transaction ID is the item ID. We get that 218 // And notify. Transaction ID is the item ID. We get that
176 // same ID back on the reply so we know what to act on 219 // same ID back on the reply so we know what to act on
177 // 220 //
@@ -179,7 +222,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer
179 new UUID(im.fromAgentID), im.message, 222 new UUID(im.fromAgentID), im.message,
180 new UUID(im.toAgentID), 223 new UUID(im.toAgentID),
181 im.fromAgentName, im.dialog, im.timestamp, 224 im.fromAgentName, im.dialog, im.timestamp,
182 itemCopy.ID, false, im.binaryBucket); 225 copyID, false, im.binaryBucket);
183 226
184 return; 227 return;
185 } 228 }
@@ -208,9 +251,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer
208 } 251 }
209 } 252 }
210 else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined) 253 else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
211 { 254 {
212 UUID itemID = new UUID(im.imSessionID); // The item, back from it's trip
213
214 // Here, the recipient is local and we can assume that the 255 // Here, the recipient is local and we can assume that the
215 // inventory is loaded. Courtesy of the above bulk update, 256 // inventory is loaded. Courtesy of the above bulk update,
216 // It will have been pushed to the client, too 257 // It will have been pushed to the client, too
@@ -224,27 +265,43 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer
224 { 265 {
225 InventoryFolderImpl trashFolder = 266 InventoryFolderImpl trashFolder =
226 userInfo.FindFolderForType((int)AssetType.TrashFolder); 267 userInfo.FindFolderForType((int)AssetType.TrashFolder);
227 268
228 InventoryItemBase item = 269 UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
229 userInfo.RootFolder.FindItem(itemID); 270
230 271 InventoryItemBase item = userInfo.RootFolder.FindItem(inventoryEntityID);
231 if (trashFolder != null && item != null) 272 InventoryFolderBase folder = null;
273
274 if (item != null && trashFolder != null)
232 { 275 {
233 item.Folder = trashFolder.ID; 276 item.Folder = trashFolder.ID;
234 277
235 userInfo.DeleteItem(itemID); 278 userInfo.DeleteItem(inventoryEntityID);
236 279
237 scene.AddInventoryItem(client, item); 280 scene.AddInventoryItem(client, item);
238 } 281 }
239 else 282 else
240 { 283 {
241 string reason = ""; 284 folder = userInfo.RootFolder.FindFolder(inventoryEntityID);
285
286 if (folder != null & trashFolder != null)
287 {
288 userInfo.MoveFolder(inventoryEntityID, trashFolder.ID);
289 }
290 }
291
292 if ((null == item && null == folder) | null == trashFolder)
293 {
294 string reason = String.Empty;
295
242 if (trashFolder == null) 296 if (trashFolder == null)
243 reason += " Trash folder not found."; 297 reason += " Trash folder not found.";
244 if (item == null) 298 if (item == null)
245 reason += " Item not found."; 299 reason += " Item not found.";
300 if (folder == null)
301 reason += " Folder not found.";
302
246 client.SendAgentAlertMessage("Unable to delete "+ 303 client.SendAgentAlertMessage("Unable to delete "+
247 "received item" + reason, false); 304 "received inventory" + reason, false);
248 } 305 }
249 } 306 }
250 307
diff --git a/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs b/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs
index b5a5123..fb1d1ff 100644
--- a/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs
@@ -624,6 +624,9 @@ namespace OpenSim.Region.Environment.Modules.World.NPC
624 public virtual void SendBulkUpdateInventory(InventoryItemBase item) 624 public virtual void SendBulkUpdateInventory(InventoryItemBase item)
625 { 625 {
626 } 626 }
627
628 public virtual void SendBulkUpdateInventory(InventoryFolderBase folderBase)
629 {}
627 630
628 public void SendTakeControls(int controls, bool passToAgent, bool TakeControls) 631 public void SendTakeControls(int controls, bool passToAgent, bool TakeControls)
629 { 632 {
diff --git a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs
index d1e0c24..3d6a905 100644
--- a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs
@@ -400,11 +400,11 @@ namespace OpenSim.Region.Environment.Scenes
400 } 400 }
401 401
402 /// <summary> 402 /// <summary>
403 /// Give an inventory item from one avatar to another 403 /// Give an inventory item from one user to another
404 /// </summary> 404 /// </summary>
405 /// <param name="recipientClient"></param> 405 /// <param name="recipientClient"></param>
406 /// <param name="senderId">ID of the sender of the item</param> 406 /// <param name="senderId">ID of the sender of the item</param>
407 /// <param name="itemId"></param> 407 /// <param name="itemId"></param>
408 public virtual void GiveInventoryItem(IClientAPI recipientClient, UUID senderId, UUID itemId) 408 public virtual void GiveInventoryItem(IClientAPI recipientClient, UUID senderId, UUID itemId)
409 { 409 {
410 InventoryItemBase itemCopy = GiveInventoryItem(recipientClient.AgentId, senderId, itemId); 410 InventoryItemBase itemCopy = GiveInventoryItem(recipientClient.AgentId, senderId, itemId);
@@ -413,8 +413,34 @@ namespace OpenSim.Region.Environment.Scenes
413 recipientClient.SendBulkUpdateInventory(itemCopy); 413 recipientClient.SendBulkUpdateInventory(itemCopy);
414 } 414 }
415 415
416 /// <summary>
417 /// Give an inventory item from one user to another
418 /// </summary>
419 /// <param name="recipient"></param>
420 /// <param name="senderId">ID of the sender of the item</param>
421 /// <param name="itemId"></param>
422 /// <returns>The inventory item copy given, null if the give was unsuccessful</returns>
416 public virtual InventoryItemBase GiveInventoryItem(UUID recipient, UUID senderId, UUID itemId) 423 public virtual InventoryItemBase GiveInventoryItem(UUID recipient, UUID senderId, UUID itemId)
417 { 424 {
425 return GiveInventoryItem(recipient, senderId, itemId, UUID.Zero);
426 }
427
428 /// <summary>
429 /// Give an inventory item from one user to another
430 /// </summary>
431 /// <param name="recipient"></param>
432 /// <param name="senderId">ID of the sender of the item</param>
433 /// <param name="itemId"></param>
434 /// <param name="recipientFolderId">
435 /// The id of the folder in which the copy item should go. If UUID.Zero then the item is placed in the most
436 /// appropriate default folder.
437 /// </param>
438 /// <returns>
439 /// The inventory item copy given, null if the give was unsuccessful
440 /// </returns>
441 public virtual InventoryItemBase GiveInventoryItem(
442 UUID recipient, UUID senderId, UUID itemId, UUID recipientFolderId)
443 {
418 // Retrieve the item from the sender 444 // Retrieve the item from the sender
419 CachedUserInfo senderUserInfo = CommsManager.UserProfileCacheService.GetUserDetails(senderId); 445 CachedUserInfo senderUserInfo = CommsManager.UserProfileCacheService.GetUserDetails(senderId);
420 446
@@ -438,7 +464,6 @@ namespace OpenSim.Region.Environment.Scenes
438 return null; 464 return null;
439 } 465 }
440 466
441 // TODO get recipient's root folder
442 CachedUserInfo recipientUserInfo 467 CachedUserInfo recipientUserInfo
443 = CommsManager.UserProfileCacheService.GetUserDetails(recipient); 468 = CommsManager.UserProfileCacheService.GetUserDetails(recipient);
444 469
@@ -457,7 +482,8 @@ namespace OpenSim.Region.Environment.Scenes
457 itemCopy.Name = item.Name; 482 itemCopy.Name = item.Name;
458 itemCopy.AssetType = item.AssetType; 483 itemCopy.AssetType = item.AssetType;
459 itemCopy.InvType = item.InvType; 484 itemCopy.InvType = item.InvType;
460 itemCopy.Folder = UUID.Zero; 485 itemCopy.Folder = recipientFolderId;
486
461 if (Permissions.PropagatePermissions()) 487 if (Permissions.PropagatePermissions())
462 { 488 {
463 if (item.InvType == 6) 489 if (item.InvType == 6)
@@ -529,8 +555,93 @@ namespace OpenSim.Region.Environment.Scenes
529 m_log.Error("[AGENT INVENTORY]: Failed to find item " + itemId.ToString() + ", no root folder"); 555 m_log.Error("[AGENT INVENTORY]: Failed to find item " + itemId.ToString() + ", no root folder");
530 return null; 556 return null;
531 } 557 }
558
532 return null; 559 return null;
533 } 560 }
561
562 /// <summary>
563 /// Give an entire inventory folder from one user to another. The entire contents (including all descendent
564 /// folders) is given.
565 /// </summary>
566 /// <param name="recipientId"></param>
567 /// <param name="senderId">ID of the sender of the item</param>
568 /// <param name="folderId"></param>
569 /// <param name="recipientParentFolderId">
570 /// The id of the receipient folder in which the send folder should be placed. If UUID.Zero then the
571 /// recipient folder is the root folder
572 /// </param>
573 /// <returns>
574 /// The inventory folder copy given, null if the copy was unsuccessful
575 /// </returns>
576 public virtual InventoryFolderImpl GiveInventoryFolder(
577 UUID recipientId, UUID senderId, UUID folderId, UUID recipientParentFolderId)
578 {
579 // Retrieve the folder from the sender
580 CachedUserInfo senderUserInfo = CommsManager.UserProfileCacheService.GetUserDetails(senderId);
581
582 if (null == senderUserInfo)
583 {
584 m_log.ErrorFormat(
585 "[AGENT INVENTORY]: Failed to find sending user {0} for folder {1}", senderId, folderId);
586
587 return null;
588 }
589
590 if (!senderUserInfo.HasReceivedInventory)
591 {
592 m_log.DebugFormat(
593 "[AGENT INVENTORY]: Could not give inventory folder - have not yet received inventory for {0}",
594 senderId);
595
596 return null;
597 }
598
599 InventoryFolderImpl folder = senderUserInfo.RootFolder.FindFolder(folderId);
600
601 if (null == folder)
602 {
603 m_log.ErrorFormat(
604 "[AGENT INVENTORY]: Could not find inventory folder {0} to give", folderId);
605
606 return null;
607 }
608
609 CachedUserInfo recipientUserInfo
610 = CommsManager.UserProfileCacheService.GetUserDetails(recipientId);
611
612 if (null == recipientUserInfo)
613 {
614 m_log.ErrorFormat(
615 "[AGENT INVENTORY]: Failed to find receiving user {0} for folder {1}", recipientId, folderId);
616
617 return null;
618 }
619
620 if (recipientParentFolderId == UUID.Zero)
621 recipientParentFolderId = recipientUserInfo.RootFolder.ID;
622
623 UUID newFolderId = UUID.Random();
624 recipientUserInfo.CreateFolder(folder.Name, newFolderId, (ushort)folder.Type, recipientParentFolderId);
625
626 // XXX: Messy - we should really get this back in the CreateFolder call
627 InventoryFolderImpl copiedFolder = recipientUserInfo.RootFolder.FindFolder(newFolderId);
628
629 // Give all the subfolders
630 List<InventoryFolderImpl> subFolders = folder.RequestListOfFolderImpls();
631 foreach (InventoryFolderImpl childFolder in subFolders)
632 {
633 GiveInventoryFolder(recipientId, senderId, childFolder.ID, copiedFolder.ID);
634 }
635
636 // Give all the items
637 List<InventoryItemBase> items = folder.RequestListOfItems();
638 foreach (InventoryItemBase item in items)
639 {
640 GiveInventoryItem(recipientId, senderId, item.ID, copiedFolder.ID);
641 }
642
643 return copiedFolder;
644 }
534 645
535 public void CopyInventoryItem(IClientAPI remoteClient, uint callbackID, UUID oldAgentID, UUID oldItemID, 646 public void CopyInventoryItem(IClientAPI remoteClient, uint callbackID, UUID oldAgentID, UUID oldItemID,
536 UUID newFolderID, string newName) 647 UUID newFolderID, string newName)
diff --git a/OpenSim/Region/Environment/Scenes/Tests/TestClient.cs b/OpenSim/Region/Environment/Scenes/Tests/TestClient.cs
index 69e45bb..cecb115 100644
--- a/OpenSim/Region/Environment/Scenes/Tests/TestClient.cs
+++ b/OpenSim/Region/Environment/Scenes/Tests/TestClient.cs
@@ -538,6 +538,9 @@ namespace OpenSim.Region.Environment.Scenes.Tests
538 public virtual void SendBulkUpdateInventory(InventoryItemBase item) 538 public virtual void SendBulkUpdateInventory(InventoryItemBase item)
539 { 539 {
540 } 540 }
541
542 public void SendBulkUpdateInventory(InventoryFolderBase folderBase)
543 {}
541 544
542 public UUID GetDefaultAnimation(string name) 545 public UUID GetDefaultAnimation(string name)
543 { 546 {
@@ -561,8 +564,8 @@ namespace OpenSim.Region.Environment.Scenes.Tests
561 int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay, 564 int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay,
562 int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent) 565 int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent)
563 { 566 {
564
565 } 567 }
568
566 public virtual void SendNameReply(UUID profileId, string firstname, string lastname) 569 public virtual void SendNameReply(UUID profileId, string firstname, string lastname)
567 { 570 {
568 } 571 }
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index 89b3bf6..f1a61bb 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -537,6 +537,9 @@ namespace OpenSim.Region.Examples.SimpleModule
537 public virtual void SendBulkUpdateInventory(InventoryItemBase item) 537 public virtual void SendBulkUpdateInventory(InventoryItemBase item)
538 { 538 {
539 } 539 }
540
541 public void SendBulkUpdateInventory(InventoryFolderBase folderBase)
542 {}
540 543
541 public UUID GetDefaultAnimation(string name) 544 public UUID GetDefaultAnimation(string name)
542 { 545 {