Prevent multiple instances of the same item ID being appended to an AvatarAppearance

It looks like this was happening when AttachmentsModule.RezAttachments was doing a secondary set of each attachment to update with the asset ID (initially they only have the inventory ID).
However, with multi-attach this was appending a second copy of the same attachment rather than updating the data that was already there.
This commit requires both simulator and service to be updated.
user_profiles
Justin Clark-Casey (justincc) 2013-03-19 21:44:18 +00:00
parent c2e4f8aed5
commit 3648164219
3 changed files with 60 additions and 34 deletions

View File

@ -459,45 +459,59 @@ namespace OpenSim.Framework
if (attachpoint == 0) if (attachpoint == 0)
return false; return false;
if (item == UUID.Zero) lock (m_attachments)
{ {
lock (m_attachments) if (item == UUID.Zero)
{ {
if (m_attachments.ContainsKey(attachpoint)) if (m_attachments.ContainsKey(attachpoint))
{ {
m_attachments.Remove(attachpoint); m_attachments.Remove(attachpoint);
return true; return true;
} }
return false;
} }
return false; // When a user logs in, the attachment item ids are pulled from persistence in the Avatars table. However,
} // the asset ids are not saved. When the avatar enters a simulator the attachments are set again. If
// we simply perform an item check here then the asset ids (which are now present) are never set, and NPC attachments
// later fail unless the attachment is detached and reattached.
//
// Therefore, we will carry on with the set if the existing attachment has no asset id.
AvatarAttachment existingAttachment = GetAttachmentForItem(item);
if (existingAttachment != null)
{
// m_log.DebugFormat(
// "[AVATAR APPEARANCE]: Found existing attachment for {0}, asset {1} at point {2}",
// existingAttachment.ItemID, existingAttachment.AssetID, existingAttachment.AttachPoint);
// When a user logs in, the attachment item ids are pulled from persistence in the Avatars table. However, if (existingAttachment.AssetID != UUID.Zero && existingAttachment.AttachPoint == (attachpoint & 0x7F))
// the asset ids are not saved. When the avatar enters a simulator the attachments are set again. If {
// we simply perform an item check here then the asset ids (which are now present) are never set, and NPC attachments m_log.DebugFormat(
// later fail unless the attachment is detached and reattached. "[AVATAR APPEARANCE]: Ignoring attempt to attach an already attached item {0} at point {1}",
// item, attachpoint);
// Therefore, we will carry on with the set if the existing attachment has no asset id.
AvatarAttachment existingAttachment = GetAttachmentForItem(item);
if (existingAttachment != null
&& existingAttachment.AssetID != UUID.Zero
&& existingAttachment.AttachPoint == (attachpoint & 0x7F))
{
// m_log.DebugFormat("[AVATAR APPEARANCE] attempt to attach an already attached item {0}",item);
return false;
}
// check if this is an append or a replace, 0x80 marks it as an append return false;
if ((attachpoint & 0x80) > 0) }
{ else
// strip the append bit {
int point = attachpoint & 0x7F; // Remove it here so that the later append does not add a second attachment but we still update
AppendAttachment(new AvatarAttachment(point, item, asset)); // the assetID
} DetachAttachment(existingAttachment.ItemID);
else }
{ }
ReplaceAttachment(new AvatarAttachment(attachpoint,item, asset));
// check if this is an append or a replace, 0x80 marks it as an append
if ((attachpoint & 0x80) > 0)
{
// strip the append bit
int point = attachpoint & 0x7F;
AppendAttachment(new AvatarAttachment(point, item, asset));
}
else
{
ReplaceAttachment(new AvatarAttachment(attachpoint,item, asset));
}
} }
return true; return true;
@ -547,6 +561,10 @@ namespace OpenSim.Framework
int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; }); int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
if (index >= 0) if (index >= 0)
{ {
// m_log.DebugFormat(
// "[AVATAR APPEARANCE]: Detaching attachment {0}, index {1}, point {2}",
// m_attachments[kvp.Key][index].ItemID, index, m_attachments[kvp.Key][index].AttachPoint);
// Remove it from the list of attachments at that attach point // Remove it from the list of attachments at that attach point
m_attachments[kvp.Key].RemoveAt(index); m_attachments[kvp.Key].RemoveAt(index);

View File

@ -547,8 +547,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
} }
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Detaching object {0} {1} for {2} in {3}", // "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}",
// so.Name, so.LocalId, sp.Name, m_scene.Name); // so.Name, so.LocalId, so.FromItemID, 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

View File

@ -326,7 +326,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
public void QueueAppearanceSave(UUID agentid) public void QueueAppearanceSave(UUID agentid)
{ {
// m_log.WarnFormat("[AVFACTORY]: Queue appearance save for {0}", agentid); // m_log.DebugFormat("[AVFACTORY]: Queueing appearance save for {0}", agentid);
// 10000 ticks per millisecond, 1000 milliseconds per second // 10000 ticks per millisecond, 1000 milliseconds per second
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000); long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000);
@ -529,7 +529,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
return; return;
} }
// m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid); // m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid);
// This could take awhile since it needs to pull inventory // This could take awhile since it needs to pull inventory
// We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape
@ -538,6 +538,14 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
// multiple save requests. // multiple save requests.
SetAppearanceAssets(sp.UUID, sp.Appearance); SetAppearanceAssets(sp.UUID, sp.Appearance);
// List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
// foreach (AvatarAttachment att in attachments)
// {
// m_log.DebugFormat(
// "[AVFACTORY]: For {0} saving attachment {1} at point {2}",
// sp.Name, att.ItemID, att.AttachPoint);
// }
m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
// Trigger this here because it's the final step in the set/queue/save process for appearance setting. // Trigger this here because it's the final step in the set/queue/save process for appearance setting.