From 38ca31b37a6ac8fe74b77e4488112eb77d612827 Mon Sep 17 00:00:00 2001 From: Justin Clarke Casey Date: Thu, 4 Dec 2008 19:57:36 +0000 Subject: * 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 --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 148 +++++++++++++++++++++ 1 file changed, 148 insertions(+) (limited to 'OpenSim/Region/ClientStack') 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 msg.MessageBlock.Message = Utils.StringToBytes(message); msg.MessageBlock.BinaryBucket = binaryBucket; + System.Console.WriteLine("SendInstantMessage: " + msg); OutPacket(msg, ThrottleOutPacketType.Task); } } @@ -1763,6 +1764,153 @@ namespace OpenSim.Region.ClientStack.LindenUDP inventoryReply.Header.Zerocoded = true; OutPacket(inventoryReply, ThrottleOutPacketType.Asset); } + + /// IClientAPI.SendBulkUpdateInventory(InventoryFolderBase) + public void SendBulkUpdateInventory(InventoryFolderBase folderBase) + { + // XXX: Nasty temporary move that will be resolved shortly + InventoryFolderImpl folder = (InventoryFolderImpl)folderBase; + + // We will use the same transaction id for all the separate packets to be sent out in this update. + UUID transactionId = UUID.Random(); + + List folderDataBlocks + = new List(); + + SendBulkUpdateInventoryRecursive(folder, ref folderDataBlocks, transactionId); + + if (folderDataBlocks.Count > 0) + { + // We'll end up with some unsent folder blocks if there were some empty folders at the end of the list + // Send these now + BulkUpdateInventoryPacket bulkUpdate + = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory); + bulkUpdate.Header.Zerocoded = true; + + bulkUpdate.AgentData.AgentID = AgentId; + bulkUpdate.AgentData.TransactionID = transactionId; + bulkUpdate.FolderData = folderDataBlocks.ToArray(); + + Console.WriteLine("SendBulkUpdateInventory :" + bulkUpdate); + OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); + } + } + + /// + /// Recursively construct bulk update packets to send folders and items + /// + /// + /// + /// + private void SendBulkUpdateInventoryRecursive( + InventoryFolderImpl folder, ref List folderDataBlocks, + UUID transactionId) + { + folderDataBlocks.Add(GenerateBulkUpdateFolderDataBlock(folder)); + + const int MAX_ITEMS_PER_PACKET = 5; + + // If there are any items then we have to start sending them off in this packet - the next folder will have + // to be in its own bulk update packet. Also, we can only fit 5 items in a packet (at least this was the limit + // being used on the Linden grid at 20081203). + List items = folder.RequestListOfItems(); + while (items.Count > 0) + { + BulkUpdateInventoryPacket bulkUpdate + = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory); + bulkUpdate.Header.Zerocoded = true; + + bulkUpdate.AgentData.AgentID = AgentId; + bulkUpdate.AgentData.TransactionID = transactionId; + bulkUpdate.FolderData = folderDataBlocks.ToArray(); + + int itemsToSend = (items.Count > MAX_ITEMS_PER_PACKET ? MAX_ITEMS_PER_PACKET : items.Count); + bulkUpdate.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[itemsToSend]; + + for (int i = 0; i < itemsToSend; i++) + { + // Remove from the end of the list so that we don't incur a performance penalty + bulkUpdate.ItemData[i] = GenerateBulkUpdateItemDataBlock(items[items.Count - 1]); + items.RemoveAt(items.Count - 1); + } + + Console.WriteLine("SendBulkUpdateInventoryRecursive :" + bulkUpdate); + OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); + + folderDataBlocks = new List(); + + // If we're going to be sending another items packet then it needs to contain just the folder to which those + // items belong. + if (items.Count > 0) + folderDataBlocks.Add(GenerateBulkUpdateFolderDataBlock(folder)); + } + + List subFolders = folder.RequestListOfFolderImpls(); + foreach (InventoryFolderImpl subFolder in subFolders) + { + SendBulkUpdateInventoryRecursive(subFolder, ref folderDataBlocks, transactionId); + } + } + + /// + /// Generate a bulk update inventory data block for the given folder + /// + /// + /// + private BulkUpdateInventoryPacket.FolderDataBlock GenerateBulkUpdateFolderDataBlock(InventoryFolderBase folder) + { + BulkUpdateInventoryPacket.FolderDataBlock folderBlock = new BulkUpdateInventoryPacket.FolderDataBlock(); + + folderBlock.FolderID = folder.ID; + folderBlock.ParentID = folder.ParentID; + folderBlock.Type = -1; + folderBlock.Name = Utils.StringToBytes(folder.Name); + + return folderBlock; + } + + /// + /// Generate a bulk update inventory data block for the given item + /// + /// + /// + private BulkUpdateInventoryPacket.ItemDataBlock GenerateBulkUpdateItemDataBlock(InventoryItemBase item) + { + BulkUpdateInventoryPacket.ItemDataBlock itemBlock = new BulkUpdateInventoryPacket.ItemDataBlock(); + + itemBlock.ItemID = item.ID; + itemBlock.AssetID = item.AssetID; + itemBlock.CreatorID = item.Creator; + itemBlock.BaseMask = item.BasePermissions; + itemBlock.Description = Utils.StringToBytes(item.Description); + itemBlock.EveryoneMask = item.EveryOnePermissions; + itemBlock.FolderID = item.Folder; + itemBlock.InvType = (sbyte)item.InvType; + itemBlock.Name = Utils.StringToBytes(item.Name); + itemBlock.NextOwnerMask = item.NextPermissions; + itemBlock.OwnerID = item.Owner; + itemBlock.OwnerMask = item.CurrentPermissions; + itemBlock.Type = (sbyte)item.AssetType; + itemBlock.GroupID = item.GroupID; + itemBlock.GroupOwned = item.GroupOwned; + itemBlock.GroupMask = item.GroupPermissions; + itemBlock.Flags = item.Flags; + itemBlock.SalePrice = item.SalePrice; + itemBlock.SaleType = item.SaleType; + itemBlock.CreationDate = item.CreationDate; + + itemBlock.CRC = + Helpers.InventoryCRC( + 1000, 0, itemBlock.InvType, + itemBlock.Type, itemBlock.AssetID, + itemBlock.GroupID, 100, + itemBlock.OwnerID, itemBlock.CreatorID, + itemBlock.ItemID, itemBlock.FolderID, + (uint)PermissionMask.All, 1, (uint)PermissionMask.All, (uint)PermissionMask.All, + (uint)PermissionMask.All); + + return itemBlock; + } /// IClientAPI.SendBulkUpdateInventory(InventoryItemBase) public void SendBulkUpdateInventory(InventoryItemBase item) -- cgit v1.1