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
parent
c453a41fb5
commit
c71f0899c2
|
@ -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,6 +100,23 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer
|
||||||
client.OnInstantMessage += OnInstantMessage;
|
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,
|
private void OnInstantMessage(IClientAPI client, UUID fromAgentID,
|
||||||
UUID fromAgentSession, UUID toAgentID,
|
UUID fromAgentSession, UUID toAgentID,
|
||||||
UUID imSessionID, uint timestamp, string fromAgentName,
|
UUID imSessionID, uint timestamp, string fromAgentName,
|
||||||
|
@ -108,128 +124,130 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer
|
||||||
uint ParentEstateID, Vector3 Position, UUID RegionID,
|
uint ParentEstateID, Vector3 Position, UUID RegionID,
|
||||||
byte[] binaryBucket)
|
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)
|
|
||||||
{
|
|
||||||
ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID];
|
|
||||||
|
|
||||||
if (!user.IsChildAgent)
|
|
||||||
{
|
|
||||||
//byte[] rawId = new byte[16];
|
|
||||||
|
|
||||||
// First byte of the array is probably the item type
|
// First byte of the array is probably the item type
|
||||||
// Next 16 bytes are the UUID
|
// 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(
|
m_log.DebugFormat("[AGENT INVENTORY]: Inserting item {0} "+
|
||||||
"[AGENT INVENTORY]: ItemId for giving is {0}", itemId);
|
"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(
|
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
|
else
|
||||||
{
|
{
|
||||||
m_log.WarnFormat(
|
// Send via grid services
|
||||||
"[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!",
|
//
|
||||||
toAgentID, client.AgentId, client.Name, message);
|
// TODO: Implement grid sending
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_log.WarnFormat(
|
|
||||||
"[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}",
|
|
||||||
toAgentID, client.AgentId, client.Name, message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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];
|
|
||||||
|
|
||||||
if (!user.IsChildAgent)
|
|
||||||
{
|
{
|
||||||
user.ControllingClient.SendInstantMessage(
|
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
|
else
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat(
|
// Send via grid
|
||||||
"[AGENT INVENTORY]: Could not find an item associated with session id {0} to accept",
|
//
|
||||||
imSessionID);
|
// TODO: Implement sending via grid
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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)
|
||||||
|
{
|
||||||
|
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(
|
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]: Declined item id {0}", m_pendingOffers[imSessionID]);
|
|
||||||
|
|
||||||
m_pendingOffers.Remove(imSessionID);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat(
|
// Send via grid
|
||||||
"[AGENT INVENTORY]: Could not find an item associated with session id {0} to decline",
|
//
|
||||||
imSessionID);
|
// TODO: Implement sending via grid
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue