aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs')
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs674
1 files changed, 358 insertions, 316 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 9fbfc34..6b3df9d 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -64,7 +64,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
64 return m_UserManagement; 64 return m_UserManagement;
65 } 65 }
66 } 66 }
67 67
68 public bool CoalesceMultipleObjectsToInventory { get; set; }
68 69
69 #region INonSharedRegionModule 70 #region INonSharedRegionModule
70 71
@@ -87,10 +88,28 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
87 if (name == Name) 88 if (name == Name)
88 { 89 {
89 m_Enabled = true; 90 m_Enabled = true;
90 m_log.InfoFormat("[INVENTORY ACCESS MODULE]: {0} enabled.", Name); 91
92 InitialiseCommon(source);
93
94 m_log.InfoFormat("[INVENTORY ACCESS MODULE]: {0} enabled.", Name);
91 } 95 }
92 } 96 }
93 } 97 }
98
99 /// <summary>
100 /// Common module config for both this and descendant classes.
101 /// </summary>
102 /// <param name="source"></param>
103 protected virtual void InitialiseCommon(IConfigSource source)
104 {
105 IConfig inventoryConfig = source.Configs["Inventory"];
106
107 if (inventoryConfig != null)
108 CoalesceMultipleObjectsToInventory
109 = inventoryConfig.GetBoolean("CoalesceMultipleObjectsToInventory", true);
110 else
111 CoalesceMultipleObjectsToInventory = true;
112 }
94 113
95 public virtual void PostInitialise() 114 public virtual void PostInitialise()
96 { 115 {
@@ -194,366 +213,386 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
194 213
195 return UUID.Zero; 214 return UUID.Zero;
196 } 215 }
197 216
198 /// <summary> 217 public virtual UUID CopyToInventory(DeRezAction action, UUID folderID,
199 /// Delete a scene object from a scene and place in the given avatar's inventory.
200 /// Returns the UUID of the newly created asset.
201 /// </summary>
202 /// <param name="action"></param>
203 /// <param name="folderID"></param>
204 /// <param name="objectGroup"></param>
205 /// <param name="remoteClient"> </param>
206 public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID,
207 List<SceneObjectGroup> objectGroups, IClientAPI remoteClient) 218 List<SceneObjectGroup> objectGroups, IClientAPI remoteClient)
208 { 219 {
209 UUID ret = UUID.Zero; 220 Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>();
210 221
211 // The following code groups the SOG's by owner. No objects 222 if (CoalesceMultipleObjectsToInventory)
212 // belonging to different people can be coalesced, for obvious
213 // reasons.
214 Dictionary<UUID, List<SceneObjectGroup>> deletes =
215 new Dictionary<UUID, List<SceneObjectGroup>>();
216
217 foreach (SceneObjectGroup g in objectGroups)
218 { 223 {
219 if (!deletes.ContainsKey(g.OwnerID)) 224 // The following code groups the SOG's by owner. No objects
220 deletes[g.OwnerID] = new List<SceneObjectGroup>(); 225 // belonging to different people can be coalesced, for obvious
221 226 // reasons.
222 deletes[g.OwnerID].Add(g); 227 foreach (SceneObjectGroup g in objectGroups)
228 {
229 if (!bundlesToCopy.ContainsKey(g.OwnerID))
230 bundlesToCopy[g.OwnerID] = new List<SceneObjectGroup>();
231
232 bundlesToCopy[g.OwnerID].Add(g);
233 }
234 }
235 else
236 {
237 // If we don't want to coalesce then put every object in its own bundle.
238 foreach (SceneObjectGroup g in objectGroups)
239 {
240 List<SceneObjectGroup> bundle = new List<SceneObjectGroup>();
241 bundle.Add(g);
242 bundlesToCopy[g.UUID] = bundle;
243 }
223 } 244 }
224 245
225 // This is pethod scoped and will be returned. It will be the 246 // This is method scoped and will be returned. It will be the
226 // last created asset id 247 // last created asset id
227 UUID assetID = UUID.Zero; 248 UUID assetID = UUID.Zero;
228 249
229 // Each iteration is really a separate asset being created, 250 // Each iteration is really a separate asset being created,
230 // with distinct destinations as well. 251 // with distinct destinations as well.
231 foreach (List<SceneObjectGroup> objlist in deletes.Values) 252 foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values)
232 { 253 assetID = CopyBundleToInventory(action, folderID, bundle, remoteClient);
233 Dictionary<UUID, string> xmlStrings = 254
234 new Dictionary<UUID, string>(); 255 return assetID;
235 256 }
236 foreach (SceneObjectGroup objectGroup in objlist) 257
237 { 258 /// <summary>
238 Vector3 inventoryStoredPosition = new Vector3 259 /// Copy a bundle of objects to inventory. If there is only one object, then this will create an object
239 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) 260 /// item. If there are multiple objects then these will be saved as a single coalesced item.
240 ? 250 261 /// </summary>
241 : objectGroup.AbsolutePosition.X) 262 /// <param name="action"></param>
242 , 263 /// <param name="folderID"></param>
243 (objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) 264 /// <param name="objlist"></param>
244 ? 250 265 /// <param name="remoteClient"></param>
245 : objectGroup.AbsolutePosition.X, 266 /// <returns></returns>
246 objectGroup.AbsolutePosition.Z); 267 protected UUID CopyBundleToInventory(
247 268 DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient)
248 Vector3 originalPosition = objectGroup.AbsolutePosition; 269 {
249 270 UUID assetID = UUID.Zero;
250 objectGroup.AbsolutePosition = inventoryStoredPosition; 271
251 272 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
252 // Make sure all bits but the ones we want are clear 273 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
253 // on take.
254 // This will be applied to the current perms, so
255 // it will do what we want.
256 objectGroup.RootPart.NextOwnerMask &=
257 ((uint)PermissionMask.Copy |
258 (uint)PermissionMask.Transfer |
259 (uint)PermissionMask.Modify);
260 objectGroup.RootPart.NextOwnerMask |=
261 (uint)PermissionMask.Move;
262
263 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup);
264
265 objectGroup.AbsolutePosition = originalPosition;
266
267 xmlStrings[objectGroup.UUID] = sceneObjectXml;
268 }
269 274
270 string itemXml; 275 foreach (SceneObjectGroup objectGroup in objlist)
276 {
277 Vector3 inventoryStoredPosition = new Vector3
278 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
279 ? 250
280 : objectGroup.AbsolutePosition.X)
281 ,
282 (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize)
283 ? 250
284 : objectGroup.AbsolutePosition.Y,
285 objectGroup.AbsolutePosition.Z);
286
287 originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition;
288
289 objectGroup.AbsolutePosition = inventoryStoredPosition;
290
291 // Make sure all bits but the ones we want are clear
292 // on take.
293 // This will be applied to the current perms, so
294 // it will do what we want.
295 objectGroup.RootPart.NextOwnerMask &=
296 ((uint)PermissionMask.Copy |
297 (uint)PermissionMask.Transfer |
298 (uint)PermissionMask.Modify);
299 objectGroup.RootPart.NextOwnerMask |=
300 (uint)PermissionMask.Move;
301
302 coa.Add(objectGroup);
303 }
271 304
272 if (objlist.Count > 1) 305 string itemXml;
273 {
274 float minX, minY, minZ;
275 float maxX, maxY, maxZ;
276 306
277 Vector3[] offsets = m_Scene.GetCombinedBoundingBox(objlist, 307 if (objlist.Count > 1)
278 out minX, out maxX, out minY, out maxY, 308 itemXml = CoalescedSceneObjectsSerializer.ToXml(coa);
279 out minZ, out maxZ); 309 else
310 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0]);
311
312 // Restore the position of each group now that it has been stored to inventory.
313 foreach (SceneObjectGroup objectGroup in objlist)
314 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
280 315
281 // CreateWrapper 316 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
282 XmlDocument itemDoc = new XmlDocument(); 317 if (item == null)
283 XmlElement root = itemDoc.CreateElement("", "CoalescedObject", ""); 318 return UUID.Zero;
284 itemDoc.AppendChild(root); 319
320 // Can't know creator is the same, so null it in inventory
321 if (objlist.Count > 1)
322 {
323 item.CreatorId = UUID.Zero.ToString();
324 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
325 }
326 else
327 {
328 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
329 item.SaleType = objlist[0].RootPart.ObjectSaleType;
330 item.SalePrice = objlist[0].RootPart.SalePrice;
331 }
332
333 AssetBase asset = CreateAsset(
334 objlist[0].GetPartName(objlist[0].RootPart.LocalId),
335 objlist[0].GetPartDescription(objlist[0].RootPart.LocalId),
336 (sbyte)AssetType.Object,
337 Utils.StringToBytes(itemXml),
338 objlist[0].OwnerID.ToString());
339 m_Scene.AssetService.Store(asset);
340
341 item.AssetID = asset.FullID;
342 assetID = asset.FullID;
285 343
286 // Embed the offsets into the group XML 344 if (DeRezAction.SaveToExistingUserInventoryItem == action)
287 for ( int i = 0 ; i < objlist.Count ; i++ ) 345 {
288 { 346 m_Scene.InventoryService.UpdateItem(item);
289 XmlDocument doc = new XmlDocument(); 347 }
290 SceneObjectGroup g = objlist[i]; 348 else
291 doc.LoadXml(xmlStrings[g.UUID]); 349 {
292 XmlElement e = (XmlElement)doc.SelectSingleNode("/SceneObjectGroup"); 350 AddPermissions(item, objlist[0], objlist, remoteClient);
293 e.SetAttribute("offsetx", offsets[i].X.ToString());
294 e.SetAttribute("offsety", offsets[i].Y.ToString());
295 e.SetAttribute("offsetz", offsets[i].Z.ToString());
296
297 XmlNode objectNode = itemDoc.ImportNode(e, true);
298 root.AppendChild(objectNode);
299 }
300 351
301 float sizeX = maxX - minX; 352 item.CreationDate = Util.UnixTimeSinceEpoch();
302 float sizeY = maxY - minY; 353 item.Description = asset.Description;
303 float sizeZ = maxZ - minZ; 354 item.Name = asset.Name;
355 item.AssetType = asset.Type;
304 356
305 root.SetAttribute("x", sizeX.ToString()); 357 m_Scene.AddInventoryItem(item);
306 root.SetAttribute("y", sizeY.ToString());
307 root.SetAttribute("z", sizeZ.ToString());
308 358
309 itemXml = itemDoc.InnerXml; 359 if (remoteClient != null && item.Owner == remoteClient.AgentId)
360 {
361 remoteClient.SendInventoryItemCreateUpdate(item, 0);
310 } 362 }
311 else 363 else
312 { 364 {
313 itemXml = xmlStrings[objlist[0].UUID]; 365 ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner);
366 if (notifyUser != null)
367 {
368 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
369 }
314 } 370 }
371 }
315 372
316 // Get the user info of the item destination 373 // This is a hook to do some per-asset post-processing for subclasses that need that
317 // 374 ExportAsset(remoteClient.AgentId, assetID);
318 UUID userID = UUID.Zero; 375
376 return assetID;
377 }
319 378
320 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || 379 protected virtual void ExportAsset(UUID agentID, UUID assetID)
321 action == DeRezAction.SaveToExistingUserInventoryItem) 380 {
322 { 381 // nothing to do here
323 // Take or take copy require a taker 382 }
324 // Saving changes requires a local user
325 //
326 if (remoteClient == null)
327 return UUID.Zero;
328 383
329 userID = remoteClient.AgentId; 384 /// <summary>
330 } 385 /// Add relevant permissions for an object to the item.
331 else 386 /// </summary>
332 { 387 /// <param name="item"></param>
333 // All returns / deletes go to the object owner 388 /// <param name="so"></param>
334 // 389 /// <param name="objsForEffectivePermissions"></param>
390 /// <param name="remoteClient"></param>
391 /// <returns></returns>
392 protected InventoryItemBase AddPermissions(
393 InventoryItemBase item, SceneObjectGroup so, List<SceneObjectGroup> objsForEffectivePermissions,
394 IClientAPI remoteClient)
395 {
396 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7;
397 foreach (SceneObjectGroup grp in objsForEffectivePermissions)
398 effectivePerms &= grp.GetEffectivePermissions();
399 effectivePerms |= (uint)PermissionMask.Move;
335 400
336 userID = objlist[0].RootPart.OwnerID; 401 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
337 } 402 {
403 uint perms = effectivePerms;
404 uint nextPerms = (perms & 7) << 13;
405 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
406 perms &= ~(uint)PermissionMask.Copy;
407 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
408 perms &= ~(uint)PermissionMask.Transfer;
409 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
410 perms &= ~(uint)PermissionMask.Modify;
411
412 item.BasePermissions = perms & so.RootPart.NextOwnerMask;
413 item.CurrentPermissions = item.BasePermissions;
414 item.NextPermissions = perms & so.RootPart.NextOwnerMask;
415 item.EveryOnePermissions = so.RootPart.EveryoneMask & so.RootPart.NextOwnerMask;
416 item.GroupPermissions = so.RootPart.GroupMask & so.RootPart.NextOwnerMask;
417
418 // Magic number badness. Maybe this deserves an enum.
419 // bit 4 (16) is the "Slam" bit, it means treat as passed
420 // and apply next owner perms on rez
421 item.CurrentPermissions |= 16; // Slam!
422 }
423 else
424 {
425 item.BasePermissions = effectivePerms;
426 item.CurrentPermissions = effectivePerms;
427 item.NextPermissions = so.RootPart.NextOwnerMask & effectivePerms;
428 item.EveryOnePermissions = so.RootPart.EveryoneMask & effectivePerms;
429 item.GroupPermissions = so.RootPart.GroupMask & effectivePerms;
430
431 item.CurrentPermissions &=
432 ((uint)PermissionMask.Copy |
433 (uint)PermissionMask.Transfer |
434 (uint)PermissionMask.Modify |
435 (uint)PermissionMask.Move |
436 7); // Preserve folded permissions
437 }
438
439 return item;
440 }
441
442 /// <summary>
443 /// Create an item using details for the given scene object.
444 /// </summary>
445 /// <param name="action"></param>
446 /// <param name="remoteClient"></param>
447 /// <param name="so"></param>
448 /// <param name="folderID"></param>
449 /// <returns></returns>
450 protected InventoryItemBase CreateItemForObject(
451 DeRezAction action, IClientAPI remoteClient, SceneObjectGroup so, UUID folderID)
452 {
453 // Get the user info of the item destination
454 //
455 UUID userID = UUID.Zero;
338 456
339 if (userID == UUID.Zero) // Can't proceed 457 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy ||
340 { 458 action == DeRezAction.SaveToExistingUserInventoryItem)
341 return UUID.Zero; 459 {
342 } 460 // Take or take copy require a taker
461 // Saving changes requires a local user
462 //
463 if (remoteClient == null)
464 return null;
343 465
344 // If we're returning someone's item, it goes back to the 466 userID = remoteClient.AgentId;
345 // owner's Lost And Found folder. 467 }
346 // Delete is treated like return in this case 468 else
347 // Deleting your own items makes them go to trash 469 {
470 // All returns / deletes go to the object owner
348 // 471 //
472 userID = so.RootPart.OwnerID;
473 }
349 474
350 InventoryFolderBase folder = null; 475 if (userID == UUID.Zero) // Can't proceed
351 InventoryItemBase item = null; 476 {
477 return null;
478 }
352 479
353 if (DeRezAction.SaveToExistingUserInventoryItem == action) 480 // If we're returning someone's item, it goes back to the
354 { 481 // owner's Lost And Found folder.
355 item = new InventoryItemBase(objlist[0].RootPart.FromUserInventoryItemID, userID); 482 // Delete is treated like return in this case
356 item = m_Scene.InventoryService.GetItem(item); 483 // Deleting your own items makes them go to trash
484 //
485
486 InventoryFolderBase folder = null;
487 InventoryItemBase item = null;
357 488
358 //item = userInfo.RootFolder.FindItem( 489 if (DeRezAction.SaveToExistingUserInventoryItem == action)
359 // objectGroup.RootPart.FromUserInventoryItemID); 490 {
491 item = new InventoryItemBase(so.RootPart.FromUserInventoryItemID, userID);
492 item = m_Scene.InventoryService.GetItem(item);
360 493
361 if (null == item) 494 //item = userInfo.RootFolder.FindItem(
362 { 495 // objectGroup.RootPart.FromUserInventoryItemID);
363 m_log.DebugFormat( 496
364 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", 497 if (null == item)
365 objlist[0].Name, objlist[0].UUID); 498 {
366 return UUID.Zero; 499 m_log.DebugFormat(
367 } 500 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.",
501 so.Name, so.UUID);
502
503 return null;
368 } 504 }
369 else 505 }
506 else
507 {
508 // Folder magic
509 //
510 if (action == DeRezAction.Delete)
370 { 511 {
371 // Folder magic 512 // Deleting someone else's item
372 // 513 //
373 if (action == DeRezAction.Delete) 514 if (remoteClient == null ||
515 so.OwnerID != remoteClient.AgentId)
374 { 516 {
375 // Deleting someone else's item 517 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
376 //
377 if (remoteClient == null ||
378 objlist[0].OwnerID != remoteClient.AgentId)
379 {
380
381 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
382 }
383 else
384 {
385 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
386 }
387 } 518 }
388 else if (action == DeRezAction.Return) 519 else
389 { 520 {
521 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
522 }
523 }
524 else if (action == DeRezAction.Return)
525 {
526 // Dump to lost + found unconditionally
527 //
528 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
529 }
390 530
391 // Dump to lost + found unconditionally 531 if (folderID == UUID.Zero && folder == null)
532 {
533 if (action == DeRezAction.Delete)
534 {
535 // Deletes go to trash by default
392 // 536 //
393 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); 537 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
394 } 538 }
395 539 else
396 if (folderID == UUID.Zero && folder == null)
397 { 540 {
398 if (action == DeRezAction.Delete) 541 if (remoteClient == null || so.OwnerID != remoteClient.AgentId)
399 { 542 {
400 // Deletes go to trash by default 543 // Taking copy of another person's item. Take to
401 // 544 // Objects folder.
402 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); 545 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
403 } 546 }
404 else 547 else
405 { 548 {
406 if (remoteClient == null || 549 // Catch all. Use lost & found
407 objlist[0].OwnerID != remoteClient.AgentId) 550 //
408 {
409 // Taking copy of another person's item. Take to
410 // Objects folder.
411 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
412 }
413 else
414 {
415 // Catch all. Use lost & found
416 //
417
418 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
419 }
420 }
421 }
422
423 // Override and put into where it came from, if it came
424 // from anywhere in inventory
425 //
426 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy)
427 {
428 if (objlist[0].RootPart.FromFolderID != UUID.Zero)
429 {
430 InventoryFolderBase f = new InventoryFolderBase(objlist[0].RootPart.FromFolderID, userID);
431 folder = m_Scene.InventoryService.GetFolder(f);
432 }
433 }
434
435 if (folder == null) // None of the above
436 {
437 folder = new InventoryFolderBase(folderID);
438 551
439 if (folder == null) // Nowhere to put it 552 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
440 {
441 return UUID.Zero;
442 } 553 }
443 } 554 }
444
445 item = new InventoryItemBase();
446 // Can't know creator is the same, so null it in inventory
447 if (objlist.Count > 1)
448 item.CreatorId = UUID.Zero.ToString();
449 else
450 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
451 item.ID = UUID.Random();
452 item.InvType = (int)InventoryType.Object;
453 item.Folder = folder.ID;
454 item.Owner = userID;
455 if (objlist.Count > 1)
456 {
457 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
458 }
459 else
460 {
461 item.SaleType = objlist[0].RootPart.ObjectSaleType;
462 item.SalePrice = objlist[0].RootPart.SalePrice;
463 }
464 } 555 }
465 556
466 AssetBase asset = CreateAsset( 557 // Override and put into where it came from, if it came
467 objlist[0].GetPartName(objlist[0].RootPart.LocalId), 558 // from anywhere in inventory
468 objlist[0].GetPartDescription(objlist[0].RootPart.LocalId), 559 //
469 (sbyte)AssetType.Object, 560 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy)
470 Utils.StringToBytes(itemXml),
471 objlist[0].OwnerID.ToString());
472 m_Scene.AssetService.Store(asset);
473 assetID = asset.FullID;
474
475 if (DeRezAction.SaveToExistingUserInventoryItem == action)
476 {
477 item.AssetID = asset.FullID;
478 m_Scene.InventoryService.UpdateItem(item);
479 }
480 else
481 { 561 {
482 item.AssetID = asset.FullID; 562 if (so.RootPart.FromFolderID != UUID.Zero)
483
484 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7;
485 foreach (SceneObjectGroup grp in objlist)
486 effectivePerms &= grp.GetEffectivePermissions();
487 effectivePerms |= (uint)PermissionMask.Move;
488
489 if (remoteClient != null && (remoteClient.AgentId != objlist[0].RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
490 { 563 {
491 uint perms = effectivePerms; 564 InventoryFolderBase f = new InventoryFolderBase(so.RootPart.FromFolderID, userID);
492 uint nextPerms = (perms & 7) << 13; 565 folder = m_Scene.InventoryService.GetFolder(f);
493 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
494 perms &= ~(uint)PermissionMask.Copy;
495 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
496 perms &= ~(uint)PermissionMask.Transfer;
497 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
498 perms &= ~(uint)PermissionMask.Modify;
499
500 item.BasePermissions = perms & objlist[0].RootPart.NextOwnerMask;
501 item.CurrentPermissions = item.BasePermissions;
502 item.NextPermissions = perms & objlist[0].RootPart.NextOwnerMask;
503 item.EveryOnePermissions = objlist[0].RootPart.EveryoneMask & objlist[0].RootPart.NextOwnerMask;
504 item.GroupPermissions = objlist[0].RootPart.GroupMask & objlist[0].RootPart.NextOwnerMask;
505
506 // Magic number badness. Maybe this deserves an enum.
507 // bit 4 (16) is the "Slam" bit, it means treat as passed
508 // and apply next owner perms on rez
509 item.CurrentPermissions |= 16; // Slam!
510 } 566 }
511 else 567 }
512 {
513 item.BasePermissions = effectivePerms;
514 item.CurrentPermissions = effectivePerms;
515 item.NextPermissions = objlist[0].RootPart.NextOwnerMask & effectivePerms;
516 item.EveryOnePermissions = objlist[0].RootPart.EveryoneMask & effectivePerms;
517 item.GroupPermissions = objlist[0].RootPart.GroupMask & effectivePerms;
518
519 item.CurrentPermissions &=
520 ((uint)PermissionMask.Copy |
521 (uint)PermissionMask.Transfer |
522 (uint)PermissionMask.Modify |
523 (uint)PermissionMask.Move |
524 7); // Preserve folded permissions
525 }
526
527 item.CreationDate = Util.UnixTimeSinceEpoch();
528 item.Description = asset.Description;
529 item.Name = asset.Name;
530 item.AssetType = asset.Type;
531 568
532 m_Scene.AddInventoryItem(item); 569 if (folder == null) // None of the above
570 {
571 folder = new InventoryFolderBase(folderID);
533 572
534 if (remoteClient != null && item.Owner == remoteClient.AgentId) 573 if (folder == null) // Nowhere to put it
535 {
536 remoteClient.SendInventoryItemCreateUpdate(item, 0);
537 }
538 else
539 { 574 {
540 ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); 575 return null;
541 if (notifyUser != null)
542 {
543 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
544 }
545 } 576 }
546 } 577 }
547 }
548 return assetID;
549 }
550 578
579 item = new InventoryItemBase();
580 item.ID = UUID.Random();
581 item.InvType = (int)InventoryType.Object;
582 item.Folder = folder.ID;
583 item.Owner = userID;
584 }
585
586 return item;
587 }
551 588
552 /// <summary> 589 /// <summary>
553 /// Rez an object into the scene from the user's inventory 590 /// Rez an object into the scene from the user's inventory
554 /// </summary> 591 /// </summary>
592 /// <remarks>
555 /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing 593 /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing
556 /// things to the scene. The caller should be doing that, I think. 594 /// things to the scene. The caller should be doing that, I think.
595 /// </remarks>
557 /// <param name="remoteClient"></param> 596 /// <param name="remoteClient"></param>
558 /// <param name="itemID"></param> 597 /// <param name="itemID"></param>
559 /// <param name="RayEnd"></param> 598 /// <param name="RayEnd"></param>
@@ -570,21 +609,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
570 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 609 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
571 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 610 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
572 { 611 {
573 // Work out position details 612// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID);
574 byte bRayEndIsIntersection = (byte)0; 613
575 614 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
576 if (RayEndIsIntersection)
577 {
578 bRayEndIsIntersection = (byte)1;
579 }
580 else
581 {
582 bRayEndIsIntersection = (byte)0;
583 }
584
585 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); 615 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
586
587
588 Vector3 pos = m_Scene.GetNewRezLocation( 616 Vector3 pos = m_Scene.GetNewRezLocation(
589 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 617 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
590 BypassRayCast, bRayEndIsIntersection, true, scale, false); 618 BypassRayCast, bRayEndIsIntersection, true, scale, false);
@@ -668,9 +696,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
668 itemId, n.OuterXml); 696 itemId, n.OuterXml);
669 objlist.Add(g); 697 objlist.Add(g);
670 XmlElement el = (XmlElement)n; 698 XmlElement el = (XmlElement)n;
671 float x = Convert.ToSingle(el.GetAttribute("offsetx")); 699
672 float y = Convert.ToSingle(el.GetAttribute("offsety")); 700 string rawX = el.GetAttribute("offsetx");
673 float z = Convert.ToSingle(el.GetAttribute("offsetz")); 701 string rawY = el.GetAttribute("offsety");
702 string rawZ = el.GetAttribute("offsetz");
703//
704// m_log.DebugFormat(
705// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>",
706// g.Name, rawX, rawY, rawZ);
707
708 float x = Convert.ToSingle(rawX);
709 float y = Convert.ToSingle(rawY);
710 float z = Convert.ToSingle(rawZ);
674 veclist.Add(new Vector3(x, y, z)); 711 veclist.Add(new Vector3(x, y, z));
675 } 712 }
676 } 713 }
@@ -762,10 +799,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
762 // affect the name stored in the serialization, transfer 799 // affect the name stored in the serialization, transfer
763 // the correct name from the inventory to the 800 // the correct name from the inventory to the
764 // object itself before we rez. 801 // object itself before we rez.
765 rootPart.Name = item.Name; 802 //
766 rootPart.Description = item.Description; 803 // Only do these for the first object if we are rezzing a coalescence.
767 rootPart.ObjectSaleType = item.SaleType; 804 if (i == 0)
768 rootPart.SalePrice = item.SalePrice; 805 {
806 rootPart.Name = item.Name;
807 rootPart.Description = item.Description;
808 rootPart.ObjectSaleType = item.SaleType;
809 rootPart.SalePrice = item.SalePrice;
810 }
769 811
770 group.SetGroup(remoteClient.ActiveGroupId, remoteClient); 812 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
771 if ((rootPart.OwnerID != item.Owner) || 813 if ((rootPart.OwnerID != item.Owner) ||