diff --git a/OpenMetaverse/Login.cs b/OpenMetaverse/Login.cs index e629207e..3434f66a 100644 --- a/OpenMetaverse/Login.cs +++ b/OpenMetaverse/Login.cs @@ -272,7 +272,15 @@ namespace OpenMetaverse // inventory-skeleton WriteXmlRpcArrayStart(writer, "inventory-skeleton"); - WriteXmlRpcInventoryItem(writer, "Inventory", UUID.Zero, 1, (uint)InventoryType.Category, InventoryRoot); + if (InventorySkeleton != null) + { + foreach (InventoryFolder folder in InventorySkeleton) + WriteXmlRpcInventoryItem(writer, folder.Name, folder.ParentUUID, (uint)folder.Version, (uint)folder.PreferredType, folder.UUID); + } + else + { + WriteXmlRpcInventoryItem(writer, "Inventory", UUID.Zero, 1, (uint)InventoryType.Category, InventoryRoot); + } WriteXmlRpcArrayEnd(writer); // buddy-list diff --git a/Programs/Simian/Extensions/AuthFreeForAll.cs b/Programs/Simian/Extensions/AuthFreeForAll.cs index e7dca96e..f2cf1585 100644 --- a/Programs/Simian/Extensions/AuthFreeForAll.cs +++ b/Programs/Simian/Extensions/AuthFreeForAll.cs @@ -47,9 +47,9 @@ namespace Simian.Extensions // Create a very basic inventory skeleton UUID rootFolder = UUID.Random(); - server.Inventory.CreateRootFolder(agent, rootFolder, "Inventory", agent.AgentID); + server.Inventory.CreateRootFolder(agent.AgentID, rootFolder, "Inventory", agent.AgentID); UUID libraryRootFolder = UUID.Random(); - server.Inventory.CreateRootFolder(agent, libraryRootFolder, "Library", agent.AgentID); + server.Inventory.CreateRootFolder(agent.AgentID, libraryRootFolder, "Library", agent.AgentID); agent.InventoryRoot = rootFolder; agent.InventoryLibraryOwner = agent.AgentID; @@ -57,30 +57,30 @@ namespace Simian.Extensions // Create some inventory items for appearance UUID clothingFolder = UUID.Random(); - server.Inventory.CreateFolder(agent, clothingFolder, "Clothing", AssetType.Clothing, + server.Inventory.CreateFolder(agent.AgentID, clothingFolder, "Clothing", AssetType.Clothing, UUID.Zero, agent.AgentID); UUID defaultOutfitFolder = UUID.Random(); - server.Inventory.CreateFolder(agent, defaultOutfitFolder, "Default Outfit", AssetType.Unknown, + server.Inventory.CreateFolder(agent.AgentID, defaultOutfitFolder, "Default Outfit", AssetType.Unknown, clothingFolder, agent.AgentID); UUID hairAsset = new UUID("dc675529-7ba5-4976-b91d-dcb9e5e36188"); - UUID hairItem = server.Inventory.CreateItem(agent, "Default Hair", "Default Hair", + UUID hairItem = server.Inventory.CreateItem(agent.AgentID, "Default Hair", "Default Hair", InventoryType.Wearable, AssetType.Bodypart, hairAsset, defaultOutfitFolder, PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0); UUID pantsAsset = new UUID("3e8ee2d6-4f21-4a55-832d-77daa505edff"); - UUID pantsItem = server.Inventory.CreateItem(agent, "Default Pants", "Default Pants", + UUID pantsItem = server.Inventory.CreateItem(agent.AgentID, "Default Pants", "Default Pants", InventoryType.Wearable, AssetType.Clothing, pantsAsset, defaultOutfitFolder, PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0); UUID shapeAsset = new UUID("530a2614-052e-49a2-af0e-534bb3c05af0"); - UUID shapeItem = server.Inventory.CreateItem(agent, "Default Shape", "Default Shape", + UUID shapeItem = server.Inventory.CreateItem(agent.AgentID, "Default Shape", "Default Shape", InventoryType.Wearable, AssetType.Clothing, shapeAsset, defaultOutfitFolder, PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0); UUID shirtAsset = new UUID("6a714f37-fe53-4230-b46f-8db384465981"); - UUID shirtItem = server.Inventory.CreateItem(agent, "Default Shirt", "Default Shirt", + UUID shirtItem = server.Inventory.CreateItem(agent.AgentID, "Default Shirt", "Default Shirt", InventoryType.Wearable, AssetType.Clothing, shirtAsset, defaultOutfitFolder, PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0); UUID skinAsset = new UUID("5f787f25-f761-4a35-9764-6418ee4774c4"); - UUID skinItem = server.Inventory.CreateItem(agent, "Default Skin", "Default Skin", + UUID skinItem = server.Inventory.CreateItem(agent.AgentID, "Default Skin", "Default Skin", InventoryType.Wearable, AssetType.Clothing, skinAsset, defaultOutfitFolder, PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0); diff --git a/Programs/Simian/Extensions/InventoryManager.cs b/Programs/Simian/Extensions/InventoryManager.cs index a11f8527..2456f55d 100644 --- a/Programs/Simian/Extensions/InventoryManager.cs +++ b/Programs/Simian/Extensions/InventoryManager.cs @@ -70,8 +70,11 @@ namespace Simian.Extensions break; } + if (parentID == UUID.Zero) + parentID = agent.InventoryRoot; + // Create the inventory item - CreateItem(agent, Utils.BytesToString(create.InventoryBlock.Name), "Created in Simian", + CreateItem(agent.AgentID, Utils.BytesToString(create.InventoryBlock.Name), "Created in Simian", (InventoryType)create.InventoryBlock.InvType, assetType, assetID, parentID, PermissionMask.All, (PermissionMask)create.InventoryBlock.NextOwnerMask, agent.AgentID, agent.AgentID, create.InventoryBlock.TransactionID, create.InventoryBlock.CallbackID); @@ -81,7 +84,11 @@ namespace Simian.Extensions { CreateInventoryFolderPacket create = (CreateInventoryFolderPacket)packet; - CreateFolder(agent, create.FolderData.FolderID, Utils.BytesToString(create.FolderData.Name), + UUID folderID = create.FolderData.FolderID; + if (folderID == UUID.Zero) + folderID = agent.InventoryRoot; + + CreateFolder(agent.AgentID, folderID, Utils.BytesToString(create.FolderData.Name), (AssetType)create.FolderData.Type, create.FolderData.ParentID, agent.AgentID); } @@ -302,9 +309,9 @@ namespace Simian.Extensions Server.UDP.SendPacket(agent.AgentID, reply, PacketCategory.Inventory); } - public bool CreateRootFolder(Agent agent, UUID folderID, string name, UUID ownerID) + public bool CreateRootFolder(UUID agentID, UUID folderID, string name, UUID ownerID) { - Dictionary agentInventory = GetAgentInventory(agent.AgentID); + Dictionary agentInventory = GetAgentInventory(agentID); lock (agentInventory) { @@ -312,7 +319,7 @@ namespace Simian.Extensions { InventoryFolder folder = new InventoryFolder(); folder.Name = name; - folder.OwnerID = agent.AgentID; + folder.OwnerID = agentID; folder.ParentID = UUID.Zero; folder.Parent = null; folder.PreferredType = AssetType.Folder; @@ -335,13 +342,10 @@ namespace Simian.Extensions return false; } - public bool CreateFolder(Agent agent, UUID folderID, string name, AssetType preferredType, + public bool CreateFolder(UUID agentID, UUID folderID, string name, AssetType preferredType, UUID parentID, UUID ownerID) { - if (parentID == UUID.Zero) - parentID = agent.InventoryRoot; - - Dictionary agentInventory = GetAgentInventory(agent.AgentID); + Dictionary agentInventory = GetAgentInventory(agentID); lock (agentInventory) { @@ -354,7 +358,7 @@ namespace Simian.Extensions { InventoryFolder folder = new InventoryFolder(); folder.Name = name; - folder.OwnerID = agent.AgentID; + folder.OwnerID = agentID; folder.ParentID = parentID; folder.Parent = parentFolder; folder.PreferredType = preferredType; @@ -387,14 +391,11 @@ namespace Simian.Extensions return false; } - public UUID CreateItem(Agent agent, string name, string description, InventoryType invType, AssetType type, + public UUID CreateItem(UUID agentID, string name, string description, InventoryType invType, AssetType type, UUID assetID, UUID parentID, PermissionMask ownerMask, PermissionMask nextOwnerMask, UUID ownerID, UUID creatorID, UUID transactionID, uint callbackID) { - if (parentID == UUID.Zero) - parentID = agent.InventoryRoot; - - Dictionary agentInventory = GetAgentInventory(agent.AgentID); + Dictionary agentInventory = GetAgentInventory(agentID); lock (agentInventory) { @@ -415,8 +416,8 @@ namespace Simian.Extensions item.Permissions.NextOwnerMask = nextOwnerMask; item.AssetType = type; item.AssetID = assetID; - item.OwnerID = agent.AgentID; - item.CreatorID = agent.AgentID; + item.OwnerID = agentID; + item.CreatorID = agentID; item.CreationDate = DateTime.Now; Logger.DebugLog(String.Format("Creating inventory item {0} (InvType: {1}, AssetType: {2})", item.Name, @@ -429,7 +430,7 @@ namespace Simian.Extensions // Send a success response UpdateCreateInventoryItemPacket update = new UpdateCreateInventoryItemPacket(); - update.AgentData.AgentID = agent.AgentID; + update.AgentData.AgentID = agentID; update.AgentData.SimApproved = true; if (transactionID != UUID.Zero) update.AgentData.TransactionID = transactionID; @@ -465,7 +466,7 @@ namespace Simian.Extensions update.InventoryData[0].SaleType = (byte)item.SaleType; update.InventoryData[0].Type = (sbyte)item.AssetType; - Server.UDP.SendPacket(agent.AgentID, update, PacketCategory.Inventory); + Server.UDP.SendPacket(agentID, update, PacketCategory.Inventory); return item.ID; } else @@ -493,9 +494,50 @@ namespace Simian.Extensions return false; } + public OpenMetaverse.InventoryFolder[] CreateInventorySkeleton(UUID agentID) + { + Dictionary inventory; + if (Inventory.TryGetValue(agentID, out inventory)) + { + List folderList = new List(); + + lock (inventory) + { + foreach (InventoryObject obj in inventory.Values) + { + if (obj is InventoryFolder) + folderList.Add((InventoryFolder)obj); + } + } + + OpenMetaverse.InventoryFolder[] folders = new OpenMetaverse.InventoryFolder[folderList.Count]; + + for (int i = 0; i < folderList.Count; i++) + { + InventoryFolder folder = folderList[i]; + + folders[i] = new OpenMetaverse.InventoryFolder(folder.ID); + folders[i].DescendentCount = folder.Children.Count; + folders[i].Name = folder.Name; + folders[i].OwnerID = folder.OwnerID; + folders[i].ParentUUID = folder.ParentID; + folders[i].PreferredType = folder.PreferredType; + folders[i].Version = folder.Version; + } + + return folders; + } + else + { + Logger.Log("CreateInventorySkeleton() called with an unknown agent " + agentID.ToString(), + Helpers.LogLevel.Warning); + return null; + } + } + #region Persistance - LLSDMap SerializeInventoryItem(InventoryItem item) + LLSDMap SerializeItem(InventoryItem item) { LLSDMap itemMap = new LLSDMap(16); itemMap.Add("ID", LLSD.FromUUID(item.ID)); @@ -517,7 +559,7 @@ namespace Simian.Extensions return itemMap; } - LLSDMap SerializeInventoryFolder(InventoryFolder folder) + LLSDMap SerializeFolder(InventoryFolder folder) { LLSDMap folderMap = new LLSDMap(6); folderMap.Add("ID", LLSD.FromUUID(folder.ID)); @@ -533,7 +575,16 @@ namespace Simian.Extensions { LLSDMap map = new LLSDMap(agentInventory.Count); - // FIXME: + foreach (KeyValuePair kvp in agentInventory) + { + LLSD value; + if (kvp.Value is InventoryItem) + value = SerializeItem((InventoryItem)kvp.Value); + else + value = SerializeFolder((InventoryFolder)kvp.Value); + + map.Add(kvp.Key.ToString(), value); + } return map; } @@ -543,10 +594,13 @@ namespace Simian.Extensions LLSDMap map = new LLSDMap(Inventory.Count); int itemCount = 0; - foreach (KeyValuePair> kvp in Inventory) + lock (Inventory) { - map.Add(kvp.Key.ToString(), SerializeInventory(kvp.Value)); - itemCount += kvp.Value.Count; + foreach (KeyValuePair> kvp in Inventory) + { + map.Add(kvp.Key.ToString(), SerializeInventory(kvp.Value)); + itemCount += kvp.Value.Count; + } } Logger.Log(String.Format("Serializing the inventory store with {0} items", itemCount), @@ -555,24 +609,105 @@ namespace Simian.Extensions return map; } + InventoryItem DeserializeItem(LLSDMap itemMap) + { + InventoryItem item = new InventoryItem(); + item.ID = itemMap["ID"].AsUUID(); + item.ParentID = itemMap["ParentID"].AsUUID(); + item.Name = itemMap["Name"].AsString(); + item.OwnerID = itemMap["OwnerID"].AsUUID(); + item.AssetID = itemMap["AssetID"].AsUUID(); + item.AssetType = (AssetType)itemMap["AssetType"].AsInteger(); + item.InventoryType = (InventoryType)itemMap["InventoryType"].AsInteger(); + item.CreatorID = itemMap["CreatorID"].AsUUID(); + item.GroupID = itemMap["GroupID"].AsUUID(); + item.Description = itemMap["Description"].AsString(); + item.GroupOwned = itemMap["GroupOwned"].AsBoolean(); + item.Permissions = Permissions.FromLLSD(itemMap["Permissions"]); + item.SalePrice = itemMap["SalePrice"].AsInteger(); + item.SaleType = (SaleType)itemMap["SaleType"].AsInteger(); + item.Flags = Utils.BytesToUInt(itemMap["Flags"].AsBinary()); + item.CreationDate = itemMap["CreationDate"].AsDate(); + return item; + } + + InventoryFolder DeserializeFolder(LLSDMap folderMap) + { + InventoryFolder folder = new InventoryFolder(); + folder.ID = folderMap["ID"].AsUUID(); + folder.ParentID = folderMap["ParentID"].AsUUID(); + folder.Name = folderMap["Name"].AsString(); + folder.OwnerID = folderMap["OwnerID"].AsUUID(); + folder.PreferredType = (AssetType)folderMap["PreferredType"].AsInteger(); + folder.Version = folderMap["Version"].AsInteger(); + return folder; + } + + Dictionary DeserializeInventory(LLSDMap map) + { + Dictionary inventory = new Dictionary(); + + foreach (KeyValuePair kvp in map) + { + UUID objectID = (UUID)kvp.Key; + LLSDMap objectMap = (LLSDMap)kvp.Value; + InventoryObject obj; + + if (objectMap.ContainsKey("AssetID")) + obj = DeserializeItem(objectMap); + else + obj = DeserializeFolder(objectMap); + + inventory[objectID] = obj; + } + + return inventory; + } + public void Deserialize(LLSD serialized) { - //accounts.Clear(); + int itemCount = 0; + LLSDMap map = (LLSDMap)serialized; - //LLSDArray array = (LLSDArray)serialized; + lock (Inventory) + { + Inventory.Clear(); - //for (int i = 0; i < array.Count; i++) - //{ - // Agent agent = new Agent(); - // object agentRef = (object)agent; - // LLSD.DeserializeMembers(ref agentRef, (LLSDMap)array[i]); - // agent = (Agent)agentRef; + foreach (KeyValuePair kvp in map) + { + UUID agentID = (UUID)kvp.Key; + Dictionary agentInventory = DeserializeInventory((LLSDMap)kvp.Value); + itemCount += agentInventory.Count; - // accounts.Add(agent.FullName, agent.AgentID, agent); - //} + Inventory[agentID] = agentInventory; + } - //Logger.Log(String.Format("Deserialized the agent store with {0} entries", accounts.Count), - // Helpers.LogLevel.Info); + // Iterate over the inventory objects and connect them to each other + foreach (Dictionary inventory in Inventory.Values) + { + foreach (InventoryObject obj in inventory.Values) + { + if (obj.ParentID != UUID.Zero) + { + InventoryObject parentObj; + if (inventory.TryGetValue(obj.ParentID, out parentObj) && parentObj is InventoryFolder) + { + InventoryFolder parent = (InventoryFolder)parentObj; + obj.Parent = parent; + parent.Children.Dictionary[obj.ID] = obj; + } + else + { + Logger.Log(String.Format("Cannot find parent folder {0} for inventory item {1}", + obj.ParentID, obj.ID), Helpers.LogLevel.Warning); + } + } + } + } + } + + Logger.Log(String.Format("Deserialized the inventory store with {0} items", itemCount), + Helpers.LogLevel.Info); } #endregion Persistance diff --git a/Programs/Simian/Extensions/ObjectManager.cs b/Programs/Simian/Extensions/ObjectManager.cs index 7b616aa7..2a64a0ed 100644 --- a/Programs/Simian/Extensions/ObjectManager.cs +++ b/Programs/Simian/Extensions/ObjectManager.cs @@ -563,7 +563,7 @@ namespace Simian.Extensions { // FIXME: Handle children InventoryFolder trash = (InventoryFolder)invObj; - Server.Inventory.CreateItem(agent, obj.Prim.Properties.Name, obj.Prim.Properties.Description, InventoryType.Object, + Server.Inventory.CreateItem(agent.AgentID, obj.Prim.Properties.Name, obj.Prim.Properties.Description, InventoryType.Object, AssetType.Object, obj.Prim.ID, trash.ID, PermissionMask.All, PermissionMask.All, agent.AgentID, obj.Prim.Properties.CreatorID, derez.AgentBlock.TransactionID, 0); Server.Scene.ObjectRemove(this, obj); diff --git a/Programs/Simian/Interfaces/IInventoryProvider.cs b/Programs/Simian/Interfaces/IInventoryProvider.cs index b21a39fa..7d7b7177 100644 --- a/Programs/Simian/Interfaces/IInventoryProvider.cs +++ b/Programs/Simian/Interfaces/IInventoryProvider.cs @@ -5,12 +5,13 @@ namespace Simian { public interface IInventoryProvider { - UUID CreateItem(Agent agent, string name, string description, InventoryType invType, AssetType type, + UUID CreateItem(UUID agentID, string name, string description, InventoryType invType, AssetType type, UUID assetID, UUID parentID, PermissionMask ownerMask, PermissionMask nextOwnerMask, UUID ownerID, UUID creatorID, UUID transactionID, uint callbackID); - bool CreateFolder(Agent agent, UUID folderID, string name, AssetType preferredType, UUID parentID, + bool CreateFolder(UUID agentID, UUID folderID, string name, AssetType preferredType, UUID parentID, UUID ownerID); - bool CreateRootFolder(Agent agent, UUID folderID, string name, UUID ownerID); + bool CreateRootFolder(UUID agentID, UUID folderID, string name, UUID ownerID); + OpenMetaverse.InventoryFolder[] CreateInventorySkeleton(UUID agentID); bool TryGetInventory(UUID agentID, UUID objectID, out InventoryObject obj); } } diff --git a/Programs/Simian/Simian.cs b/Programs/Simian/Simian.cs index 38e6da8c..921eecbd 100644 --- a/Programs/Simian/Simian.cs +++ b/Programs/Simian/Simian.cs @@ -293,6 +293,7 @@ namespace Simian reader.Close(); LoginResponseData responseData = HandleLogin(firstName, lastName, password, start, version, channel); + responseData.InventorySkeleton = Inventory.CreateInventorySkeleton(responseData.AgentID); XmlWriter writer = XmlWriter.Create(context.Response.OutputStream); responseData.ToXmlRpc(writer); writer.Close(); diff --git a/prebuild.xml b/prebuild.xml index 6142a3d0..4268070d 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -81,6 +81,7 @@ +