diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 0589748577..1829c8d47e 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -1614,12 +1614,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController } // Attachments - Dictionary attachments = avatarAppearance.Attachments; + List attachments = avatarAppearance.GetAttachments(); - foreach (KeyValuePair attachment in attachments) + foreach (AvatarAttachment attachment in attachments) { - int attachpoint = attachment.Value.AttachPoint; - UUID itemID = attachment.Value.ItemID; + int attachpoint = attachment.AttachPoint; + UUID itemID = attachment.ItemID; if (itemID != UUID.Zero) { diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs index 8271d76b44..3f6d4d640b 100644 --- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs +++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs @@ -27,6 +27,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Xml; using OpenMetaverse; using OpenSim.Framework; @@ -765,25 +766,19 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory FormatPart(rdata, "UnderShirt", rdata.userAppearance.UnderShirtItem, rdata.userAppearance.UnderShirtAsset); FormatPart(rdata, "UnderPants", rdata.userAppearance.UnderPantsItem, rdata.userAppearance.UnderPantsAsset); - Hashtable attachments = rdata.userAppearance.GetAttachments(); + Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting attachments", MsgId); - if (attachments != null) + rdata.writer.WriteStartElement("Attachments"); + List attachments = rdata.userAppearance.GetAttachments(); + foreach (AvatarAttachment attach in attachments) { - - Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting attachments", MsgId); - - rdata.writer.WriteStartElement("Attachments"); - for (int i = 0; i < attachments.Count; i++) - { - Hashtable attachment = attachments[i] as Hashtable; - rdata.writer.WriteStartElement("Attachment"); - rdata.writer.WriteAttributeString("AtPoint", i.ToString()); - rdata.writer.WriteAttributeString("Item", (string) attachment["item"]); - rdata.writer.WriteAttributeString("Asset", (string) attachment["asset"]); - rdata.writer.WriteEndElement(); - } + rdata.writer.WriteStartElement("Attachment"); + rdata.writer.WriteAttributeString("AtPoint", attach.AttachPoint.ToString()); + rdata.writer.WriteAttributeString("Item", attach.ItemID.ToString()); + rdata.writer.WriteAttributeString("Asset", attach.AssetID.ToString()); rdata.writer.WriteEndElement(); } + rdata.writer.WriteEndElement(); Primitive.TextureEntry texture = rdata.userAppearance.Texture; diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index 55646dda91..ba0cad2dde 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -51,7 +51,7 @@ namespace OpenSim.Framework protected byte[] m_visualparams; protected Primitive.TextureEntry m_texture; protected AvatarWearable[] m_wearables; - protected Dictionary m_attachments; + protected Dictionary> m_attachments; protected float m_avatarHeight = 0; protected float m_hipOffset = 0; @@ -85,11 +85,6 @@ namespace OpenSim.Framework set { m_wearables = value; } } - public virtual Dictionary Attachments - { - get { return m_attachments; } - } - public virtual UUID BodyItem { get { return m_wearables[AvatarWearable.BODY].ItemID; } set { m_wearables[AvatarWearable.BODY].ItemID = value; } @@ -246,7 +241,7 @@ namespace OpenSim.Framework SetDefaultParams(); SetHeight(); - m_attachments = new Dictionary(); + m_attachments = new Dictionary>(); } public AvatarAppearance(UUID avatarID, OSDMap map) @@ -284,7 +279,7 @@ namespace OpenSim.Framework SetHeight(); - m_attachments = new Dictionary(); + m_attachments = new Dictionary>(); } public AvatarAppearance(AvatarAppearance appearance) @@ -302,7 +297,7 @@ namespace OpenSim.Framework SetDefaultParams(); SetHeight(); - m_attachments = new Dictionary(); + m_attachments = new Dictionary>(); return; } @@ -329,9 +324,10 @@ namespace OpenSim.Framework if (appearance.VisualParams != null) m_visualparams = (byte[])appearance.VisualParams.Clone(); - m_attachments = new Dictionary(); - foreach (KeyValuePair kvp in appearance.Attachments) - m_attachments[kvp.Key] = new AvatarAttachment(kvp.Value); + // Copy the attachment, force append mode since that ensures consistency + m_attachments = new Dictionary>(); + foreach (AvatarAttachment attachment in appearance.GetAttachments()) + AppendAttachment(new AvatarAttachment(attachment)); } protected virtual void SetDefaultWearables() @@ -487,12 +483,41 @@ namespace OpenSim.Framework } // DEBUG OFF - public void SetAttachments(AvatarAttachment[] data) + /// + /// Get a list of the attachments, note that there may be + /// duplicate attachpoints + /// + public List GetAttachments() { - foreach (AvatarAttachment attach in data) - m_attachments[attach.AttachPoint] = new AvatarAttachment(attach); + List alist = new List(); + foreach (KeyValuePair> kvp in m_attachments) + { + foreach (AvatarAttachment attach in kvp.Value) + alist.Add(new AvatarAttachment(attach)); + } + + return alist; + } + + internal void AppendAttachment(AvatarAttachment attach) + { + if (! m_attachments.ContainsKey(attach.AttachPoint)) + m_attachments[attach.AttachPoint] = new List(); + m_attachments[attach.AttachPoint].Add(attach); } + internal void ReplaceAttachment(AvatarAttachment attach) + { + m_attachments[attach.AttachPoint] = new List(); + m_attachments[attach.AttachPoint].Add(attach); + } + + /// + /// Add an attachment, if the attachpoint has the + /// 0x80 bit set then we assume this is an append + /// operation otherwise we replace whatever is + /// currently attached at the attachpoint + /// public void SetAttachment(int attachpoint, UUID item, UUID asset) { if (attachpoint == 0) @@ -505,67 +530,47 @@ namespace OpenSim.Framework return; } - m_attachments[attachpoint] = new AvatarAttachment(attachpoint,item,asset); - } - - public Hashtable GetAttachments() - { - if (m_attachments.Count == 0) - return null; - - Hashtable ret = new Hashtable(); - - foreach (KeyValuePair kvp in m_attachments) + // check if this is an append or a replace, 0x80 marks it as an append + if ((attachpoint & 0x80) > 0) { - Hashtable data = new Hashtable(); - data["item"] = kvp.Value.ItemID.ToString(); - data["asset"] = kvp.Value.AssetID.ToString(); - - ret[kvp.Key] = data; + // strip the append bit + int point = attachpoint & 0x7F; + AppendAttachment(new AvatarAttachment(point, item, asset)); + } + else + { + ReplaceAttachment(new AvatarAttachment(attachpoint,item,asset)); } - - return ret; - } - - public List GetAttachedPoints() - { - return new List(m_attachments.Keys); - } - - public UUID GetAttachedItem(int attachpoint) - { - if (!m_attachments.ContainsKey(attachpoint)) - return UUID.Zero; - - return m_attachments[attachpoint].ItemID; - } - - public UUID GetAttachedAsset(int attachpoint) - { - if (!m_attachments.ContainsKey(attachpoint)) - return UUID.Zero; - - return m_attachments[attachpoint].AssetID; } public int GetAttachpoint(UUID itemID) { - foreach (KeyValuePair kvp in m_attachments) + foreach (KeyValuePair> kvp in m_attachments) { - if (kvp.Value.ItemID == itemID) - { + int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; }); + if (index >= 0) return kvp.Key; - } } + return 0; } public void DetachAttachment(UUID itemID) { - int attachpoint = GetAttachpoint(itemID); + foreach (KeyValuePair> kvp in m_attachments) + { + int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; }); + if (index >= 0) + { + // Remove it from the list of attachments at that attach point + m_attachments[kvp.Key].RemoveAt(index); - if (attachpoint > 0) - m_attachments.Remove(attachpoint); + // And remove the list if there are no more attachments here + if (m_attachments[kvp.Key].Count == 0) + m_attachments.Remove(kvp.Key); + return; + } + } } public void ClearAttachments() @@ -607,8 +612,8 @@ namespace OpenSim.Framework // Attachments OSDArray attachs = new OSDArray(m_attachments.Count); - foreach (KeyValuePair kvp in m_attachments) - attachs.Add(kvp.Value.Pack()); + foreach (AvatarAttachment attach in GetAttachments()) + attachs.Add(attach.Pack()); data["attachments"] = attachs; return data; @@ -675,15 +680,12 @@ namespace OpenSim.Framework } // Attachments - m_attachments = new Dictionary(); + m_attachments = new Dictionary>(); if ((data != null) && (data["attachments"] != null) && (data["attachments"]).Type == OSDType.Array) { OSDArray attachs = (OSDArray)(data["attachments"]); for (int i = 0; i < attachs.Count; i++) - { - AvatarAttachment attach = new AvatarAttachment((OSDMap)attachs[i]); - m_attachments[attach.AttachPoint] = attach; - } + AppendAttachment(new AvatarAttachment((OSDMap)attachs[i])); } } catch (Exception e) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 5dc48d7402..f828a2d45a 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3657,15 +3657,16 @@ namespace OpenSim.Region.Framework.Scenes return; } - List attPoints = m_appearance.GetAttachedPoints(); - foreach (int p in attPoints) + List attachments = m_appearance.GetAttachments(); + foreach (AvatarAttachment attach in attachments) { if (m_isDeleted) return; - UUID itemID = m_appearance.GetAttachedItem(p); + int p = attach.AttachPoint; + UUID itemID = attach.ItemID; - //UUID assetID = m_appearance.GetAttachedAsset(p); + //UUID assetID = attach.AssetID; // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down // But they're not used anyway, the item is being looked up for now, so let's proceed. //if (UUID.Zero == assetID) diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs index 0786bd9821..922eaafeda 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs @@ -29,6 +29,7 @@ using System.Collections; using System.Collections.Generic; using System.Security; using OpenMetaverse; +using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; @@ -81,16 +82,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule get { List attachments = new List(); - Hashtable internalAttachments = GetSP().Appearance.GetAttachments(); - if (internalAttachments != null) + List internalAttachments = GetSP().Appearance.GetAttachments(); + foreach (AvatarAttachment attach in internalAttachments) { - foreach (DictionaryEntry element in internalAttachments) - { - Hashtable attachInfo = (Hashtable)element.Value; - attachments.Add(new SPAvatarAttachment(m_rootScene, this, (int) element.Key, - new UUID((string) attachInfo["item"]), - new UUID((string) attachInfo["asset"]), m_security)); - } + attachments.Add(new SPAvatarAttachment(m_rootScene, this, attach.AttachPoint, + new UUID(attach.ItemID), + new UUID(attach.AssetID), m_security)); } return attachments.ToArray(); diff --git a/OpenSim/Services/Interfaces/IAvatarService.cs b/OpenSim/Services/Interfaces/IAvatarService.cs index 93b977b534..eaa653439e 100644 --- a/OpenSim/Services/Interfaces/IAvatarService.cs +++ b/OpenSim/Services/Interfaces/IAvatarService.cs @@ -178,17 +178,11 @@ namespace OpenSim.Services.Interfaces Data["UnderShirtAsset"] = appearance.UnderShirtAsset.ToString(); // Attachments - Hashtable attachs = appearance.GetAttachments(); - if (attachs != null) - foreach (DictionaryEntry dentry in attachs) - { - if (dentry.Value != null) - { - Hashtable tab = (Hashtable)dentry.Value; - if (tab.ContainsKey("item") && tab["item"] != null) - Data["_ap_" + dentry.Key] = tab["item"].ToString(); - } - } + List attachments = appearance.GetAttachments(); + foreach (AvatarAttachment attach in attachments) + { + Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString(); + } } public AvatarAppearance ToAvatarAppearance(UUID owner)