aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs206
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs13
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs59
3 files changed, 118 insertions, 160 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 2e1948d..d099511 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -49,6 +49,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
49 49
50 private Scene m_scene; 50 private Scene m_scene;
51 private IDialogModule m_dialogModule; 51 private IDialogModule m_dialogModule;
52 private IInventoryAccessModule m_invAccessModule;
52 53
53 /// <summary> 54 /// <summary>
54 /// Are attachments enabled? 55 /// Are attachments enabled?
@@ -87,7 +88,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
87 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents; 88 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents;
88 } 89 }
89 90
90 public void RegionLoaded(Scene scene) {} 91 public void RegionLoaded(Scene scene)
92 {
93 m_invAccessModule = m_scene.RequestModuleInterface<IInventoryAccessModule>();
94 }
91 95
92 public void Close() 96 public void Close()
93 { 97 {
@@ -578,90 +582,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
578 /// <returns>The user inventory item created that holds the attachment.</returns> 582 /// <returns>The user inventory item created that holds the attachment.</returns>
579 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IScenePresence sp, SceneObjectGroup grp) 583 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IScenePresence sp, SceneObjectGroup grp)
580 { 584 {
585 if (m_invAccessModule == null)
586 return null;
587
581 // m_log.DebugFormat( 588 // m_log.DebugFormat(
582 // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", 589 // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
583 // grp.Name, grp.LocalId, remoteClient.Name); 590 // grp.Name, grp.LocalId, remoteClient.Name);
584 591
585 Vector3 inventoryStoredPosition = new Vector3 592 InventoryItemBase newItem = m_invAccessModule.CopyToInventory(
586 (((grp.AbsolutePosition.X > (int)Constants.RegionSize) 593 DeRezAction.TakeCopy,
587 ? Constants.RegionSize - 6 594 m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object).ID,
588 : grp.AbsolutePosition.X) 595 new List<SceneObjectGroup> { grp },
589 , 596 sp.ControllingClient, true)[0];
590 (grp.AbsolutePosition.Y > (int)Constants.RegionSize)
591 ? Constants.RegionSize - 6
592 : grp.AbsolutePosition.Y,
593 grp.AbsolutePosition.Z);
594
595 Vector3 originalPosition = grp.AbsolutePosition;
596
597 grp.AbsolutePosition = inventoryStoredPosition;
598
599 // If we're being called from a script, then trying to serialize that same script's state will not complete
600 // in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if
601 // the client/server crashes rather than logging out normally, the attachment's scripts will resume
602 // without state on relog. Arguably, this is what we want anyway.
603 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, false);
604
605 grp.AbsolutePosition = originalPosition;
606
607 AssetBase asset = m_scene.CreateAsset(
608 grp.GetPartName(grp.LocalId),
609 grp.GetPartDescription(grp.LocalId),
610 (sbyte)AssetType.Object,
611 Utils.StringToBytes(sceneObjectXml),
612 sp.UUID);
613
614 m_scene.AssetService.Store(asset);
615
616 InventoryItemBase item = new InventoryItemBase();
617 item.CreatorId = grp.RootPart.CreatorID.ToString();
618 item.CreatorData = grp.RootPart.CreatorData;
619 item.Owner = sp.UUID;
620 item.ID = UUID.Random();
621 item.AssetID = asset.FullID;
622 item.Description = asset.Description;
623 item.Name = asset.Name;
624 item.AssetType = asset.Type;
625 item.InvType = (int)InventoryType.Object;
626
627 InventoryFolderBase folder = m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
628 if (folder != null)
629 item.Folder = folder.ID;
630 else // oopsies
631 item.Folder = UUID.Zero;
632
633 if ((sp.UUID != grp.RootPart.OwnerID) && m_scene.Permissions.PropagatePermissions())
634 {
635 item.BasePermissions = grp.RootPart.NextOwnerMask;
636 item.CurrentPermissions = grp.RootPart.NextOwnerMask;
637 item.NextPermissions = grp.RootPart.NextOwnerMask;
638 item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
639 item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
640 }
641 else
642 {
643 item.BasePermissions = grp.RootPart.BaseMask;
644 item.CurrentPermissions = grp.RootPart.OwnerMask;
645 item.NextPermissions = grp.RootPart.NextOwnerMask;
646 item.EveryOnePermissions = grp.RootPart.EveryoneMask;
647 item.GroupPermissions = grp.RootPart.GroupMask;
648 }
649 item.CreationDate = Util.UnixTimeSinceEpoch();
650 597
651 // sets itemID so client can show item as 'attached' in inventory 598 // sets itemID so client can show item as 'attached' in inventory
652 grp.FromItemID = item.ID; 599 grp.FromItemID = newItem.ID;
653 600
654 if (m_scene.AddInventoryItem(item)) 601 return newItem;
655 {
656 sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
657 }
658 else
659 {
660 if (m_dialogModule != null)
661 m_dialogModule.SendAlertToUser(sp.ControllingClient, "Operation failed");
662 }
663
664 return item;
665 } 602 }
666 603
667 // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards. 604 // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards.
@@ -709,70 +646,69 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
709 private SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 646 private SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
710 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt) 647 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt)
711 { 648 {
712 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 649 if (m_invAccessModule == null)
713 if (invAccess != null) 650 return null;
651
652 lock (sp.AttachmentsSyncLock)
714 { 653 {
715 lock (sp.AttachmentsSyncLock) 654 SceneObjectGroup objatt;
655
656 if (itemID != UUID.Zero)
657 objatt = m_invAccessModule.RezObject(sp.ControllingClient,
658 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
659 false, false, sp.UUID, true);
660 else
661 objatt = m_invAccessModule.RezObject(sp.ControllingClient,
662 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
663 false, false, sp.UUID, true);
664
665 // m_log.DebugFormat(
666 // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
667 // objatt.Name, remoteClient.Name, AttachmentPt);
668
669 if (objatt != null)
716 { 670 {
717 SceneObjectGroup objatt; 671 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
718 672 objatt.HasGroupChanged = false;
719 if (itemID != UUID.Zero) 673 bool tainted = false;
720 objatt = invAccess.RezObject(sp.ControllingClient, 674 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
721 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, 675 tainted = true;
722 false, false, sp.UUID, true); 676
723 else 677 // This will throw if the attachment fails
724 objatt = invAccess.RezObject(sp.ControllingClient, 678 try
725 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
726 false, false, sp.UUID, true);
727
728 // m_log.DebugFormat(
729 // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
730 // objatt.Name, remoteClient.Name, AttachmentPt);
731
732 if (objatt != null)
733 { 679 {
734 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. 680 AttachObject(sp, objatt, attachmentPt, false);
735 objatt.HasGroupChanged = false; 681 }
736 bool tainted = false; 682 catch (Exception e)
737 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) 683 {
738 tainted = true; 684 m_log.ErrorFormat(
739 685 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
740 // This will throw if the attachment fails 686 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
741 try 687
742 { 688 // Make sure the object doesn't stick around and bail
743 AttachObject(sp, objatt, attachmentPt, false); 689 sp.RemoveAttachment(objatt);
744 } 690 m_scene.DeleteSceneObject(objatt, false);
745 catch (Exception e) 691 return null;
746 { 692 }
747 m_log.ErrorFormat(
748 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
749 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
750
751 // Make sure the object doesn't stick around and bail
752 sp.RemoveAttachment(objatt);
753 m_scene.DeleteSceneObject(objatt, false);
754 return null;
755 }
756 693
757 if (tainted) 694 if (tainted)
758 objatt.HasGroupChanged = true; 695 objatt.HasGroupChanged = true;
759 696
760 // Fire after attach, so we don't get messy perms dialogs 697 // Fire after attach, so we don't get messy perms dialogs
761 // 4 == AttachedRez 698 // 4 == AttachedRez
762 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); 699 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
763 objatt.ResumeScripts(); 700 objatt.ResumeScripts();
764 701
765 // Do this last so that event listeners have access to all the effects of the attachment 702 // Do this last so that event listeners have access to all the effects of the attachment
766 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); 703 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
767 704
768 return objatt; 705 return objatt;
769 } 706 }
770 else 707 else
771 { 708 {
772 m_log.WarnFormat( 709 m_log.WarnFormat(
773 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", 710 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
774 itemID, sp.Name, attachmentPt); 711 itemID, sp.Name, attachmentPt);
775 }
776 } 712 }
777 } 713 }
778 714
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 42d07fd..5e89eec 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -99,12 +99,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
99 public void TestAddAttachmentFromGround() 99 public void TestAddAttachmentFromGround()
100 { 100 {
101 TestHelpers.InMethod(); 101 TestHelpers.InMethod();
102// log4net.Config.XmlConfigurator.Configure(); 102// TestHelpers.EnableLogging();
103 103
104 AddPresence(); 104 AddPresence();
105 string attName = "att"; 105 string attName = "att";
106 106
107 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName).ParentGroup; 107 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, m_presence.UUID).ParentGroup;
108 108
109 m_attMod.AttachObject(m_presence, so, (uint)AttachmentPoint.Chest, false); 109 m_attMod.AttachObject(m_presence, so, (uint)AttachmentPoint.Chest, false);
110 110
@@ -123,6 +123,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
123 Assert.That( 123 Assert.That(
124 m_presence.Appearance.GetAttachpoint(attSo.FromItemID), 124 m_presence.Appearance.GetAttachpoint(attSo.FromItemID),
125 Is.EqualTo((int)AttachmentPoint.Chest)); 125 Is.EqualTo((int)AttachmentPoint.Chest));
126
127 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID));
128 Assert.That(attachmentItem, Is.Not.Null);
129 Assert.That(attachmentItem.Name, Is.EqualTo(attName));
130
131 InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(m_presence.UUID, AssetType.Object);
132 Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
133
134// TestHelpers.DisableLogging();
126 } 135 }
127 136
128 [Test] 137 [Test]
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 8171487..f219d4c 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -295,9 +295,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
295 return UUID.Zero; 295 return UUID.Zero;
296 } 296 }
297 297
298 public virtual UUID CopyToInventory(DeRezAction action, UUID folderID, 298 public virtual List<InventoryItemBase> CopyToInventory(
299 List<SceneObjectGroup> objectGroups, IClientAPI remoteClient) 299 DeRezAction action, UUID folderID,
300 List<SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool asAttachment)
300 { 301 {
302 List<InventoryItemBase> copiedItems = new List<InventoryItemBase>();
303
301 Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>(); 304 Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>();
302 305
303 if (CoalesceMultipleObjectsToInventory) 306 if (CoalesceMultipleObjectsToInventory)
@@ -324,16 +327,16 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
324 } 327 }
325 } 328 }
326 329
327 // This is method scoped and will be returned. It will be the 330// m_log.DebugFormat(
328 // last created asset id 331// "[INVENTORY ACCESS MODULE]: Copying {0} object bundles to folder {1} action {2} for {3}",
329 UUID assetID = UUID.Zero; 332// bundlesToCopy.Count, folderID, action, remoteClient.Name);
330 333
331 // Each iteration is really a separate asset being created, 334 // Each iteration is really a separate asset being created,
332 // with distinct destinations as well. 335 // with distinct destinations as well.
333 foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values) 336 foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values)
334 assetID = CopyBundleToInventory(action, folderID, bundle, remoteClient); 337 copiedItems.Add(CopyBundleToInventory(action, folderID, bundle, remoteClient, asAttachment));
335 338
336 return assetID; 339 return copiedItems;
337 } 340 }
338 341
339 /// <summary> 342 /// <summary>
@@ -344,12 +347,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
344 /// <param name="folderID"></param> 347 /// <param name="folderID"></param>
345 /// <param name="objlist"></param> 348 /// <param name="objlist"></param>
346 /// <param name="remoteClient"></param> 349 /// <param name="remoteClient"></param>
347 /// <returns></returns> 350 /// <param name="asAttachment">Should be true if the bundle is being copied as an attachment. This prevents
348 protected UUID CopyBundleToInventory( 351 /// attempted serialization of any script state which would abort any operating scripts.</param>
349 DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient) 352 /// <returns>The inventory item created by the copy</returns>
353 protected InventoryItemBase CopyBundleToInventory(
354 DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient,
355 bool asAttachment)
350 { 356 {
351 UUID assetID = UUID.Zero;
352
353 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); 357 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
354 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); 358 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
355 359
@@ -385,18 +389,27 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
385 389
386 string itemXml; 390 string itemXml;
387 391
392 // If we're being called from a script, then trying to serialize that same script's state will not complete
393 // in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if
394 // the client/server crashes rather than logging out normally, the attachment's scripts will resume
395 // without state on relog. Arguably, this is what we want anyway.
388 if (objlist.Count > 1) 396 if (objlist.Count > 1)
389 itemXml = CoalescedSceneObjectsSerializer.ToXml(coa); 397 itemXml = CoalescedSceneObjectsSerializer.ToXml(coa, !asAttachment);
390 else 398 else
391 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0]); 399 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment);
392 400
393 // Restore the position of each group now that it has been stored to inventory. 401 // Restore the position of each group now that it has been stored to inventory.
394 foreach (SceneObjectGroup objectGroup in objlist) 402 foreach (SceneObjectGroup objectGroup in objlist)
395 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; 403 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
396 404
397 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); 405 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
406
407// m_log.DebugFormat(
408// "[INVENTORY ACCESS MODULE]: Created item is {0}",
409// item != null ? item.ID.ToString() : "NULL");
410
398 if (item == null) 411 if (item == null)
399 return UUID.Zero; 412 return null;
400 413
401 // Can't know creator is the same, so null it in inventory 414 // Can't know creator is the same, so null it in inventory
402 if (objlist.Count > 1) 415 if (objlist.Count > 1)
@@ -406,7 +419,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
406 } 419 }
407 else 420 else
408 { 421 {
409 item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); 422 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
423 item.CreatorData = objlist[0].RootPart.CreatorData;
410 item.SaleType = objlist[0].RootPart.ObjectSaleType; 424 item.SaleType = objlist[0].RootPart.ObjectSaleType;
411 item.SalePrice = objlist[0].RootPart.SalePrice; 425 item.SalePrice = objlist[0].RootPart.SalePrice;
412 } 426 }
@@ -419,8 +433,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
419 objlist[0].OwnerID.ToString()); 433 objlist[0].OwnerID.ToString());
420 m_Scene.AssetService.Store(asset); 434 m_Scene.AssetService.Store(asset);
421 435
422 item.AssetID = asset.FullID; 436 item.AssetID = asset.FullID;
423 assetID = asset.FullID;
424 437
425 if (DeRezAction.SaveToExistingUserInventoryItem == action) 438 if (DeRezAction.SaveToExistingUserInventoryItem == action)
426 { 439 {
@@ -453,9 +466,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
453 466
454 // This is a hook to do some per-asset post-processing for subclasses that need that 467 // This is a hook to do some per-asset post-processing for subclasses that need that
455 if (remoteClient != null) 468 if (remoteClient != null)
456 ExportAsset(remoteClient.AgentId, assetID); 469 ExportAsset(remoteClient.AgentId, asset.FullID);
457 470
458 return assetID; 471 return item;
459 } 472 }
460 473
461 protected virtual void ExportAsset(UUID agentID, UUID assetID) 474 protected virtual void ExportAsset(UUID agentID, UUID assetID)
@@ -643,7 +656,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
643 { 656 {
644 // Catch all. Use lost & found 657 // Catch all. Use lost & found
645 // 658 //
646
647 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); 659 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
648 } 660 }
649 } 661 }
@@ -964,8 +976,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
964 976
965 so.FromFolderID = item.Folder; 977 so.FromFolderID = item.Folder;
966 978
967// Console.WriteLine("rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}", 979// m_log.DebugFormat(
968// rootPart.OwnerID, item.Owner, item.CurrentPermissions); 980// "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}",
981// rootPart.OwnerID, item.Owner, item.CurrentPermissions);
969 982
970 if ((rootPart.OwnerID != item.Owner) || 983 if ((rootPart.OwnerID != item.Owner) ||
971 (item.CurrentPermissions & 16) != 0) 984 (item.CurrentPermissions & 16) != 0)