From 7e5d5537815d5626387d8638da769192ab3c7ca8 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 15 Mar 2013 23:46:49 +0000 Subject: Make the LSL memory functions virtual so script engines can override them if they have different memory management. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 8adf4d9..f07b645 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6068,7 +6068,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return m_host.ParentGroup.AttachmentPoint; } - public LSL_Integer llGetFreeMemory() + public virtual LSL_Integer llGetFreeMemory() { m_host.AddScriptLPS(1); // Make scripts designed for LSO happy @@ -11560,7 +11560,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return 16384; } - public LSL_Integer llGetUsedMemory() + public virtual LSL_Integer llGetUsedMemory() { m_host.AddScriptLPS(1); // The value returned for LSO scripts in SL @@ -11790,4 +11790,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } -} \ No newline at end of file +} -- cgit v1.1 From a7a9a8a614549c7492e4954189e9f4df2473ca1e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 18 Mar 2013 20:42:08 +0000 Subject: Fix recent regression where an item worn to an attachment point that was already occupied did not remove the previous attachment (current behaviour) Regression was commit ccd6f4 (Tue Mar 5 23:47:36 2013) Added regression test for this case. --- .../Avatar/Attachments/AttachmentsModule.cs | 178 +++++++++++---------- .../Attachments/Tests/AttachmentsModuleTests.cs | 64 +++++++- 2 files changed, 153 insertions(+), 89 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index b6a7481..2092d6f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -289,16 +289,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (!Enabled) return false; - if (AttachObjectInternal(sp, group, attachmentPt, silent, temp)) - { - m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); - return true; - } - - return false; + return AttachObjectInternal(sp, group, attachmentPt, silent, temp, false); } - - private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp) + + /// + /// Internal method which actually does all the work for attaching an object. + /// + /// The object attached. + /// + /// The object to attach. + /// + /// + /// + /// If true then scripts are resumed on the attached object. + private bool AttachObjectInternal( + IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp, bool resumeScripts) { // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", @@ -322,44 +327,44 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return false; } + Vector3 attachPos = group.AbsolutePosition; + + // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should + // be removed when that functionality is implemented in opensim + attachmentPt &= 0x7f; + + // 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) + { + attachPos = Vector3.Zero; + } + + // AttachmentPt 0 means the client chose to 'wear' the attachment. + if (attachmentPt == 0) + { + // Check object for stored attachment point + attachmentPt = group.AttachmentPoint; + } + + // if we still didn't find a suitable attachment point....... + if (attachmentPt == 0) + { + // Stick it on left hand with Zero Offset from the attachment point. + attachmentPt = (uint)AttachmentPoint.LeftHand; + attachPos = Vector3.Zero; + } + // Remove any previous attachments List existingAttachments = sp.GetAttachments(attachmentPt); // At the moment we can only deal with a single attachment if (existingAttachments.Count != 0 && existingAttachments[0].FromItemID != UUID.Zero) - DetachSingleAttachmentToInv(sp, group); + DetachSingleAttachmentToInv(sp, existingAttachments[0]); lock (sp.AttachmentsSyncLock) { - Vector3 attachPos = group.AbsolutePosition; - - // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should - // be removed when that functionality is implemented in opensim - attachmentPt &= 0x7f; - - // 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) - { - attachPos = Vector3.Zero; - } - - // AttachmentPt 0 means the client chose to 'wear' the attachment. - if (attachmentPt == 0) - { - // Check object for stored attachment point - attachmentPt = group.AttachmentPoint; - } - - // if we still didn't find a suitable attachment point....... - if (attachmentPt == 0) - { - // Stick it on left hand with Zero Offset from the attachment point. - attachmentPt = (uint)AttachmentPoint.LeftHand; - attachPos = Vector3.Zero; - } - group.AttachmentPoint = attachmentPt; group.AbsolutePosition = attachPos; @@ -367,6 +372,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp); AttachToAgent(sp, group, attachmentPt, attachPos, silent); + + if (resumeScripts) + { + // Fire after attach, so we don't get messy perms dialogs + // 4 == AttachedRez + group.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); + group.ResumeScripts(); + } + + // Do this last so that event listeners have access to all the effects of the attachment + m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); } return true; @@ -391,8 +407,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return null; // m_log.DebugFormat( -// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}", -// (AttachmentPoint)AttachmentPt, itemID, sp.Name); +// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2} in {3}", +// (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name); // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should // be removed when that functionality is implemented in opensim @@ -525,6 +541,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return; } +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: Detaching object {0} {1} for {2} in {3}", +// so.Name, so.LocalId, sp.Name, m_scene.Name); + // Scripts MUST be snapshotted before the object is // removed from the scene because doing otherwise will // clobber the run flag @@ -846,60 +866,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return null; } - // Remove any previous attachments - List attachments = sp.GetAttachments(attachmentPt); - - // At the moment we can only deal with a single attachment - if (attachments.Count != 0) - DetachSingleAttachmentToInv(sp, attachments[0]); - - lock (sp.AttachmentsSyncLock) - { // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", // objatt.Name, sp.Name, attachmentPt, m_scene.Name); - // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. - objatt.HasGroupChanged = false; - bool tainted = false; - if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) - tainted = true; - - // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal - // course of events. If not, then it's probably not worth trying to recover the situation - // since this is more likely to trigger further exceptions and confuse later debugging. If - // exceptions can be thrown in expected error conditions (not NREs) then make this consistent - // since other normal error conditions will simply return false instead. - // This will throw if the attachment fails - try - { - AttachObjectInternal(sp, objatt, attachmentPt, false, false); - } - catch (Exception e) - { - m_log.ErrorFormat( - "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", - objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); - - // Make sure the object doesn't stick around and bail - sp.RemoveAttachment(objatt); - m_scene.DeleteSceneObject(objatt, false); - return null; - } - - if (tainted) - objatt.HasGroupChanged = true; + // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. + objatt.HasGroupChanged = false; + bool tainted = false; + if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) + tainted = true; + + // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal + // course of events. If not, then it's probably not worth trying to recover the situation + // since this is more likely to trigger further exceptions and confuse later debugging. If + // exceptions can be thrown in expected error conditions (not NREs) then make this consistent + // since other normal error conditions will simply return false instead. + // This will throw if the attachment fails + try + { + AttachObjectInternal(sp, objatt, attachmentPt, false, false, true); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", + objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); - // Fire after attach, so we don't get messy perms dialogs - // 4 == AttachedRez - objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); - objatt.ResumeScripts(); + // Make sure the object doesn't stick around and bail + sp.RemoveAttachment(objatt); + m_scene.DeleteSceneObject(objatt, false); + return null; + } - // Do this last so that event listeners have access to all the effects of the attachment - m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); + if (tainted) + objatt.HasGroupChanged = true; - return objatt; - } + return objatt; } /// diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 0ee01c7..624adcf 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -293,7 +293,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // 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 @@ -301,6 +300,69 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests } /// + /// Test wearing an attachment from inventory, as opposed to explicit choosing the rez point + /// + [Test] + public void TestWearAttachmentFromInventory() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + Scene scene = CreateTestScene(); + UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); + ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); + + InventoryItemBase attItem1 = CreateAttachmentItem(scene, ua1.PrincipalID, "att1", 0x10, 0x20); + InventoryItemBase attItem2 = CreateAttachmentItem(scene, ua1.PrincipalID, "att2", 0x11, 0x21); + + { + scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem1.ID, (uint)AttachmentPoint.Default); + + // default attachment point is currently the left hand. + Assert.That(sp.HasAttachments(), Is.True); + List attachments = sp.GetAttachments(); + Assert.That(attachments.Count, Is.EqualTo(1)); + SceneObjectGroup attSo = attachments[0]; + Assert.That(attSo.Name, Is.EqualTo(attItem1.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(attItem1.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); + Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); + + // Check events + Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); + } + + // Test wearing a second attachment at the same position + // Until multiple attachments at one point is implemented, this will remove the first attachment + // This test relies on both attachments having the same default attachment point (in this case LeftHand + // since none other has been set). + { + scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default); + + // default attachment point is currently the left hand. + Assert.That(sp.HasAttachments(), Is.True); + List 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)); + } + } + + /// /// Test specific conditions associated with rezzing a scripted attachment from inventory. /// [Test] -- cgit v1.1 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 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 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 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 that we do not attempt to attach an in-world object that someone else is sitting on. /// @@ -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 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 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 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)); + } } /// @@ -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 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)); + } } /// -- cgit v1.1