diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs new file mode 100644 index 0000000..81cef5b --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs | |||
@@ -0,0 +1,429 @@ | |||
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 OpenSimulator 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 | |||
28 | using System; | ||
29 | using System.IO; | ||
30 | using System.Reflection; | ||
31 | using OpenMetaverse; | ||
32 | using log4net; | ||
33 | using OpenSim.Framework; | ||
34 | using OpenSim.Region.Framework.Interfaces; | ||
35 | using System.Collections.Generic; | ||
36 | using System.Xml; | ||
37 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
38 | |||
39 | namespace OpenSim.Region.Framework.Scenes | ||
40 | { | ||
41 | public partial class SceneObjectGroup : EntityBase | ||
42 | { | ||
43 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
44 | |||
45 | /// <summary> | ||
46 | /// Force all task inventories of prims in the scene object to persist | ||
47 | /// </summary> | ||
48 | public void ForceInventoryPersistence() | ||
49 | { | ||
50 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
51 | for (int i = 0; i < parts.Length; i++) | ||
52 | parts[i].Inventory.ForceInventoryPersistence(); | ||
53 | } | ||
54 | |||
55 | /// <summary> | ||
56 | /// Start the scripts contained in all the prims in this group. | ||
57 | /// </summary> | ||
58 | /// <param name="startParam"></param> | ||
59 | /// <param name="postOnRez"></param> | ||
60 | /// <param name="engine"></param> | ||
61 | /// <param name="stateSource"></param> | ||
62 | /// <returns> | ||
63 | /// Number of scripts that were valid for starting. This does not guarantee that all these scripts | ||
64 | /// were actually started, but just that the start could be attempt (e.g. the asset data for the script could be found) | ||
65 | /// </returns> | ||
66 | public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) | ||
67 | { | ||
68 | int scriptsStarted = 0; | ||
69 | |||
70 | if (m_scene == null) | ||
71 | { | ||
72 | m_log.DebugFormat("[PRIM INVENTORY]: m_scene is null. Unable to create script instances"); | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | // Don't start scripts if they're turned off in the region! | ||
77 | if (!m_scene.RegionInfo.RegionSettings.DisableScripts) | ||
78 | { | ||
79 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
80 | for (int i = 0; i < parts.Length; i++) | ||
81 | scriptsStarted | ||
82 | += parts[i].Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource); | ||
83 | } | ||
84 | |||
85 | return scriptsStarted; | ||
86 | } | ||
87 | |||
88 | /// <summary> | ||
89 | /// Stop and remove the scripts contained in all the prims in this group | ||
90 | /// </summary> | ||
91 | /// <param name="sceneObjectBeingDeleted"> | ||
92 | /// Should be true if these scripts are being removed because the scene | ||
93 | /// object is being deleted. This will prevent spurious updates to the client. | ||
94 | /// </param> | ||
95 | public void RemoveScriptInstances(bool sceneObjectBeingDeleted) | ||
96 | { | ||
97 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
98 | for (int i = 0; i < parts.Length; i++) | ||
99 | parts[i].Inventory.RemoveScriptInstances(sceneObjectBeingDeleted); | ||
100 | } | ||
101 | |||
102 | /// <summary> | ||
103 | /// Stop the scripts contained in all the prims in this group | ||
104 | /// </summary> | ||
105 | public void StopScriptInstances() | ||
106 | { | ||
107 | Array.ForEach<SceneObjectPart>(m_parts.GetArray(), p => p.Inventory.StopScriptInstances()); | ||
108 | } | ||
109 | |||
110 | /// <summary> | ||
111 | /// Add an inventory item from a user's inventory to a prim in this scene object. | ||
112 | /// </summary> | ||
113 | /// <param name="agentID">The agent adding the item.</param> | ||
114 | /// <param name="localID">The local ID of the part receiving the add.</param> | ||
115 | /// <param name="item">The user inventory item being added.</param> | ||
116 | /// <param name="copyItemID">The item UUID that should be used by the new item.</param> | ||
117 | /// <returns></returns> | ||
118 | public bool AddInventoryItem(UUID agentID, uint localID, InventoryItemBase item, UUID copyItemID) | ||
119 | { | ||
120 | // m_log.DebugFormat( | ||
121 | // "[PRIM INVENTORY]: Adding inventory item {0} from {1} to part with local ID {2}", | ||
122 | // item.Name, remoteClient.Name, localID); | ||
123 | |||
124 | UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID; | ||
125 | |||
126 | SceneObjectPart part = GetPart(localID); | ||
127 | if (part != null) | ||
128 | { | ||
129 | TaskInventoryItem taskItem = new TaskInventoryItem(); | ||
130 | |||
131 | taskItem.ItemID = newItemId; | ||
132 | taskItem.AssetID = item.AssetID; | ||
133 | taskItem.Name = item.Name; | ||
134 | taskItem.Description = item.Description; | ||
135 | taskItem.OwnerID = part.OwnerID; // Transfer ownership | ||
136 | taskItem.CreatorID = item.CreatorIdAsUuid; | ||
137 | taskItem.Type = item.AssetType; | ||
138 | taskItem.InvType = item.InvType; | ||
139 | |||
140 | if (agentID != part.OwnerID && m_scene.Permissions.PropagatePermissions()) | ||
141 | { | ||
142 | taskItem.BasePermissions = item.BasePermissions & | ||
143 | item.NextPermissions; | ||
144 | taskItem.CurrentPermissions = item.CurrentPermissions & | ||
145 | item.NextPermissions; | ||
146 | taskItem.EveryonePermissions = item.EveryOnePermissions & | ||
147 | item.NextPermissions; | ||
148 | taskItem.GroupPermissions = item.GroupPermissions & | ||
149 | item.NextPermissions; | ||
150 | taskItem.NextPermissions = item.NextPermissions; | ||
151 | // We're adding this to a prim we don't own. Force | ||
152 | // owner change | ||
153 | taskItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; | ||
154 | } | ||
155 | else | ||
156 | { | ||
157 | taskItem.BasePermissions = item.BasePermissions; | ||
158 | taskItem.CurrentPermissions = item.CurrentPermissions; | ||
159 | taskItem.EveryonePermissions = item.EveryOnePermissions; | ||
160 | taskItem.GroupPermissions = item.GroupPermissions; | ||
161 | taskItem.NextPermissions = item.NextPermissions; | ||
162 | } | ||
163 | |||
164 | taskItem.Flags = item.Flags; | ||
165 | |||
166 | // m_log.DebugFormat( | ||
167 | // "[PRIM INVENTORY]: Flags are 0x{0:X} for item {1} added to part {2} by {3}", | ||
168 | // taskItem.Flags, taskItem.Name, localID, remoteClient.Name); | ||
169 | |||
170 | // TODO: These are pending addition of those fields to TaskInventoryItem | ||
171 | // taskItem.SalePrice = item.SalePrice; | ||
172 | // taskItem.SaleType = item.SaleType; | ||
173 | taskItem.CreationDate = (uint)item.CreationDate; | ||
174 | |||
175 | bool addFromAllowedDrop = agentID != part.OwnerID; | ||
176 | |||
177 | part.Inventory.AddInventoryItem(taskItem, addFromAllowedDrop); | ||
178 | |||
179 | return true; | ||
180 | } | ||
181 | else | ||
182 | { | ||
183 | m_log.ErrorFormat( | ||
184 | "[PRIM INVENTORY]: " + | ||
185 | "Couldn't find prim local ID {0} in group {1}, {2} to add inventory item ID {3}", | ||
186 | localID, Name, UUID, newItemId); | ||
187 | } | ||
188 | |||
189 | return false; | ||
190 | } | ||
191 | |||
192 | /// <summary> | ||
193 | /// Returns an existing inventory item. Returns the original, so any changes will be live. | ||
194 | /// </summary> | ||
195 | /// <param name="primID"></param> | ||
196 | /// <param name="itemID"></param> | ||
197 | /// <returns>null if the item does not exist</returns> | ||
198 | public TaskInventoryItem GetInventoryItem(uint primID, UUID itemID) | ||
199 | { | ||
200 | SceneObjectPart part = GetPart(primID); | ||
201 | if (part != null) | ||
202 | { | ||
203 | return part.Inventory.GetInventoryItem(itemID); | ||
204 | } | ||
205 | else | ||
206 | { | ||
207 | m_log.ErrorFormat( | ||
208 | "[PRIM INVENTORY]: " + | ||
209 | "Couldn't find prim local ID {0} in prim {1}, {2} to get inventory item ID {3}", | ||
210 | primID, part.Name, part.UUID, itemID); | ||
211 | } | ||
212 | |||
213 | return null; | ||
214 | } | ||
215 | |||
216 | /// <summary> | ||
217 | /// Update an existing inventory item. | ||
218 | /// </summary> | ||
219 | /// <param name="item">The updated item. An item with the same id must already exist | ||
220 | /// in this prim's inventory</param> | ||
221 | /// <returns>false if the item did not exist, true if the update occurred succesfully</returns> | ||
222 | public bool UpdateInventoryItem(TaskInventoryItem item) | ||
223 | { | ||
224 | SceneObjectPart part = GetPart(item.ParentPartID); | ||
225 | if (part != null) | ||
226 | { | ||
227 | part.Inventory.UpdateInventoryItem(item); | ||
228 | |||
229 | return true; | ||
230 | } | ||
231 | else | ||
232 | { | ||
233 | m_log.ErrorFormat( | ||
234 | "[PRIM INVENTORY]: " + | ||
235 | "Couldn't find prim ID {0} to update item {1}, {2}", | ||
236 | item.ParentPartID, item.Name, item.ItemID); | ||
237 | } | ||
238 | |||
239 | return false; | ||
240 | } | ||
241 | |||
242 | public int RemoveInventoryItem(uint localID, UUID itemID) | ||
243 | { | ||
244 | SceneObjectPart part = GetPart(localID); | ||
245 | if (part != null) | ||
246 | { | ||
247 | int type = part.Inventory.RemoveInventoryItem(itemID); | ||
248 | |||
249 | return type; | ||
250 | } | ||
251 | |||
252 | return -1; | ||
253 | } | ||
254 | |||
255 | public uint GetEffectivePermissions() | ||
256 | { | ||
257 | uint perms=(uint)(PermissionMask.Modify | | ||
258 | PermissionMask.Copy | | ||
259 | PermissionMask.Move | | ||
260 | PermissionMask.Transfer) | 7; | ||
261 | |||
262 | uint ownerMask = 0x7fffffff; | ||
263 | |||
264 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
265 | for (int i = 0; i < parts.Length; i++) | ||
266 | { | ||
267 | SceneObjectPart part = parts[i]; | ||
268 | // m_log.DebugFormat("[SCENE OBJECT GROUP INVENTORY]: Effective perms of {0} are {1}", part.Name, (OpenMetaverse.PermissionMask)part.OwnerMask); | ||
269 | ownerMask &= part.OwnerMask; | ||
270 | perms &= part.Inventory.MaskEffectivePermissions(); | ||
271 | } | ||
272 | |||
273 | if ((ownerMask & (uint)PermissionMask.Modify) == 0) | ||
274 | perms &= ~(uint)PermissionMask.Modify; | ||
275 | if ((ownerMask & (uint)PermissionMask.Copy) == 0) | ||
276 | perms &= ~(uint)PermissionMask.Copy; | ||
277 | if ((ownerMask & (uint)PermissionMask.Transfer) == 0) | ||
278 | perms &= ~(uint)PermissionMask.Transfer; | ||
279 | |||
280 | // If root prim permissions are applied here, this would screw | ||
281 | // with in-inventory manipulation of the next owner perms | ||
282 | // in a major way. So, let's move this to the give itself. | ||
283 | // Yes. I know. Evil. | ||
284 | // if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Modify) == 0) | ||
285 | // perms &= ~((uint)PermissionMask.Modify >> 13); | ||
286 | // if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Copy) == 0) | ||
287 | // perms &= ~((uint)PermissionMask.Copy >> 13); | ||
288 | // if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Transfer) == 0) | ||
289 | // perms &= ~((uint)PermissionMask.Transfer >> 13); | ||
290 | |||
291 | return perms; | ||
292 | } | ||
293 | |||
294 | public void ApplyNextOwnerPermissions() | ||
295 | { | ||
296 | // m_log.DebugFormat("[PRIM INVENTORY]: Applying next owner permissions to {0} {1}", Name, UUID); | ||
297 | |||
298 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
299 | for (int i = 0; i < parts.Length; i++) | ||
300 | parts[i].ApplyNextOwnerPermissions(); | ||
301 | } | ||
302 | |||
303 | public string GetStateSnapshot() | ||
304 | { | ||
305 | Dictionary<UUID, string> states = new Dictionary<UUID, string>(); | ||
306 | |||
307 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
308 | for (int i = 0; i < parts.Length; i++) | ||
309 | { | ||
310 | SceneObjectPart part = parts[i]; | ||
311 | foreach (KeyValuePair<UUID, string> s in part.Inventory.GetScriptStates()) | ||
312 | states[s.Key] = s.Value; | ||
313 | } | ||
314 | |||
315 | if (states.Count < 1) | ||
316 | return String.Empty; | ||
317 | |||
318 | XmlDocument xmldoc = new XmlDocument(); | ||
319 | |||
320 | XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, | ||
321 | String.Empty, String.Empty); | ||
322 | |||
323 | xmldoc.AppendChild(xmlnode); | ||
324 | XmlElement rootElement = xmldoc.CreateElement("", "ScriptData", | ||
325 | String.Empty); | ||
326 | |||
327 | xmldoc.AppendChild(rootElement); | ||
328 | |||
329 | |||
330 | XmlElement wrapper = xmldoc.CreateElement("", "ScriptStates", | ||
331 | String.Empty); | ||
332 | |||
333 | rootElement.AppendChild(wrapper); | ||
334 | |||
335 | foreach (KeyValuePair<UUID, string> state in states) | ||
336 | { | ||
337 | XmlDocument sdoc = new XmlDocument(); | ||
338 | sdoc.LoadXml(state.Value); | ||
339 | XmlNodeList rootL = sdoc.GetElementsByTagName("State"); | ||
340 | XmlNode rootNode = rootL[0]; | ||
341 | |||
342 | XmlNode newNode = xmldoc.ImportNode(rootNode, true); | ||
343 | wrapper.AppendChild(newNode); | ||
344 | } | ||
345 | |||
346 | return xmldoc.InnerXml; | ||
347 | } | ||
348 | |||
349 | public void SetState(string objXMLData, IScene ins) | ||
350 | { | ||
351 | if (!(ins is Scene)) | ||
352 | return; | ||
353 | |||
354 | Scene s = (Scene)ins; | ||
355 | |||
356 | if (objXMLData == String.Empty) | ||
357 | return; | ||
358 | |||
359 | IScriptModule scriptModule = null; | ||
360 | |||
361 | foreach (IScriptModule sm in s.RequestModuleInterfaces<IScriptModule>()) | ||
362 | { | ||
363 | if (sm.ScriptEngineName == s.DefaultScriptEngine) | ||
364 | scriptModule = sm; | ||
365 | else if (scriptModule == null) | ||
366 | scriptModule = sm; | ||
367 | } | ||
368 | |||
369 | if (scriptModule == null) | ||
370 | return; | ||
371 | |||
372 | XmlDocument doc = new XmlDocument(); | ||
373 | try | ||
374 | { | ||
375 | doc.LoadXml(objXMLData); | ||
376 | } | ||
377 | catch (Exception) // (System.Xml.XmlException) | ||
378 | { | ||
379 | // We will get here if the XML is invalid or in unit | ||
380 | // tests. Really should determine which it is and either | ||
381 | // fail silently or log it | ||
382 | // Fail silently, for now. | ||
383 | // TODO: Fix this | ||
384 | // | ||
385 | return; | ||
386 | } | ||
387 | |||
388 | XmlNodeList rootL = doc.GetElementsByTagName("ScriptData"); | ||
389 | if (rootL.Count != 1) | ||
390 | return; | ||
391 | |||
392 | XmlElement rootE = (XmlElement)rootL[0]; | ||
393 | |||
394 | XmlNodeList dataL = rootE.GetElementsByTagName("ScriptStates"); | ||
395 | if (dataL.Count != 1) | ||
396 | return; | ||
397 | |||
398 | XmlElement dataE = (XmlElement)dataL[0]; | ||
399 | |||
400 | foreach (XmlNode n in dataE.ChildNodes) | ||
401 | { | ||
402 | XmlElement stateE = (XmlElement)n; | ||
403 | UUID itemID = new UUID(stateE.GetAttribute("UUID")); | ||
404 | |||
405 | scriptModule.SetXMLState(itemID, n.OuterXml); | ||
406 | } | ||
407 | } | ||
408 | |||
409 | public void ResumeScripts() | ||
410 | { | ||
411 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
412 | for (int i = 0; i < parts.Length; i++) | ||
413 | parts[i].Inventory.ResumeScripts(); | ||
414 | } | ||
415 | |||
416 | /// <summary> | ||
417 | /// Returns true if any part in the scene object contains scripts, false otherwise. | ||
418 | /// </summary> | ||
419 | /// <returns></returns> | ||
420 | public bool ContainsScripts() | ||
421 | { | ||
422 | foreach (SceneObjectPart part in Parts) | ||
423 | if (part.Inventory.ContainsScripts()) | ||
424 | return true; | ||
425 | |||
426 | return false; | ||
427 | } | ||
428 | } | ||
429 | } | ||