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. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using OpenMetaverse; using OpenMetaverse;
@ -33,6 +35,7 @@ using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
using OpenSim.Framework.Communications.Cache;
namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer 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); = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary> /// <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 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 #region IRegionModule Members
@ -64,6 +62,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer
"InventoryTransferModule") "InventoryTransferModule")
return; return;
} }
if (!m_Scenelist.Contains(scene)) if (!m_Scenelist.Contains(scene))
{ {
m_Scenelist.Add(scene); m_Scenelist.Add(scene);
@ -101,135 +100,154 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer
client.OnInstantMessage += OnInstantMessage; client.OnInstantMessage += OnInstantMessage;
} }
private void OnInstantMessage(IClientAPI client, UUID fromAgentID, private Scene FindClientScene(UUID agentId)
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)
{ {
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) if (dialog == (byte) InstantMessageDialog.InventoryOffered)
{ {
m_log.DebugFormat( ScenePresence user =
"[AGENT INVENTORY]: Routing inventory offering message from {0}, {1} to {2}", scene.GetScenePresence(toAgentID);
client.AgentId, client.Name, 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) // And notify. Transaction ID is the item ID. We get that
{ // same ID back on the reply so we know what to act on
//byte[] rawId = new byte[16]; //
user.ControllingClient.SendInstantMessage(
// 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(
fromAgentID, message, toAgentID, fromAgentName, fromAgentID, message, toAgentID, fromAgentName,
dialog, timestamp, UUID.Zero, false, binaryBucket); dialog, timestamp, itemCopy.ID, false,
binaryBucket);
return; 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 else
{ {
m_log.WarnFormat( // Send via grid services
"[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}", //
toAgentID, client.AgentId, client.Name, message); // TODO: Implement grid sending
} }
} }
else if (dialog == (byte) InstantMessageDialog.InventoryAccepted) else if (dialog == (byte) InstantMessageDialog.InventoryAccepted)
{ {
m_log.DebugFormat( ScenePresence user = scene.GetScenePresence(toAgentID);
"[AGENT INVENTORY]: Routing inventory accepted 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) if (user != null) // Local
{ {
ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID]; user.ControllingClient.SendInstantMessage(
if (!user.IsChildAgent)
{
user.ControllingClient.SendInstantMessage(
fromAgentID, message, toAgentID, fromAgentName, fromAgentID, message, toAgentID, fromAgentName,
dialog, timestamp, UUID.Zero, false, binaryBucket); 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 else
{ {
m_log.WarnFormat( // Send via grid
"[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}", //
toAgentID, client.AgentId, client.Name, message); // TODO: Implement sending via grid
} }
} }
else if (dialog == (byte) InstantMessageDialog.InventoryDeclined) 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
{
ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID];
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, fromAgentID, message, toAgentID, fromAgentName,
dialog, timestamp, UUID.Zero, false, binaryBucket); dialog, timestamp, UUID.Zero, false, binaryBucket);
}
if (m_pendingOffers.ContainsKey(imSessionID)) else
{ {
m_log.DebugFormat( // Send via grid
"[AGENT INVENTORY]: Declined item id {0}", m_pendingOffers[imSessionID]); //
// TODO: Implement sending via grid
m_pendingOffers.Remove(imSessionID);
}
else
{
m_log.ErrorFormat(
"[AGENT INVENTORY]: Could not find an item associated with session id {0} to decline",
imSessionID);
}
}
} }
} }
} }

View File

@ -406,6 +406,14 @@ namespace OpenSim.Region.Environment.Scenes
/// <param name="senderId">ID of the sender of the item</param> /// <param name="senderId">ID of the sender of the item</param>
/// <param name="itemId"></param> /// <param name="itemId"></param>
public virtual void GiveInventoryItem(IClientAPI recipientClient, UUID senderId, UUID itemId) 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 // Retrieve the item from the sender
CachedUserInfo senderUserInfo = CommsManager.UserProfileCacheService.GetUserDetails(senderId); CachedUserInfo senderUserInfo = CommsManager.UserProfileCacheService.GetUserDetails(senderId);
@ -415,7 +423,7 @@ namespace OpenSim.Region.Environment.Scenes
m_log.ErrorFormat( m_log.ErrorFormat(
"[AGENT INVENTORY]: Failed to find sending user {0} for item {1}", senderId, itemId); "[AGENT INVENTORY]: Failed to find sending user {0} for item {1}", senderId, itemId);
return; return null;
} }
if (senderUserInfo.RootFolder != null) if (senderUserInfo.RootFolder != null)
@ -427,18 +435,21 @@ namespace OpenSim.Region.Environment.Scenes
if (!ExternalChecks.ExternalChecksBypassPermissions()) if (!ExternalChecks.ExternalChecksBypassPermissions())
{ {
if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
return; return null;
} }
// TODO get recipient's root folder // TODO get recipient's root folder
CachedUserInfo recipientUserInfo CachedUserInfo recipientUserInfo
= CommsManager.UserProfileCacheService.GetUserDetails(recipientClient.AgentId); = CommsManager.UserProfileCacheService.GetUserDetails(recipient);
if (recipientUserInfo != null) if (recipientUserInfo != null)
{ {
if (!recipientUserInfo.HasReceivedInventory)
CommsManager.UserProfileCacheService.RequestInventoryForUser(recipient);
// Insert a copy of the item into the recipient // Insert a copy of the item into the recipient
InventoryItemBase itemCopy = new InventoryItemBase(); InventoryItemBase itemCopy = new InventoryItemBase();
itemCopy.Owner = recipientClient.AgentId; itemCopy.Owner = recipient;
itemCopy.Creator = item.Creator; itemCopy.Creator = item.Creator;
itemCopy.ID = UUID.Random(); itemCopy.ID = UUID.Random();
itemCopy.AssetID = item.AssetID; itemCopy.AssetID = item.AssetID;
@ -493,14 +504,13 @@ namespace OpenSim.Region.Environment.Scenes
senderUserInfo.DeleteItem(itemId); senderUserInfo.DeleteItem(itemId);
} }
// Let the recipient client know about this new item return itemCopy;
recipientClient.SendBulkUpdateInventory(itemCopy);
} }
else else
{ {
m_log.ErrorFormat( m_log.ErrorFormat(
"[AGENT INVENTORY]: Could not find userinfo for recipient user {0}, {1} of item {2}, {3} from {4}", "[AGENT INVENTORY]: Could not find userinfo for recipient user {0} of item {1}, {2} from {3}",
recipientClient.Name, recipientClient.AgentId, item.Name, recipient, item.Name,
item.ID, senderId); item.ID, senderId);
} }
} }
@ -509,14 +519,15 @@ namespace OpenSim.Region.Environment.Scenes
m_log.ErrorFormat( m_log.ErrorFormat(
"[AGENT INVENTORY]: Failed to find item {0} to give to {1}", itemId, senderId); "[AGENT INVENTORY]: Failed to find item {0} to give to {1}", itemId, senderId);
return; return null;
} }
} }
else else
{ {
m_log.Error("[AGENT INVENTORY]: Failed to find item " + itemId.ToString() + ", no root folder"); 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, public void CopyInventoryItem(IClientAPI remoteClient, uint callbackID, UUID oldAgentID, UUID oldItemID,