diff --git a/Programs/Simian/Agent.cs b/Programs/Simian/Agent.cs index 5184c18c..c0a84668 100644 --- a/Programs/Simian/Agent.cs +++ b/Programs/Simian/Agent.cs @@ -39,12 +39,15 @@ namespace Simian public int ProfileWantDo; public string ProfileAboutText; public string ProfileFirstText; + public string ProfileBornOn; + public string ProfileURL; public UUID ProfileImage; public UUID ProfileFirstImage; + public ProfileFlags ProfileFlags; // Appearance public byte[] VisualParams; - public byte[] Texture; + //public byte[] Texture; public float Height; public UUID ShapeItem; public UUID ShapeAsset; diff --git a/Programs/Simian/Extensions/AccountManager.cs b/Programs/Simian/Extensions/AccountManager.cs index 57f14387..8e07e7c5 100644 --- a/Programs/Simian/Extensions/AccountManager.cs +++ b/Programs/Simian/Extensions/AccountManager.cs @@ -53,26 +53,6 @@ namespace Simian.Extensions PrimFlags.ObjectAnyOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | PrimFlags.ObjectOwnerModify | PrimFlags.ObjectYouOwner; - // HACK: FIXME: These should point to actual inventories, not random UUIDs - - // Agent inventory - InventoryFolder rootFolder = new InventoryFolder(); - rootFolder.ID = agent.InventoryRoot; - rootFolder.Name = "Inventory"; - rootFolder.OwnerID = agent.AgentID; - rootFolder.PreferredType = AssetType.RootFolder; - rootFolder.Version = 1; - agent.Inventory[rootFolder.ID] = rootFolder; - - // Default library - InventoryFolder libRootFolder = new InventoryFolder(); - libRootFolder.ID = agent.InventoryLibraryRoot; - libRootFolder.Name = "Library"; - libRootFolder.OwnerID = agent.AgentID; - libRootFolder.PreferredType = AssetType.RootFolder; - libRootFolder.Version = 1; - agent.Library[libRootFolder.ID] = libRootFolder; - return agent; } else diff --git a/Programs/Simian/Extensions/AssetManager.cs b/Programs/Simian/Extensions/AssetManager.cs index 55b1f6de..d9529c84 100644 --- a/Programs/Simian/Extensions/AssetManager.cs +++ b/Programs/Simian/Extensions/AssetManager.cs @@ -41,7 +41,7 @@ namespace Simian.Extensions if (texture.DecodeLayerBoundaries()) { lock (AssetStore) - AssetStore[asset.AssetID] = asset; + AssetStore[asset.AssetID] = texture; } else { @@ -285,11 +285,14 @@ namespace Simian.Extensions { Logger.Log(String.Format( "Request for asset {0} with type {1} does not match actual asset type {2}", - asset.AssetID, type, asset.AssetType), Helpers.LogLevel.Warning); + assetID, type, asset.AssetType), Helpers.LogLevel.Warning); } } else { + Logger.Log(String.Format("Request for missing asset {0} with type {1}", + assetID, type), Helpers.LogLevel.Warning); + // Asset not found response.TransferInfo.Size = 0; response.TransferInfo.Status = (int)StatusCode.UnknownSource; diff --git a/Programs/Simian/Extensions/AuthFreeForAll.cs b/Programs/Simian/Extensions/AuthFreeForAll.cs index 7318449a..0d8625f5 100644 --- a/Programs/Simian/Extensions/AuthFreeForAll.cs +++ b/Programs/Simian/Extensions/AuthFreeForAll.cs @@ -41,14 +41,58 @@ namespace Simian.Extensions agent.HomeLookAt = agent.CurrentLookAt; agent.HomePosition = agent.CurrentPosition; agent.HomeRegionHandle = agent.CurrentRegionHandle; - agent.InventoryLibraryOwner = UUID.Random(); // FIXME: - agent.InventoryLibraryRoot = UUID.Random(); // FIXME: - agent.InventoryRoot = UUID.Random(); // FIXME: agent.LastName = lastName; agent.PasswordHash = password; - // FIXME: Give new avatars a default appearance - //agent.VisualParams; - //agent.Texture; + + // Create a very basic inventory skeleton + UUID rootFolder = UUID.Random(); + server.Inventory.CreateRootFolder(agent, rootFolder, "Inventory", agent.AgentID); + UUID libraryRootFolder = UUID.Random(); + server.Inventory.CreateRootFolder(agent, libraryRootFolder, "Library", agent.AgentID); + + agent.InventoryRoot = rootFolder; + agent.InventoryLibraryOwner = agent.AgentID; + agent.InventoryLibraryRoot = libraryRootFolder; + + // Create some inventory items for appearance + UUID clothingFolder = UUID.Random(); + server.Inventory.CreateFolder(agent, clothingFolder, "Clothing", AssetType.Clothing, + UUID.Zero, agent.AgentID); + UUID defaultOutfitFolder = UUID.Random(); + server.Inventory.CreateFolder(agent, 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", + 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", + 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", + 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", + 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", + InventoryType.Wearable, AssetType.Clothing, skinAsset, defaultOutfitFolder, + PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0); + + agent.HairAsset = hairAsset; + agent.HairItem = hairItem; + agent.PantsAsset = pantsAsset; + agent.PantsItem = pantsItem; + agent.ShapeAsset = shapeAsset; + agent.ShapeItem = shapeItem; + agent.ShirtAsset = shirtAsset; + agent.ShirtItem = shirtItem; + agent.SkinAsset = skinAsset; + agent.SkinItem = skinItem; server.Accounts.AddAccount(agent); diff --git a/Programs/Simian/Extensions/ConnectionManagement.cs b/Programs/Simian/Extensions/ConnectionManagement.cs index 17b2b002..a8b7b92d 100644 --- a/Programs/Simian/Extensions/ConnectionManagement.cs +++ b/Programs/Simian/Extensions/ConnectionManagement.cs @@ -73,29 +73,6 @@ namespace Simian.Extensions { LogoutRequestPacket request = (LogoutRequestPacket)packet; - lock (server.Agents) - { - if (server.Agents.ContainsKey(agent.AgentID)) - { - KillObjectPacket kill = new KillObjectPacket(); - kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; - kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); - kill.ObjectData[0].ID = agent.Avatar.LocalID; - - server.UDP.BroadcastPacket(kill, PacketCategory.State); - } - } - - // Remove the avatar from the scene - SimulationObject obj; - if (server.Scene.TryGetObject(agent.AgentID, out obj)) - server.Scene.ObjectRemove(this, obj); - else - Logger.Log("Logout request from an agent that is not in the scene", Helpers.LogLevel.Warning); - - // Remove the UDP client - server.UDP.RemoveClient(agent); - LogoutReplyPacket reply = new LogoutReplyPacket(); reply.AgentData.AgentID = agent.AgentID; reply.AgentData.SessionID = agent.SessionID; @@ -105,12 +82,7 @@ namespace Simian.Extensions server.UDP.SendPacket(agent.AgentID, reply, PacketCategory.Transaction); - //HACK: Notify everyone when someone logs off - OfflineNotificationPacket offline = new OfflineNotificationPacket(); - offline.AgentBlock = new OfflineNotificationPacket.AgentBlockBlock[1]; - offline.AgentBlock[0] = new OfflineNotificationPacket.AgentBlockBlock(); - offline.AgentBlock[0].AgentID = agent.AgentID; - server.UDP.BroadcastPacket(offline, PacketCategory.State); + server.DisconnectClient(agent); } } } diff --git a/Programs/Simian/Extensions/InventoryManager.cs b/Programs/Simian/Extensions/InventoryManager.cs index 040e53b3..0542f5b0 100644 --- a/Programs/Simian/Extensions/InventoryManager.cs +++ b/Programs/Simian/Extensions/InventoryManager.cs @@ -20,6 +20,7 @@ namespace Simian.Extensions Server.UDP.RegisterPacketCallback(PacketType.CreateInventoryFolder, new PacketCallback(CreateInventoryFolderHandler)); Server.UDP.RegisterPacketCallback(PacketType.UpdateInventoryItem, new PacketCallback(UpdateInventoryItemHandler)); Server.UDP.RegisterPacketCallback(PacketType.FetchInventoryDescendents, new PacketCallback(FetchInventoryDescendentsHandler)); + Server.UDP.RegisterPacketCallback(PacketType.FetchInventory, new PacketCallback(FetchInventoryHandler)); } public void Stop() @@ -56,44 +57,8 @@ namespace Simian.Extensions { CreateInventoryFolderPacket create = (CreateInventoryFolderPacket)packet; - lock (agent.Inventory) - { - InventoryObject parent; - if (agent.Inventory.TryGetValue(create.FolderData.ParentID, out parent)) - { - InventoryFolder parentFolder = (InventoryFolder)parent; - - if (!agent.Inventory.ContainsKey(create.FolderData.FolderID)) - { - InventoryFolder folder = new InventoryFolder(); - folder.Name = Utils.BytesToString(create.FolderData.Name); - folder.OwnerID = agent.AgentID; - folder.ParentID = create.FolderData.ParentID; - folder.Parent = parentFolder; - folder.PreferredType = (AssetType)create.FolderData.Type; - folder.ID = create.FolderData.FolderID; - folder.Version = 1; - - Logger.DebugLog(String.Format("Creating inventory folder {0}", folder.Name)); - - agent.Inventory[folder.ID] = folder; - lock (parentFolder.Children.Dictionary) - parentFolder.Children.Dictionary[folder.ID] = folder; - } - else - { - Logger.Log(String.Format( - "Cannot create new inventory folder, item {0} already exists", - create.FolderData.FolderID), Helpers.LogLevel.Warning); - } - } - else - { - Logger.Log(String.Format( - "Cannot create new inventory folder, parent folder {0} does not exist", - create.FolderData.ParentID), Helpers.LogLevel.Warning); - } - } + CreateFolder(agent, create.FolderData.FolderID, Utils.BytesToString(create.FolderData.Name), + (AssetType)create.FolderData.Type, create.FolderData.ParentID, agent.AgentID); } void UpdateInventoryItemHandler(Packet packet, Agent agent) @@ -246,12 +211,150 @@ namespace Simian.Extensions } else { - Logger.Log(String.Format( - "FetchInventoryDescendents called for an unknown folder {0}", - fetch.InventoryData.FolderID), Helpers.LogLevel.Warning); + Logger.Log("FetchInventoryDescendents called for an unknown folder " + fetch.InventoryData.FolderID, + Helpers.LogLevel.Warning); } } + void FetchInventoryHandler(Packet packet, Agent agent) + { + FetchInventoryPacket fetch = (FetchInventoryPacket)packet; + + FetchInventoryReplyPacket reply = new FetchInventoryReplyPacket(); + reply.AgentData.AgentID = agent.AgentID; + reply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[fetch.InventoryData.Length]; + + for (int i = 0; i < fetch.InventoryData.Length; i++) + { + UUID itemID = fetch.InventoryData[i].ItemID; + + reply.InventoryData[i] = new FetchInventoryReplyPacket.InventoryDataBlock(); + reply.InventoryData[i].ItemID = itemID; + + InventoryObject obj; + if (agent.Inventory.TryGetValue(itemID, out obj) && obj is InventoryItem) + { + InventoryItem item = (InventoryItem)obj; + + reply.InventoryData[i].AssetID = item.AssetID; + reply.InventoryData[i].BaseMask = (uint)item.Permissions.BaseMask; + reply.InventoryData[i].CRC = Helpers.InventoryCRC((int)Utils.DateTimeToUnixTime(item.CreationDate), + (byte)item.SaleType, (sbyte)item.InventoryType, (sbyte)item.AssetType, item.AssetID, item.GroupID, + item.SalePrice, item.OwnerID, item.CreatorID, item.ID, item.ParentID, + (uint)item.Permissions.EveryoneMask, item.Flags, (uint)item.Permissions.NextOwnerMask, + (uint)item.Permissions.GroupMask, (uint)item.Permissions.OwnerMask); + reply.InventoryData[i].CreationDate = (int)Utils.DateTimeToUnixTime(item.CreationDate); + reply.InventoryData[i].CreatorID = item.CreatorID; + reply.InventoryData[i].Description = Utils.StringToBytes(item.Description); + reply.InventoryData[i].EveryoneMask = (uint)item.Permissions.EveryoneMask; + reply.InventoryData[i].Flags = item.Flags; + reply.InventoryData[i].FolderID = item.ParentID; + reply.InventoryData[i].GroupID = item.GroupID; + reply.InventoryData[i].GroupMask = (uint)item.Permissions.GroupMask; + reply.InventoryData[i].GroupOwned = item.GroupOwned; + reply.InventoryData[i].InvType = (sbyte)item.InventoryType; + reply.InventoryData[i].Name = Utils.StringToBytes(item.Name); + reply.InventoryData[i].NextOwnerMask = (uint)item.Permissions.NextOwnerMask; + reply.InventoryData[i].OwnerID = item.OwnerID; + reply.InventoryData[i].OwnerMask = (uint)item.Permissions.OwnerMask; + reply.InventoryData[i].SalePrice = item.SalePrice; + reply.InventoryData[i].SaleType = (byte)item.SaleType; + reply.InventoryData[i].Type = (sbyte)item.AssetType; + } + else + { + Logger.Log("FetchInventory called for an unknown item " + itemID.ToString(), + Helpers.LogLevel.Warning); + + reply.InventoryData[i].Name = new byte[0]; + reply.InventoryData[i].Description = new byte[0]; + } + } + + Server.UDP.SendPacket(agent.AgentID, reply, PacketCategory.Inventory); + } + + public bool CreateRootFolder(Agent agent, UUID folderID, string name, UUID ownerID) + { + lock (agent.Inventory) + { + if (!agent.Inventory.ContainsKey(folderID)) + { + InventoryFolder folder = new InventoryFolder(); + folder.Name = name; + folder.OwnerID = agent.AgentID; + folder.ParentID = UUID.Zero; + folder.Parent = null; + folder.PreferredType = AssetType.Folder; + folder.ID = folderID; + folder.Version = 1; + + Logger.DebugLog("Creating root inventory folder " + folder.Name); + + agent.Inventory[folder.ID] = folder; + return true; + } + else + { + Logger.Log(String.Format( + "Cannot create root inventory folder, item {0} already exists", folderID), + Helpers.LogLevel.Warning); + } + } + + return false; + } + + public bool CreateFolder(Agent agent, UUID folderID, string name, AssetType preferredType, + UUID parentID, UUID ownerID) + { + if (parentID == UUID.Zero) + parentID = agent.InventoryRoot; + + lock (agent.Inventory) + { + InventoryObject parent; + if (agent.Inventory.TryGetValue(parentID, out parent) && parent is InventoryFolder) + { + InventoryFolder parentFolder = (InventoryFolder)parent; + + if (!agent.Inventory.ContainsKey(folderID)) + { + InventoryFolder folder = new InventoryFolder(); + folder.Name = name; + folder.OwnerID = agent.AgentID; + folder.ParentID = parentID; + folder.Parent = parentFolder; + folder.PreferredType = preferredType; + folder.ID = folderID; + folder.Version = 1; + + Logger.DebugLog("Creating inventory folder " + folder.Name); + + agent.Inventory[folder.ID] = folder; + lock (parentFolder.Children.Dictionary) + parentFolder.Children.Dictionary[folder.ID] = folder; + + return true; + } + else + { + Logger.Log(String.Format( + "Cannot create new inventory folder, item {0} already exists", folderID), + Helpers.LogLevel.Warning); + } + } + else + { + Logger.Log(String.Format( + "Cannot create new inventory folder, parent folder {0} does not exist", parentID), + Helpers.LogLevel.Warning); + } + } + + return false; + } + public UUID CreateItem(Agent agent, string name, string description, InventoryType invType, AssetType type, UUID assetID, UUID parentID, PermissionMask ownerMask, PermissionMask nextOwnerMask, UUID ownerID, UUID creatorID, UUID transactionID, uint callbackID) @@ -277,6 +380,7 @@ namespace Simian.Extensions item.Permissions.OwnerMask = ownerMask; item.Permissions.NextOwnerMask = nextOwnerMask; item.AssetType = type; + item.AssetID = assetID; item.OwnerID = agent.AgentID; item.CreatorID = agent.AgentID; item.CreationDate = DateTime.Now; @@ -333,7 +437,7 @@ namespace Simian.Extensions else { Logger.Log(String.Format( - "Cannot created new inventory item, folder {0} does not exist", + "Cannot create new inventory item, folder {0} does not exist", parentID), Helpers.LogLevel.Warning); return UUID.Zero; diff --git a/Programs/Simian/Interfaces/IInventoryProvider.cs b/Programs/Simian/Interfaces/IInventoryProvider.cs index 654f1aea..997e42c0 100644 --- a/Programs/Simian/Interfaces/IInventoryProvider.cs +++ b/Programs/Simian/Interfaces/IInventoryProvider.cs @@ -8,5 +8,8 @@ namespace Simian UUID CreateItem(Agent agent, 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, + UUID ownerID); + bool CreateRootFolder(Agent agent, UUID folderID, string name, UUID ownerID); } } diff --git a/Programs/Simian/Simian.cs b/Programs/Simian/Simian.cs index 9bf79540..bace95da 100644 --- a/Programs/Simian/Simian.cs +++ b/Programs/Simian/Simian.cs @@ -114,6 +114,26 @@ namespace Simian HttpServer.Stop(); } + public void DisconnectClient(Agent agent) + { + // Remove the avatar from the scene + SimulationObject obj; + if (Scene.TryGetObject(agent.AgentID, out obj)) + Scene.ObjectRemove(this, obj); + else + Logger.Log("Disconnecting an agent that is not in the scene", Helpers.LogLevel.Warning); + + // Remove the UDP client + UDP.RemoveClient(agent); + + // HACK: Notify everyone when someone disconnects + OfflineNotificationPacket offline = new OfflineNotificationPacket(); + offline.AgentBlock = new OfflineNotificationPacket.AgentBlockBlock[1]; + offline.AgentBlock[0] = new OfflineNotificationPacket.AgentBlockBlock(); + offline.AgentBlock[0].AgentID = agent.AgentID; + UDP.BroadcastPacket(offline, PacketCategory.State); + } + void TryAssignToInterface(ISimianExtension extension) { if (extension is IAuthenticationProvider)