From c71f0899c255c9415210662273365cad83e40c0e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 12 Nov 2008 06:22:31 +0000 Subject: Revamp inventory transfer module, step 1. Inventory will now be saved if destination user is offline/out of range. No more eternal cache is needed for tracking IDs. Code cleanup. Removed some casts from IScene to Scene. Decline now properly places item in trash rather than deleting it outright. --- .../Inventory/Transfer/InventoryTransferModule.cs | 216 +++++++++++---------- .../Region/Environment/Scenes/Scene.Inventory.cs | 31 ++- 2 files changed, 138 insertions(+), 109 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index b134591..71cc726 100644 --- a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -25,6 +25,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; +using System.Collections; using System.Collections.Generic; using System.Reflection; using OpenMetaverse; @@ -33,6 +35,7 @@ using Nini.Config; using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; +using OpenSim.Framework.Communications.Cache; namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer { @@ -42,14 +45,9 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// - /// We need to keep track of the pending item offers between clients since the itemId offered only - /// occurs in the initial offer message, not the accept message. So this dictionary links - /// IM Session Ids to ItemIds - /// - private IDictionary m_pendingOffers = new Dictionary(); - private List m_Scenelist = new List(); - private Dictionary m_AgentRegions = new Dictionary(); + private Dictionary m_AgentRegions = + new Dictionary(); #region IRegionModule Members @@ -64,6 +62,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer "InventoryTransferModule") return; } + if (!m_Scenelist.Contains(scene)) { m_Scenelist.Add(scene); @@ -101,136 +100,155 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer client.OnInstantMessage += OnInstantMessage; } + private Scene FindClientScene(UUID agentId) + { + lock (m_Scenelist) + { + foreach (Scene scene in m_Scenelist) + { + ScenePresence presence = scene.GetScenePresence(agentId); + if (presence != null) + { + if (!presence.IsChildAgent) + return scene; + } + } + } + return null; + } + private void OnInstantMessage(IClientAPI client, UUID fromAgentID, - UUID fromAgentSession, UUID toAgentID, - UUID imSessionID, uint timestamp, string fromAgentName, - string message, byte dialog, bool fromGroup, byte offline, - uint ParentEstateID, Vector3 Position, UUID RegionID, - byte[] binaryBucket) + UUID fromAgentSession, UUID toAgentID, + UUID imSessionID, uint timestamp, string fromAgentName, + string message, byte dialog, bool fromGroup, byte offline, + uint ParentEstateID, Vector3 Position, UUID RegionID, + byte[] binaryBucket) { + Scene scene = FindClientScene(client.AgentId); + + if (scene == null) // Something seriously wrong here. + return; + if (dialog == (byte) InstantMessageDialog.InventoryOffered) { - m_log.DebugFormat( - "[AGENT INVENTORY]: Routing inventory offering message from {0}, {1} to {2}", - client.AgentId, client.Name, toAgentID); + ScenePresence user = + scene.GetScenePresence(toAgentID); - if (((Scene)(client.Scene)).Entities.ContainsKey(toAgentID) && ((Scene)(client.Scene)).Entities[toAgentID] is ScenePresence) - { - ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID]; + // First byte of the array is probably the item type + // Next 16 bytes are the UUID - if (!user.IsChildAgent) - { - //byte[] rawId = new byte[16]; + UUID itemID = new UUID(binaryBucket, 1); - // First byte of the array is probably the item type - // Next 16 bytes are the UUID - //Array.Copy(binaryBucket, 1, rawId, 0, 16); + m_log.DebugFormat("[AGENT INVENTORY]: Inserting item {0} "+ + "into agent {1}'s inventory", + itemID, toAgentID); - //UUID itemId = new UUID(new Guid(rawId)); - UUID itemId = new UUID(binaryBucket, 1); + InventoryItemBase itemCopy = scene.GiveInventoryItem(toAgentID, + client.AgentId, itemID); - m_log.DebugFormat( - "[AGENT INVENTORY]: ItemId for giving is {0}", itemId); + byte[] itemCopyID = itemCopy.ID.GetBytes(); - m_pendingOffers[imSessionID] = itemId; + Array.Copy(itemCopyID, 0, binaryBucket, 1, 16); - user.ControllingClient.SendInstantMessage( + // Send the IM to the recipient. The item is already + // in their inventory, so it will not be lost if + // they are offline. + // + if (user != null && !user.IsChildAgent) + { + // User is online. So, let's make the item visible + // + user.ControllingClient.SendBulkUpdateInventory(itemCopy); + + // And notify. Transaction ID is the item ID. We get that + // same ID back on the reply so we know what to act on + // + user.ControllingClient.SendInstantMessage( fromAgentID, message, toAgentID, fromAgentName, - dialog, timestamp, UUID.Zero, false, binaryBucket); + dialog, timestamp, itemCopy.ID, false, + binaryBucket); - return; - } - else - { - m_log.WarnFormat( - "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!", - toAgentID, client.AgentId, client.Name, message); - } + return; } else { - m_log.WarnFormat( - "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}", - toAgentID, client.AgentId, client.Name, message); + // Send via grid services + // + // TODO: Implement grid sending } } else if (dialog == (byte) InstantMessageDialog.InventoryAccepted) { - m_log.DebugFormat( - "[AGENT INVENTORY]: Routing inventory accepted message from {0}, {1} to {2}", - client.AgentId, client.Name, toAgentID); + ScenePresence user = scene.GetScenePresence(toAgentID); - if (((Scene)(client.Scene)).Entities.ContainsKey(toAgentID) && ((Scene)(client.Scene)).Entities[toAgentID] is ScenePresence) + if (user != null) // Local { - ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID]; - - if (!user.IsChildAgent) - { - user.ControllingClient.SendInstantMessage( + user.ControllingClient.SendInstantMessage( fromAgentID, message, toAgentID, fromAgentName, dialog, timestamp, UUID.Zero, false, binaryBucket); - - if (m_pendingOffers.ContainsKey(imSessionID)) - { - m_log.DebugFormat( - "[AGENT INVENTORY]: Accepted item id {0}", m_pendingOffers[imSessionID]); - - // Since the message originates from the accepting client, the toAgentID is - // the agent giving the item. - ((Scene)(client.Scene)).GiveInventoryItem(client, toAgentID, m_pendingOffers[imSessionID]); - - m_pendingOffers.Remove(imSessionID); - } - else - { - m_log.ErrorFormat( - "[AGENT INVENTORY]: Could not find an item associated with session id {0} to accept", - imSessionID); - } - - return; - } - else - { - m_log.WarnFormat( - "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!", - toAgentID, client.AgentId, client.Name, message); - } } else { - m_log.WarnFormat( - "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}", - toAgentID, client.AgentId, client.Name, message); + // Send via grid + // + // TODO: Implement sending via grid } } else if (dialog == (byte) InstantMessageDialog.InventoryDeclined) { - if (((Scene)(client.Scene)).Entities.ContainsKey(toAgentID) && ((Scene)(client.Scene)).Entities[toAgentID] is ScenePresence) + UUID itemID = imSessionID; // The item, back from it's trip + + // Here, the recipient is local and we can assume that the + // inventory is loaded. Courtesy of the above bulk update, + // It will have been pushed to the client, too + // + + CachedUserInfo userInfo = + scene.CommsManager.UserProfileCacheService. + GetUserDetails(client.AgentId); + + if (userInfo != null) { - ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID]; + InventoryFolderImpl trashFolder = + userInfo.FindFolderForType((int)AssetType.TrashFolder); - if (!user.IsChildAgent) + InventoryItemBase item = + userInfo.RootFolder.FindItem(itemID); + + if (trashFolder != null && item != null) { - user.ControllingClient.SendInstantMessage( - fromAgentID, message, toAgentID, fromAgentName, - dialog, timestamp, UUID.Zero, false, binaryBucket); + item.Folder = trashFolder.ID; - if (m_pendingOffers.ContainsKey(imSessionID)) - { - m_log.DebugFormat( - "[AGENT INVENTORY]: Declined item id {0}", m_pendingOffers[imSessionID]); + userInfo.DeleteItem(itemID); - m_pendingOffers.Remove(imSessionID); - } - else - { - m_log.ErrorFormat( - "[AGENT INVENTORY]: Could not find an item associated with session id {0} to decline", - imSessionID); - } + scene.AddInventoryItem(client, item); + } + else + { + string reason = ""; + if (trashFolder == null) + reason += " Trash folder not found."; + if (item == null) + reason += " Item not found."; + client.SendAgentAlertMessage("Unable to delete "+ + "received item"+reason, false); } } + + ScenePresence user = scene.GetScenePresence(toAgentID); + + if (user != null) // Local + { + user.ControllingClient.SendInstantMessage( + fromAgentID, message, toAgentID, fromAgentName, + dialog, timestamp, UUID.Zero, false, binaryBucket); + } + else + { + // Send via grid + // + // TODO: Implement sending via grid + } } } diff --git a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs index 298b9ff..7e32086 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs @@ -407,6 +407,14 @@ namespace OpenSim.Region.Environment.Scenes /// public virtual void GiveInventoryItem(IClientAPI recipientClient, UUID senderId, UUID itemId) { + InventoryItemBase itemCopy = GiveInventoryItem(recipientClient.AgentId, senderId, itemId); + + if (itemCopy != null) + recipientClient.SendBulkUpdateInventory(itemCopy); + } + + public virtual InventoryItemBase GiveInventoryItem(UUID recipient, UUID senderId, UUID itemId) + { // Retrieve the item from the sender CachedUserInfo senderUserInfo = CommsManager.UserProfileCacheService.GetUserDetails(senderId); @@ -415,7 +423,7 @@ namespace OpenSim.Region.Environment.Scenes m_log.ErrorFormat( "[AGENT INVENTORY]: Failed to find sending user {0} for item {1}", senderId, itemId); - return; + return null; } if (senderUserInfo.RootFolder != null) @@ -427,18 +435,21 @@ namespace OpenSim.Region.Environment.Scenes if (!ExternalChecks.ExternalChecksBypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) - return; + return null; } // TODO get recipient's root folder CachedUserInfo recipientUserInfo - = CommsManager.UserProfileCacheService.GetUserDetails(recipientClient.AgentId); + = CommsManager.UserProfileCacheService.GetUserDetails(recipient); if (recipientUserInfo != null) { + if (!recipientUserInfo.HasReceivedInventory) + CommsManager.UserProfileCacheService.RequestInventoryForUser(recipient); + // Insert a copy of the item into the recipient InventoryItemBase itemCopy = new InventoryItemBase(); - itemCopy.Owner = recipientClient.AgentId; + itemCopy.Owner = recipient; itemCopy.Creator = item.Creator; itemCopy.ID = UUID.Random(); itemCopy.AssetID = item.AssetID; @@ -493,14 +504,13 @@ namespace OpenSim.Region.Environment.Scenes senderUserInfo.DeleteItem(itemId); } - // Let the recipient client know about this new item - recipientClient.SendBulkUpdateInventory(itemCopy); + return itemCopy; } else { m_log.ErrorFormat( - "[AGENT INVENTORY]: Could not find userinfo for recipient user {0}, {1} of item {2}, {3} from {4}", - recipientClient.Name, recipientClient.AgentId, item.Name, + "[AGENT INVENTORY]: Could not find userinfo for recipient user {0} of item {1}, {2} from {3}", + recipient, item.Name, item.ID, senderId); } } @@ -509,14 +519,15 @@ namespace OpenSim.Region.Environment.Scenes m_log.ErrorFormat( "[AGENT INVENTORY]: Failed to find item {0} to give to {1}", itemId, senderId); - return; + return null; } } else { m_log.Error("[AGENT INVENTORY]: Failed to find item " + itemId.ToString() + ", no root folder"); - return; + return null; } + return null; } public void CopyInventoryItem(IClientAPI remoteClient, uint callbackID, UUID oldAgentID, UUID oldItemID, -- cgit v1.1