diff --git a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index b134591ace..71cc726d4b 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,135 +100,154 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer
client.OnInstantMessage += OnInstantMessage;
}
- 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)
+ 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)
+ {
+ 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)
+ // First byte of the array is probably the item type
+ // Next 16 bytes are the UUID
+
+ UUID itemID = new UUID(binaryBucket, 1);
+
+ m_log.DebugFormat("[AGENT INVENTORY]: Inserting item {0} "+
+ "into agent {1}'s inventory",
+ itemID, toAgentID);
+
+ InventoryItemBase itemCopy = scene.GiveInventoryItem(toAgentID,
+ client.AgentId, itemID);
+
+ byte[] itemCopyID = itemCopy.ID.GetBytes();
+
+ Array.Copy(itemCopyID, 0, binaryBucket, 1, 16);
+
+ // 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)
{
- ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID];
+ // User is online. So, let's make the item visible
+ //
+ user.ControllingClient.SendBulkUpdateInventory(itemCopy);
- if (!user.IsChildAgent)
- {
- //byte[] rawId = new byte[16];
-
- // First byte of the array is probably the item type
- // Next 16 bytes are the UUID
- //Array.Copy(binaryBucket, 1, rawId, 0, 16);
-
- //UUID itemId = new UUID(new Guid(rawId));
- UUID itemId = new UUID(binaryBucket, 1);
-
- m_log.DebugFormat(
- "[AGENT INVENTORY]: ItemId for giving is {0}", itemId);
-
- m_pendingOffers[imSessionID] = itemId;
-
- user.ControllingClient.SendInstantMessage(
+ // 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)
- {
- ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID];
+ UUID itemID = imSessionID; // The item, back from it's trip
- if (!user.IsChildAgent)
+ // 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)
+ {
+ InventoryFolderImpl trashFolder =
+ userInfo.FindFolderForType((int)AssetType.TrashFolder);
+
+ InventoryItemBase item =
+ userInfo.RootFolder.FindItem(itemID);
+
+ if (trashFolder != null && item != null)
{
- user.ControllingClient.SendInstantMessage(
+ item.Folder = trashFolder.ID;
+
+ userInfo.DeleteItem(itemID);
+
+ 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);
-
- if (m_pendingOffers.ContainsKey(imSessionID))
- {
- m_log.DebugFormat(
- "[AGENT INVENTORY]: Declined item id {0}", m_pendingOffers[imSessionID]);
-
- m_pendingOffers.Remove(imSessionID);
- }
- else
- {
- m_log.ErrorFormat(
- "[AGENT INVENTORY]: Could not find an item associated with session id {0} to decline",
- imSessionID);
- }
- }
+ }
+ 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 298b9ff325..7e32086fe3 100644
--- a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs
@@ -406,6 +406,14 @@ namespace OpenSim.Region.Environment.Scenes
/// ID of the sender of the item
///
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,