aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs')
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs288
1 files changed, 288 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
new file mode 100644
index 0000000..ed58338
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -0,0 +1,288 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Collections.Generic;
29using System.Reflection;
30using OpenMetaverse;
31using log4net;
32using Nini.Config;
33using OpenSim.Framework;
34using OpenSim.Region.Environment.Interfaces;
35using OpenSim.Region.Environment.Scenes;
36
37namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer
38{
39 public class InventoryTransferModule : IInventoryTransferModule, IRegionModule
40 {
41 private static readonly ILog m_log
42 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 /// <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>();
52 private Dictionary<UUID, Scene> m_AgentRegions = new Dictionary<UUID, Scene>();
53
54 #region IRegionModule Members
55
56 public void Initialise(Scene scene, IConfigSource config)
57 {
58 if (!m_Scenelist.Contains(scene))
59 {
60 m_Scenelist.Add(scene);
61
62 scene.RegisterModuleInterface<IInventoryTransferModule>(this);
63
64 scene.EventManager.OnNewClient += OnNewClient;
65 scene.EventManager.OnClientClosed += ClientLoggedOut;
66 }
67 }
68
69 public void PostInitialise()
70 {
71 }
72
73 public void Close()
74 {
75 }
76
77 public string Name
78 {
79 get { return "InventoryModule"; }
80 }
81
82 public bool IsSharedModule
83 {
84 get { return true; }
85 }
86
87 #endregion
88
89 private void OnNewClient(IClientAPI client)
90 {
91 // Inventory giving is conducted via instant message
92 client.OnInstantMessage += OnInstantMessage;
93 }
94
95 private void OnInstantMessage(IClientAPI client, UUID fromAgentID,
96 UUID fromAgentSession, UUID toAgentID,
97 UUID imSessionID, uint timestamp, string fromAgentName,
98 string message, byte dialog, bool fromGroup, byte offline,
99 uint ParentEstateID, Vector3 Position, UUID RegionID,
100 byte[] binaryBucket)
101 {
102 if (dialog == (byte) InstantMessageDialog.InventoryOffered)
103 {
104 m_log.DebugFormat(
105 "[AGENT INVENTORY]: Routing inventory offering message from {0}, {1} to {2}",
106 client.AgentId, client.Name, toAgentID);
107
108 if (((Scene)(client.Scene)).Entities.ContainsKey(toAgentID) && ((Scene)(client.Scene)).Entities[toAgentID] is ScenePresence)
109 {
110 ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID];
111
112 if (!user.IsChildAgent)
113 {
114 //byte[] rawId = new byte[16];
115
116 // First byte of the array is probably the item type
117 // Next 16 bytes are the UUID
118 //Array.Copy(binaryBucket, 1, rawId, 0, 16);
119
120 //UUID itemId = new UUID(new Guid(rawId));
121 UUID itemId = new UUID(binaryBucket, 1);
122
123 m_log.DebugFormat(
124 "[AGENT INVENTORY]: ItemId for giving is {0}", itemId);
125
126 m_pendingOffers[imSessionID] = itemId;
127
128 user.ControllingClient.SendInstantMessage(
129 fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName,
130 dialog, timestamp, binaryBucket);
131
132 return;
133 }
134 else
135 {
136 m_log.WarnFormat(
137 "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!",
138 toAgentID, client.AgentId, client.Name, message);
139 }
140 }
141 else
142 {
143 m_log.WarnFormat(
144 "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}",
145 toAgentID, client.AgentId, client.Name, message);
146 }
147 }
148 else if (dialog == (byte) InstantMessageDialog.InventoryAccepted)
149 {
150 m_log.DebugFormat(
151 "[AGENT INVENTORY]: Routing inventory accepted message from {0}, {1} to {2}",
152 client.AgentId, client.Name, toAgentID);
153
154 if (((Scene)(client.Scene)).Entities.ContainsKey(toAgentID) && ((Scene)(client.Scene)).Entities[toAgentID] is ScenePresence)
155 {
156 ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID];
157
158 if (!user.IsChildAgent)
159 {
160 user.ControllingClient.SendInstantMessage(
161 fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName,
162 dialog, timestamp, binaryBucket);
163
164 if (m_pendingOffers.ContainsKey(imSessionID))
165 {
166 m_log.DebugFormat(
167 "[AGENT INVENTORY]: Accepted item id {0}", m_pendingOffers[imSessionID]);
168
169 // Since the message originates from the accepting client, the toAgentID is
170 // the agent giving the item.
171 ((Scene)(client.Scene)).GiveInventoryItem(client, toAgentID, m_pendingOffers[imSessionID]);
172
173 m_pendingOffers.Remove(imSessionID);
174 }
175 else
176 {
177 m_log.ErrorFormat(
178 "[AGENT INVENTORY]: Could not find an item associated with session id {0} to accept",
179 imSessionID);
180 }
181
182 return;
183 }
184 else
185 {
186 m_log.WarnFormat(
187 "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!",
188 toAgentID, client.AgentId, client.Name, message);
189 }
190 }
191 else
192 {
193 m_log.WarnFormat(
194 "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}",
195 toAgentID, client.AgentId, client.Name, message);
196 }
197 }
198 else if (dialog == (byte) InstantMessageDialog.InventoryDeclined)
199 {
200 if (((Scene)(client.Scene)).Entities.ContainsKey(toAgentID) && ((Scene)(client.Scene)).Entities[toAgentID] is ScenePresence)
201 {
202 ScenePresence user = (ScenePresence) ((Scene)(client.Scene)).Entities[toAgentID];
203
204 if (!user.IsChildAgent)
205 {
206 user.ControllingClient.SendInstantMessage(
207 fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName,
208 dialog, timestamp, binaryBucket);
209
210 if (m_pendingOffers.ContainsKey(imSessionID))
211 {
212 m_log.DebugFormat(
213 "[AGENT INVENTORY]: Declined item id {0}", m_pendingOffers[imSessionID]);
214
215 m_pendingOffers.Remove(imSessionID);
216 }
217 else
218 {
219 m_log.ErrorFormat(
220 "[AGENT INVENTORY]: Could not find an item associated with session id {0} to decline",
221 imSessionID);
222 }
223 }
224 }
225 }
226 }
227
228 public void SetRootAgentScene(UUID agentID, Scene scene)
229 {
230 m_AgentRegions[agentID] = scene;
231 }
232
233 public bool NeedSceneCacheClear(UUID agentID, Scene scene)
234 {
235 if (!m_AgentRegions.ContainsKey(agentID))
236 {
237 // Since we can get here two ways, we need to scan
238 // the scenes here. This is somewhat more expensive
239 // but helps avoid a nasty bug
240 //
241
242 foreach (Scene s in m_Scenelist)
243 {
244 ScenePresence presence;
245
246 if (s.TryGetAvatar(agentID, out presence))
247 {
248 // If the agent is in this scene, then we
249 // are being called twice in a single
250 // teleport. This is wasteful of cycles
251 // but harmless due to this 2nd level check
252 //
253 // If the agent is found in another scene
254 // then the list wasn't current
255 //
256 // If the agent is totally unknown, then what
257 // are we even doing here??
258 //
259 if (s == scene)
260 return true;
261 else
262 return false;
263 }
264 }
265 return true;
266 }
267
268 // The agent is left in current Scene, so we must be
269 // going to another instance
270 //
271 if (m_AgentRegions[agentID] == scene)
272 {
273 m_AgentRegions.Remove(agentID);
274 return true;
275 }
276
277 // Another region has claimed the agent
278 //
279 return false;
280 }
281
282 public void ClientLoggedOut(UUID agentID)
283 {
284 if (m_AgentRegions.ContainsKey(agentID))
285 m_AgentRegions.Remove(agentID);
286 }
287 }
288}