diff options
author | Melanie Thielker | 2008-11-12 06:22:31 +0000 |
---|---|---|
committer | Melanie Thielker | 2008-11-12 06:22:31 +0000 |
commit | c71f0899c255c9415210662273365cad83e40c0e (patch) | |
tree | c5f0e684a95c89462229dd6149d84b6b458ed169 | |
parent | * Set defaults on the allowed LSL Compilers to 'lsl' unless you've specified ... (diff) | |
download | opensim-SC-c71f0899c255c9415210662273365cad83e40c0e.zip opensim-SC-c71f0899c255c9415210662273365cad83e40c0e.tar.gz opensim-SC-c71f0899c255c9415210662273365cad83e40c0e.tar.bz2 opensim-SC-c71f0899c255c9415210662273365cad83e40c0e.tar.xz |
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.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs | 216 | ||||
-rw-r--r-- | OpenSim/Region/Environment/Scenes/Scene.Inventory.cs | 31 |
2 files changed, 138 insertions, 109 deletions
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 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | ||
29 | using System.Collections; | ||
28 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
29 | using System.Reflection; | 31 | using System.Reflection; |
30 | using OpenMetaverse; | 32 | using OpenMetaverse; |
@@ -33,6 +35,7 @@ using Nini.Config; | |||
33 | using OpenSim.Framework; | 35 | using OpenSim.Framework; |
34 | using OpenSim.Region.Environment.Interfaces; | 36 | using OpenSim.Region.Environment.Interfaces; |
35 | using OpenSim.Region.Environment.Scenes; | 37 | using OpenSim.Region.Environment.Scenes; |
38 | using OpenSim.Framework.Communications.Cache; | ||
36 | 39 | ||
37 | namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer | 40 | namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer |
38 | { | 41 | { |
@@ -42,14 +45,9 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer | |||
42 | = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 45 | = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
43 | 46 | ||
44 | /// <summary> | 47 | /// <summary> |
45 | /// We need to keep track of the pending item offers between clients since the itemId offered only | ||
46 | /// occurs in the initial offer message, not the accept message. So this dictionary links | ||
47 | /// IM Session Ids to ItemIds | ||
48 | /// </summary> | ||
49 | private IDictionary<UUID, UUID> m_pendingOffers = new Dictionary<UUID, UUID>(); | ||
50 | |||
51 | private List<Scene> m_Scenelist = new List<Scene>(); | 48 | private List<Scene> m_Scenelist = new List<Scene>(); |
52 | private Dictionary<UUID, Scene> m_AgentRegions = new Dictionary<UUID, Scene>(); | 49 | private Dictionary<UUID, Scene> m_AgentRegions = |
50 | new Dictionary<UUID, Scene>(); | ||
53 | 51 | ||
54 | #region IRegionModule Members | 52 | #region IRegionModule Members |
55 | 53 | ||
@@ -64,6 +62,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer | |||
64 | "InventoryTransferModule") | 62 | "InventoryTransferModule") |
65 | return; | 63 | return; |
66 | } | 64 | } |
65 | |||
67 | if (!m_Scenelist.Contains(scene)) | 66 | if (!m_Scenelist.Contains(scene)) |
68 | { | 67 | { |
69 | m_Scenelist.Add(scene); | 68 | m_Scenelist.Add(scene); |
@@ -101,136 +100,155 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer | |||
101 | client.OnInstantMessage += OnInstantMessage; | 100 | client.OnInstantMessage += OnInstantMessage; |
102 | } | 101 | } |
103 | 102 | ||
103 | private Scene FindClientScene(UUID agentId) | ||
104 | { | ||
105 | lock (m_Scenelist) | ||
106 | { | ||
107 | foreach (Scene scene in m_Scenelist) | ||
108 | { | ||
109 | ScenePresence presence = scene.GetScenePresence(agentId); | ||
110 | if (presence != null) | ||
111 | { | ||
112 | if (!presence.IsChildAgent) | ||
113 | return scene; | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | return null; | ||
118 | } | ||
119 | |||
104 | private void OnInstantMessage(IClientAPI client, UUID fromAgentID, | 120 | private void OnInstantMessage(IClientAPI client, UUID fromAgentID, |
105 | UUID fromAgentSession, UUID toAgentID, | 121 | UUID fromAgentSession, UUID toAgentID, |
106 | UUID imSessionID, uint timestamp, string fromAgentName, | 122 | UUID imSessionID, uint timestamp, string fromAgentName, |
107 | string message, byte dialog, bool fromGroup, byte offline, | 123 | string message, byte dialog, bool fromGroup, byte offline, |
108 | uint ParentEstateID, Vector3 Position, UUID RegionID, | 124 | uint ParentEstateID, Vector3 Position, UUID RegionID, |
109 | byte[] binaryBucket) | 125 | byte[] binaryBucket) |
110 | { | 126 | { |
127 | Scene scene = FindClientScene(client.AgentId); | ||
128 | |||
129 | if (scene == null) // Something seriously wrong here. | ||
130 | return; | ||
131 | |||
111 | if (dialog == (byte) InstantMessageDialog.InventoryOffered) | 132 | if (dialog == (byte) InstantMessageDialog.InventoryOffered) |
112 | { | 133 | { |
113 | m_log.DebugFormat( | 134 | ScenePresence user = |
114 | "[AGENT INVENTORY]: Routing inventory offering message from {0}, {1} to {2}", | 135 | scene.GetScenePresence(toAgentID); |
115 | client.AgentId, client.Name, toAgentID); | ||
116 | 136 | ||
117 | if (((Scene)(client.Scene)).Entities.ContainsKey(toAgentID) && ((Scene)(client.Scene)).Entities[toAgentID] is ScenePresence) | 137 | // First byte of the array is probably the item type |
118 | { | 138 | // Next 16 bytes are the UUID |
119 | ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID]; | ||
120 | 139 | ||
121 | if (!user.IsChildAgent) | 140 | UUID itemID = new UUID(binaryBucket, 1); |
122 | { | ||
123 | //byte[] rawId = new byte[16]; | ||
124 | 141 | ||
125 | // First byte of the array is probably the item type | 142 | m_log.DebugFormat("[AGENT INVENTORY]: Inserting item {0} "+ |
126 | // Next 16 bytes are the UUID | 143 | "into agent {1}'s inventory", |
127 | //Array.Copy(binaryBucket, 1, rawId, 0, 16); | 144 | itemID, toAgentID); |
128 | 145 | ||
129 | //UUID itemId = new UUID(new Guid(rawId)); | 146 | InventoryItemBase itemCopy = scene.GiveInventoryItem(toAgentID, |
130 | UUID itemId = new UUID(binaryBucket, 1); | 147 | client.AgentId, itemID); |
131 | 148 | ||
132 | m_log.DebugFormat( | 149 | byte[] itemCopyID = itemCopy.ID.GetBytes(); |
133 | "[AGENT INVENTORY]: ItemId for giving is {0}", itemId); | ||
134 | 150 | ||
135 | m_pendingOffers[imSessionID] = itemId; | 151 | Array.Copy(itemCopyID, 0, binaryBucket, 1, 16); |
136 | 152 | ||
137 | user.ControllingClient.SendInstantMessage( | 153 | // Send the IM to the recipient. The item is already |
154 | // in their inventory, so it will not be lost if | ||
155 | // they are offline. | ||
156 | // | ||
157 | if (user != null && !user.IsChildAgent) | ||
158 | { | ||
159 | // User is online. So, let's make the item visible | ||
160 | // | ||
161 | user.ControllingClient.SendBulkUpdateInventory(itemCopy); | ||
162 | |||
163 | // And notify. Transaction ID is the item ID. We get that | ||
164 | // same ID back on the reply so we know what to act on | ||
165 | // | ||
166 | user.ControllingClient.SendInstantMessage( | ||
138 | fromAgentID, message, toAgentID, fromAgentName, | 167 | fromAgentID, message, toAgentID, fromAgentName, |
139 | dialog, timestamp, UUID.Zero, false, binaryBucket); | 168 | dialog, timestamp, itemCopy.ID, false, |
169 | binaryBucket); | ||
140 | 170 | ||
141 | return; | 171 | return; |
142 | } | ||
143 | else | ||
144 | { | ||
145 | m_log.WarnFormat( | ||
146 | "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!", | ||
147 | toAgentID, client.AgentId, client.Name, message); | ||
148 | } | ||
149 | } | 172 | } |
150 | else | 173 | else |
151 | { | 174 | { |
152 | m_log.WarnFormat( | 175 | // Send via grid services |
153 | "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}", | 176 | // |
154 | toAgentID, client.AgentId, client.Name, message); | 177 | // TODO: Implement grid sending |
155 | } | 178 | } |
156 | } | 179 | } |
157 | else if (dialog == (byte) InstantMessageDialog.InventoryAccepted) | 180 | else if (dialog == (byte) InstantMessageDialog.InventoryAccepted) |
158 | { | 181 | { |
159 | m_log.DebugFormat( | 182 | ScenePresence user = scene.GetScenePresence(toAgentID); |
160 | "[AGENT INVENTORY]: Routing inventory accepted message from {0}, {1} to {2}", | ||
161 | client.AgentId, client.Name, toAgentID); | ||
162 | 183 | ||
163 | if (((Scene)(client.Scene)).Entities.ContainsKey(toAgentID) && ((Scene)(client.Scene)).Entities[toAgentID] is ScenePresence) | 184 | if (user != null) // Local |
164 | { | 185 | { |
165 | ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID]; | 186 | user.ControllingClient.SendInstantMessage( |
166 | |||
167 | if (!user.IsChildAgent) | ||
168 | { | ||
169 | user.ControllingClient.SendInstantMessage( | ||
170 | fromAgentID, message, toAgentID, fromAgentName, | 187 | fromAgentID, message, toAgentID, fromAgentName, |
171 | dialog, timestamp, UUID.Zero, false, binaryBucket); | 188 | dialog, timestamp, UUID.Zero, false, binaryBucket); |
172 | |||
173 | if (m_pendingOffers.ContainsKey(imSessionID)) | ||
174 | { | ||
175 | m_log.DebugFormat( | ||
176 | "[AGENT INVENTORY]: Accepted item id {0}", m_pendingOffers[imSessionID]); | ||
177 | |||
178 | // Since the message originates from the accepting client, the toAgentID is | ||
179 | // the agent giving the item. | ||
180 | ((Scene)(client.Scene)).GiveInventoryItem(client, toAgentID, m_pendingOffers[imSessionID]); | ||
181 | |||
182 | m_pendingOffers.Remove(imSessionID); | ||
183 | } | ||
184 | else | ||
185 | { | ||
186 | m_log.ErrorFormat( | ||
187 | "[AGENT INVENTORY]: Could not find an item associated with session id {0} to accept", | ||
188 | imSessionID); | ||
189 | } | ||
190 | |||
191 | return; | ||
192 | } | ||
193 | else | ||
194 | { | ||
195 | m_log.WarnFormat( | ||
196 | "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!", | ||
197 | toAgentID, client.AgentId, client.Name, message); | ||
198 | } | ||
199 | } | 189 | } |
200 | else | 190 | else |
201 | { | 191 | { |
202 | m_log.WarnFormat( | 192 | // Send via grid |
203 | "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}", | 193 | // |
204 | toAgentID, client.AgentId, client.Name, message); | 194 | // TODO: Implement sending via grid |
205 | } | 195 | } |
206 | } | 196 | } |
207 | else if (dialog == (byte) InstantMessageDialog.InventoryDeclined) | 197 | else if (dialog == (byte) InstantMessageDialog.InventoryDeclined) |
208 | { | 198 | { |
209 | if (((Scene)(client.Scene)).Entities.ContainsKey(toAgentID) && ((Scene)(client.Scene)).Entities[toAgentID] is ScenePresence) | 199 | UUID itemID = imSessionID; // The item, back from it's trip |
200 | |||
201 | // Here, the recipient is local and we can assume that the | ||
202 | // inventory is loaded. Courtesy of the above bulk update, | ||
203 | // It will have been pushed to the client, too | ||
204 | // | ||
205 | |||
206 | CachedUserInfo userInfo = | ||
207 | scene.CommsManager.UserProfileCacheService. | ||
208 | GetUserDetails(client.AgentId); | ||
209 | |||
210 | if (userInfo != null) | ||
210 | { | 211 | { |
211 | ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID]; | 212 | InventoryFolderImpl trashFolder = |
213 | userInfo.FindFolderForType((int)AssetType.TrashFolder); | ||
212 | 214 | ||
213 | if (!user.IsChildAgent) | 215 | InventoryItemBase item = |
216 | userInfo.RootFolder.FindItem(itemID); | ||
217 | |||
218 | if (trashFolder != null && item != null) | ||
214 | { | 219 | { |
215 | user.ControllingClient.SendInstantMessage( | 220 | item.Folder = trashFolder.ID; |
216 | fromAgentID, message, toAgentID, fromAgentName, | ||
217 | dialog, timestamp, UUID.Zero, false, binaryBucket); | ||
218 | 221 | ||
219 | if (m_pendingOffers.ContainsKey(imSessionID)) | 222 | userInfo.DeleteItem(itemID); |
220 | { | ||
221 | m_log.DebugFormat( | ||
222 | "[AGENT INVENTORY]: Declined item id {0}", m_pendingOffers[imSessionID]); | ||
223 | 223 | ||
224 | m_pendingOffers.Remove(imSessionID); | 224 | scene.AddInventoryItem(client, item); |
225 | } | 225 | } |
226 | else | 226 | else |
227 | { | 227 | { |
228 | m_log.ErrorFormat( | 228 | string reason = ""; |
229 | "[AGENT INVENTORY]: Could not find an item associated with session id {0} to decline", | 229 | if (trashFolder == null) |
230 | imSessionID); | 230 | reason += " Trash folder not found."; |
231 | } | 231 | if (item == null) |
232 | reason += " Item not found."; | ||
233 | client.SendAgentAlertMessage("Unable to delete "+ | ||
234 | "received item"+reason, false); | ||
232 | } | 235 | } |
233 | } | 236 | } |
237 | |||
238 | ScenePresence user = scene.GetScenePresence(toAgentID); | ||
239 | |||
240 | if (user != null) // Local | ||
241 | { | ||
242 | user.ControllingClient.SendInstantMessage( | ||
243 | fromAgentID, message, toAgentID, fromAgentName, | ||
244 | dialog, timestamp, UUID.Zero, false, binaryBucket); | ||
245 | } | ||
246 | else | ||
247 | { | ||
248 | // Send via grid | ||
249 | // | ||
250 | // TODO: Implement sending via grid | ||
251 | } | ||
234 | } | 252 | } |
235 | } | 253 | } |
236 | 254 | ||
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 | |||
407 | /// <param name="itemId"></param> | 407 | /// <param name="itemId"></param> |
408 | public virtual void GiveInventoryItem(IClientAPI recipientClient, UUID senderId, UUID itemId) | 408 | public virtual void GiveInventoryItem(IClientAPI recipientClient, UUID senderId, UUID itemId) |
409 | { | 409 | { |
410 | InventoryItemBase itemCopy = GiveInventoryItem(recipientClient.AgentId, senderId, itemId); | ||
411 | |||
412 | if (itemCopy != null) | ||
413 | recipientClient.SendBulkUpdateInventory(itemCopy); | ||
414 | } | ||
415 | |||
416 | public virtual InventoryItemBase GiveInventoryItem(UUID recipient, UUID senderId, UUID itemId) | ||
417 | { | ||
410 | // Retrieve the item from the sender | 418 | // Retrieve the item from the sender |
411 | CachedUserInfo senderUserInfo = CommsManager.UserProfileCacheService.GetUserDetails(senderId); | 419 | CachedUserInfo senderUserInfo = CommsManager.UserProfileCacheService.GetUserDetails(senderId); |
412 | 420 | ||
@@ -415,7 +423,7 @@ namespace OpenSim.Region.Environment.Scenes | |||
415 | m_log.ErrorFormat( | 423 | m_log.ErrorFormat( |
416 | "[AGENT INVENTORY]: Failed to find sending user {0} for item {1}", senderId, itemId); | 424 | "[AGENT INVENTORY]: Failed to find sending user {0} for item {1}", senderId, itemId); |
417 | 425 | ||
418 | return; | 426 | return null; |
419 | } | 427 | } |
420 | 428 | ||
421 | if (senderUserInfo.RootFolder != null) | 429 | if (senderUserInfo.RootFolder != null) |
@@ -427,18 +435,21 @@ namespace OpenSim.Region.Environment.Scenes | |||
427 | if (!ExternalChecks.ExternalChecksBypassPermissions()) | 435 | if (!ExternalChecks.ExternalChecksBypassPermissions()) |
428 | { | 436 | { |
429 | if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) | 437 | if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) |
430 | return; | 438 | return null; |
431 | } | 439 | } |
432 | 440 | ||
433 | // TODO get recipient's root folder | 441 | // TODO get recipient's root folder |
434 | CachedUserInfo recipientUserInfo | 442 | CachedUserInfo recipientUserInfo |
435 | = CommsManager.UserProfileCacheService.GetUserDetails(recipientClient.AgentId); | 443 | = CommsManager.UserProfileCacheService.GetUserDetails(recipient); |
436 | 444 | ||
437 | if (recipientUserInfo != null) | 445 | if (recipientUserInfo != null) |
438 | { | 446 | { |
447 | if (!recipientUserInfo.HasReceivedInventory) | ||
448 | CommsManager.UserProfileCacheService.RequestInventoryForUser(recipient); | ||
449 | |||
439 | // Insert a copy of the item into the recipient | 450 | // Insert a copy of the item into the recipient |
440 | InventoryItemBase itemCopy = new InventoryItemBase(); | 451 | InventoryItemBase itemCopy = new InventoryItemBase(); |
441 | itemCopy.Owner = recipientClient.AgentId; | 452 | itemCopy.Owner = recipient; |
442 | itemCopy.Creator = item.Creator; | 453 | itemCopy.Creator = item.Creator; |
443 | itemCopy.ID = UUID.Random(); | 454 | itemCopy.ID = UUID.Random(); |
444 | itemCopy.AssetID = item.AssetID; | 455 | itemCopy.AssetID = item.AssetID; |
@@ -493,14 +504,13 @@ namespace OpenSim.Region.Environment.Scenes | |||
493 | senderUserInfo.DeleteItem(itemId); | 504 | senderUserInfo.DeleteItem(itemId); |
494 | } | 505 | } |
495 | 506 | ||
496 | // Let the recipient client know about this new item | 507 | return itemCopy; |
497 | recipientClient.SendBulkUpdateInventory(itemCopy); | ||
498 | } | 508 | } |
499 | else | 509 | else |
500 | { | 510 | { |
501 | m_log.ErrorFormat( | 511 | m_log.ErrorFormat( |
502 | "[AGENT INVENTORY]: Could not find userinfo for recipient user {0}, {1} of item {2}, {3} from {4}", | 512 | "[AGENT INVENTORY]: Could not find userinfo for recipient user {0} of item {1}, {2} from {3}", |
503 | recipientClient.Name, recipientClient.AgentId, item.Name, | 513 | recipient, item.Name, |
504 | item.ID, senderId); | 514 | item.ID, senderId); |
505 | } | 515 | } |
506 | } | 516 | } |
@@ -509,14 +519,15 @@ namespace OpenSim.Region.Environment.Scenes | |||
509 | m_log.ErrorFormat( | 519 | m_log.ErrorFormat( |
510 | "[AGENT INVENTORY]: Failed to find item {0} to give to {1}", itemId, senderId); | 520 | "[AGENT INVENTORY]: Failed to find item {0} to give to {1}", itemId, senderId); |
511 | 521 | ||
512 | return; | 522 | return null; |
513 | } | 523 | } |
514 | } | 524 | } |
515 | else | 525 | else |
516 | { | 526 | { |
517 | m_log.Error("[AGENT INVENTORY]: Failed to find item " + itemId.ToString() + ", no root folder"); | 527 | m_log.Error("[AGENT INVENTORY]: Failed to find item " + itemId.ToString() + ", no root folder"); |
518 | return; | 528 | return null; |
519 | } | 529 | } |
530 | return null; | ||
520 | } | 531 | } |
521 | 532 | ||
522 | public void CopyInventoryItem(IClientAPI remoteClient, uint callbackID, UUID oldAgentID, UUID oldItemID, | 533 | public void CopyInventoryItem(IClientAPI remoteClient, uint callbackID, UUID oldAgentID, UUID oldItemID, |