From 3611d33b00650ccc71994b331e4c6595f95d3131 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Mon, 18 Mar 2013 22:04:27 +0000
Subject: Improve rejection of any attempt to reattach an object that is
 already attached.

This also adds/extends regression tests for wearing attachments directly for the scene and attempting to reattach/rewear already attached objects.
---
 .../Avatar/Attachments/AttachmentsModule.cs        |  24 +--
 .../Attachments/Tests/AttachmentsModuleTests.cs    | 201 +++++++++++++++++++--
 2 files changed, 194 insertions(+), 31 deletions(-)

(limited to 'OpenSim')

diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 2092d6f..1c28f49 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -305,6 +305,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
         private bool AttachObjectInternal(
             IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp, bool resumeScripts)
         {
+            if (sp.GetAttachments().Contains(group))
+            {
+//                m_log.WarnFormat(
+//                    "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
+//                    group.Name, group.LocalId, sp.Name, AttachmentPt);
+
+                return false;
+            }
+
 //                m_log.DebugFormat(
 //                    "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
 //                    group.Name, group.LocalId, sp.Name, attachmentPt, silent);
@@ -318,15 +327,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
                 return false;
             }
 
-            if (sp.GetAttachments(attachmentPt).Contains(group))
-            {
-//                m_log.WarnFormat(
-//                    "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
-//                    group.Name, group.LocalId, sp.Name, AttachmentPt);
-
-                return false;
-            }
-
             Vector3 attachPos = group.AbsolutePosition;
 
             // TODO: this short circuits multiple attachments functionality  in  LL viewer 2.1+ and should
@@ -336,13 +336,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
             // If the attachment point isn't the same as the one previously used
             // set it's offset position = 0 so that it appears on the attachment point
             // and not in a weird location somewhere unknown.
-            if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint)
+            if (attachmentPt != (uint)AttachmentPoint.Default && attachmentPt != group.AttachmentPoint)
             {
                 attachPos = Vector3.Zero;
             }
 
-            // AttachmentPt 0 means the client chose to 'wear' the attachment.
-            if (attachmentPt == 0)
+            // AttachmentPt 0 (default) means the client chose to 'wear' the attachment.
+            if (attachmentPt == (uint)AttachmentPoint.Default)
             {
                 // Check object for stored attachment point
                 attachmentPt = group.AttachmentPoint;
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 624adcf..719a59c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -228,6 +228,120 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
             Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
         }
 
+        [Test]
+        public void TestWearAttachmentFromGround()
+        {
+            TestHelpers.InMethod();
+//            TestHelpers.EnableLogging();
+
+            Scene scene = CreateTestScene();
+            UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
+            ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
+
+            SceneObjectGroup so2 = SceneHelpers.AddSceneObject(scene, "att2", sp.UUID);
+
+            {
+                SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID);
+
+                m_numberOfAttachEventsFired = 0;
+                scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, false);
+
+                // Check status on scene presence
+                Assert.That(sp.HasAttachments(), Is.True);
+                List<SceneObjectGroup> attachments = sp.GetAttachments();
+                Assert.That(attachments.Count, Is.EqualTo(1));
+                SceneObjectGroup attSo = attachments[0];
+                Assert.That(attSo.Name, Is.EqualTo(so.Name));
+                Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
+                Assert.That(attSo.IsAttachment);
+                Assert.That(attSo.UsesPhysics, Is.False);
+                Assert.That(attSo.IsTemporary, Is.False);
+
+                // Check item status
+                Assert.That(
+                    sp.Appearance.GetAttachpoint(attSo.FromItemID),
+                    Is.EqualTo((int)AttachmentPoint.LeftHand));
+
+                InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID));
+                Assert.That(attachmentItem, Is.Not.Null);
+                Assert.That(attachmentItem.Name, Is.EqualTo(so.Name));
+
+                InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
+                Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
+
+                Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(2));
+
+                // Check events
+                Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
+            }
+
+            // Test wearing a different attachment from the ground.
+            {
+                scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, false);
+
+                // Check status on scene presence
+                Assert.That(sp.HasAttachments(), Is.True);
+                List<SceneObjectGroup> attachments = sp.GetAttachments();
+                Assert.That(attachments.Count, Is.EqualTo(1));
+                SceneObjectGroup attSo = attachments[0];
+                Assert.That(attSo.Name, Is.EqualTo(so2.Name));
+                Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
+                Assert.That(attSo.IsAttachment);
+                Assert.That(attSo.UsesPhysics, Is.False);
+                Assert.That(attSo.IsTemporary, Is.False);
+
+                // Check item status
+                Assert.That(
+                    sp.Appearance.GetAttachpoint(attSo.FromItemID),
+                    Is.EqualTo((int)AttachmentPoint.LeftHand));
+
+                InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID));
+                Assert.That(attachmentItem, Is.Not.Null);
+                Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name));
+
+                InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
+                Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
+
+                Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
+
+                // Check events
+                Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3));
+            }
+
+            // Test rewearing an already worn attachment from ground.  Nothing should happen.
+            {
+                scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, false);
+
+                // Check status on scene presence
+                Assert.That(sp.HasAttachments(), Is.True);
+                List<SceneObjectGroup> attachments = sp.GetAttachments();
+                Assert.That(attachments.Count, Is.EqualTo(1));
+                SceneObjectGroup attSo = attachments[0];
+                Assert.That(attSo.Name, Is.EqualTo(so2.Name));
+                Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
+                Assert.That(attSo.IsAttachment);
+                Assert.That(attSo.UsesPhysics, Is.False);
+                Assert.That(attSo.IsTemporary, Is.False);
+
+                // Check item status
+                Assert.That(
+                    sp.Appearance.GetAttachpoint(attSo.FromItemID),
+                    Is.EqualTo((int)AttachmentPoint.LeftHand));
+
+                InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID));
+                Assert.That(attachmentItem, Is.Not.Null);
+                Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name));
+
+                InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
+                Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
+
+                Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
+
+                // Check events
+                Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3));
+            }
+        }
+
         /// <summary>
         /// Test that we do not attempt to attach an in-world object that someone else is sitting on.
         /// </summary>
@@ -275,28 +389,54 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
 
             InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
 
-            m_numberOfAttachEventsFired = 0;
-            scene.AttachmentsModule.RezSingleAttachmentFromInventory(
-                sp, attItem.ID, (uint)AttachmentPoint.Chest);
+            {
+                scene.AttachmentsModule.RezSingleAttachmentFromInventory(
+                    sp, attItem.ID, (uint)AttachmentPoint.Chest);
 
-            // Check scene presence status
-            Assert.That(sp.HasAttachments(), Is.True);
-            List<SceneObjectGroup> attachments = sp.GetAttachments();
-            Assert.That(attachments.Count, Is.EqualTo(1));
-            SceneObjectGroup attSo = attachments[0];
-            Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
-            Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
-            Assert.That(attSo.IsAttachment);
-            Assert.That(attSo.UsesPhysics, Is.False);
-            Assert.That(attSo.IsTemporary, Is.False);
+                // Check scene presence status
+                Assert.That(sp.HasAttachments(), Is.True);
+                List<SceneObjectGroup> attachments = sp.GetAttachments();
+                Assert.That(attachments.Count, Is.EqualTo(1));
+                SceneObjectGroup attSo = attachments[0];
+                Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
+                Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
+                Assert.That(attSo.IsAttachment);
+                Assert.That(attSo.UsesPhysics, Is.False);
+                Assert.That(attSo.IsTemporary, Is.False);
 
-            // Check appearance status
-            Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
-            Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
-            Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
+                // Check appearance status
+                Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
+                Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
+                Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
 
-            // Check events
-            Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
+                // Check events
+                Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
+            }
+
+            // Test attaching an already attached attachment
+            {
+                scene.AttachmentsModule.RezSingleAttachmentFromInventory(
+                    sp, attItem.ID, (uint)AttachmentPoint.Chest);
+
+                // Check scene presence status
+                Assert.That(sp.HasAttachments(), Is.True);
+                List<SceneObjectGroup> attachments = sp.GetAttachments();
+                Assert.That(attachments.Count, Is.EqualTo(1));
+                SceneObjectGroup attSo = attachments[0];
+                Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
+                Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
+                Assert.That(attSo.IsAttachment);
+                Assert.That(attSo.UsesPhysics, Is.False);
+                Assert.That(attSo.IsTemporary, Is.False);
+
+                // Check appearance status
+                Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
+                Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
+                Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
+
+                // Check events
+                Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
+            }
         }
 
         /// <summary>
@@ -316,6 +456,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
             InventoryItemBase attItem2 = CreateAttachmentItem(scene, ua1.PrincipalID, "att2", 0x11, 0x21);
 
             {
+                m_numberOfAttachEventsFired = 0;
                 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem1.ID, (uint)AttachmentPoint.Default);
 
                 // default attachment point is currently the left hand.
@@ -360,6 +501,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
                 // Check events
                 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3));
             }
+
+            // Test wearing an already attached attachment
+            {
+                scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default);
+
+                // default attachment point is currently the left hand.
+                Assert.That(sp.HasAttachments(), Is.True);
+                List<SceneObjectGroup> attachments = sp.GetAttachments();
+                Assert.That(attachments.Count, Is.EqualTo(1));
+                SceneObjectGroup attSo = attachments[0];
+                Assert.That(attSo.Name, Is.EqualTo(attItem2.Name));
+                Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
+                Assert.That(attSo.IsAttachment);
+
+                // Check appearance status
+                Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
+                Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand));
+                Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
+
+                // Check events
+                Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3));
+            }
         }
 
         /// <summary>
-- 
cgit v1.1