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.
0.6.1-post-fixes
Melanie Thielker 2008-11-12 06:22:31 +00:00
parent c453a41fb5
commit c71f0899c2
2 changed files with 145 additions and 116 deletions

View File

@ -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);
/// <summary>
/// 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
/// </summary>
private IDictionary<UUID, UUID> m_pendingOffers = new Dictionary<UUID, UUID>();
private List<Scene> m_Scenelist = new List<Scene>();
private Dictionary<UUID, Scene> m_AgentRegions = new Dictionary<UUID, Scene>();
private Dictionary<UUID, Scene> m_AgentRegions =
new Dictionary<UUID, Scene>();
#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,6 +100,23 @@ 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,
@ -108,128 +124,130 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer
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);
if (((Scene)(client.Scene)).Entities.ContainsKey(toAgentID) && ((Scene)(client.Scene)).Entities[toAgentID] is ScenePresence)
{
ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID];
if (!user.IsChildAgent)
{
//byte[] rawId = new byte[16];
ScenePresence user =
scene.GetScenePresence(toAgentID);
// 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);
UUID itemID = new UUID(binaryBucket, 1);
m_log.DebugFormat(
"[AGENT INVENTORY]: ItemId for giving is {0}", itemId);
m_log.DebugFormat("[AGENT INVENTORY]: Inserting item {0} "+
"into agent {1}'s inventory",
itemID, toAgentID);
m_pendingOffers[imSessionID] = itemId;
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)
{
// 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);
}
}
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)
{
ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID];
if (!user.IsChildAgent)
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]: 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)
{
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);
}
}
// Send via grid
//
// TODO: Implement sending via grid
}
}
}

View File

@ -406,6 +406,14 @@ namespace OpenSim.Region.Environment.Scenes
/// <param name="senderId">ID of the sender of the item</param>
/// <param name="itemId"></param>
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,