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.
user_profiles
Justin Clark-Casey (justincc) 2013-03-18 20:42:08 +00:00
parent 46a81b3527
commit a7a9a8a614
2 changed files with 154 additions and 90 deletions

View File

@ -289,16 +289,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
if (!Enabled) if (!Enabled)
return false; return false;
if (AttachObjectInternal(sp, group, attachmentPt, silent, temp)) return AttachObjectInternal(sp, group, attachmentPt, silent, temp, false);
{
m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID);
return true;
} }
return false; /// <summary>
} /// Internal method which actually does all the work for attaching an object.
/// </summary>
private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp) /// <returns>The object attached.</returns>
/// <param name='sp'></param>
/// <param name='group'>The object to attach.</param>
/// <param name='attachmentPt'></param>
/// <param name='silent'></param>
/// <param name='temp'></param>
/// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param>
private bool AttachObjectInternal(
IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp, bool resumeScripts)
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
@ -322,15 +327,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return false; return false;
} }
// Remove any previous attachments
List<SceneObjectGroup> 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);
lock (sp.AttachmentsSyncLock)
{
Vector3 attachPos = group.AbsolutePosition; Vector3 attachPos = group.AbsolutePosition;
// TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
@ -360,6 +356,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
attachPos = Vector3.Zero; attachPos = Vector3.Zero;
} }
// Remove any previous attachments
List<SceneObjectGroup> 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, existingAttachments[0]);
lock (sp.AttachmentsSyncLock)
{
group.AttachmentPoint = attachmentPt; group.AttachmentPoint = attachmentPt;
group.AbsolutePosition = attachPos; group.AbsolutePosition = attachPos;
@ -367,6 +372,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp); UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp);
AttachToAgent(sp, group, attachmentPt, attachPos, silent); 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; return true;
@ -391,8 +407,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return null; return null;
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}", // "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2} in {3}",
// (AttachmentPoint)AttachmentPt, itemID, sp.Name); // (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name);
// TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
// be removed when that functionality is implemented in opensim // be removed when that functionality is implemented in opensim
@ -525,6 +541,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return; 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 // Scripts MUST be snapshotted before the object is
// removed from the scene because doing otherwise will // removed from the scene because doing otherwise will
// clobber the run flag // clobber the run flag
@ -846,15 +866,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return null; return null;
} }
// Remove any previous attachments
List<SceneObjectGroup> 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( // m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", // "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}",
// objatt.Name, sp.Name, attachmentPt, m_scene.Name); // objatt.Name, sp.Name, attachmentPt, m_scene.Name);
@ -873,7 +884,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// This will throw if the attachment fails // This will throw if the attachment fails
try try
{ {
AttachObjectInternal(sp, objatt, attachmentPt, false, false); AttachObjectInternal(sp, objatt, attachmentPt, false, false, true);
} }
catch (Exception e) catch (Exception e)
{ {
@ -890,17 +901,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
if (tainted) if (tainted)
objatt.HasGroupChanged = true; objatt.HasGroupChanged = true;
// Fire after attach, so we don't get messy perms dialogs
// 4 == AttachedRez
objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
objatt.ResumeScripts();
// 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);
return objatt; return objatt;
} }
}
/// <summary> /// <summary>
/// Update the user inventory to reflect an attachment /// Update the user inventory to reflect an attachment

View File

@ -293,13 +293,75 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
// Check appearance status // Check appearance status
Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
// Check events // Check events
Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
} }
/// <summary>
/// Test wearing an attachment from inventory, as opposed to explicit choosing the rez point
/// </summary>
[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<SceneObjectGroup> 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<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> /// <summary>
/// Test specific conditions associated with rezzing a scripted attachment from inventory. /// Test specific conditions associated with rezzing a scripted attachment from inventory.
/// </summary> /// </summary>