diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 206 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs | 13 |
2 files changed, 82 insertions, 137 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] |