From 267f18925d06ca05e2a5ffbfbb63582783762439 Mon Sep 17 00:00:00 2001 From: Master ScienceSim Date: Thu, 21 Oct 2010 16:48:58 -0700 Subject: [PATCH 01/12] First attempt to get multiple attachments working to support viewer2. The attachment code appears to work correctly for 1.23 viewers so, in spite of some big changes in the internal representation, there don't appear to be regressions. That being said, I still can't get a viewer2 avatar to show correctly. --- .../RemoteController/RemoteAdminPlugin.cs | 8 +- .../Rest/Inventory/RestAppearanceServices.cs | 25 ++-- OpenSim/Framework/AvatarAppearance.cs | 138 +++++++++--------- .../Region/Framework/Scenes/ScenePresence.cs | 9 +- .../Scripting/Minimodule/SPAvatar.cs | 15 +- OpenSim/Services/Interfaces/IAvatarService.cs | 16 +- 6 files changed, 100 insertions(+), 111 deletions(-) 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) From 657cceb8847f94a9af0c8b2358124105d778486c Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Mon, 25 Oct 2010 09:41:08 -0700 Subject: [PATCH 02/12] Intermediate commit for backward compatability; does not compile yet --- OpenSim/Framework/AgentCircuitData.cs | 73 +++++++++++------------ OpenSim/Framework/ChildAgentDataUpdate.cs | 70 +++++++++++++--------- 2 files changed, 77 insertions(+), 66 deletions(-) diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs index be98380cfd..30a954837d 100644 --- a/OpenSim/Framework/AgentCircuitData.cs +++ b/OpenSim/Framework/AgentCircuitData.cs @@ -206,16 +206,18 @@ namespace OpenSim.Framework args["service_session_id"] = OSD.FromString(ServiceSessionID); args["start_pos"] = OSD.FromString(startpos.ToString()); - args["appearance_serial"] = OSD.FromInteger(Appearance.Serial); args["client_ip"] = OSD.FromString(IPAddress); args["viewer"] = OSD.FromString(Viewer); args["channel"] = OSD.FromString(Channel); args["mac"] = OSD.FromString(Mac); args["id0"] = OSD.FromString(Id0); -/* + // Eventually this code should be deprecated, use full appearance + // packing in packed_appearance if (Appearance != null) { + args["appearance_serial"] = OSD.FromInteger(Appearance.Serial); + //System.Console.WriteLine("XXX Before packing Wearables"); if ((Appearance.Wearables != null) && (Appearance.Wearables.Length > 0)) { @@ -230,20 +232,19 @@ namespace OpenSim.Framework } //System.Console.WriteLine("XXX Before packing Attachments"); - Dictionary attachments = Appearance.Attachments; + List attachments = Appearance.GetAttachments(); if ((attachments != null) && (attachments.Count > 0)) { OSDArray attachs = new OSDArray(attachments.Count); - foreach (KeyValuePair kvp in attachments) + foreach (AvatarAttachment attach in attachments) { - AvatarAttachment adata = new AvatarAttachment(kvp.Value); - attachs.Add(adata.Pack()); + attachs.Add(attach.Pack()); //System.Console.WriteLine("XXX att.pt=" + kvp.Key + "; itemID=" + kvp.Value[0] + "; assetID=" + kvp.Value[1]); } args["attachments"] = attachs; } } -*/ + if (Appearance != null) { OSDMap appmap = Appearance.Pack(); @@ -339,6 +340,34 @@ namespace OpenSim.Framework try { // Unpack various appearance elements Appearance = new AvatarAppearance(AgentID); + + // Eventually this code should be deprecated, use full appearance + // packing in packed_appearance + if (args["appearance_serial"] != null) + Appearance.Serial = args["appearance_serial"].AsInteger(); + + if ((args["wearables"] != null) && (args["wearables"]).Type == OSDType.Array) + { + OSDArray wears = (OSDArray)(args["wearables"]); + for (int i = 0; i < wears.Count / 2; i++) + { + Appearance.Wearables[i].ItemID = wears[i*2].AsUUID(); + Appearance.Wearables[i].AssetID = wears[(i*2)+1].AsUUID(); + } + } + + if ((args["attachments"] != null) && (args["attachments"]).Type == OSDType.Array) + { + OSDArray attachs = (OSDArray)(args["attachments"]); + foreach (OSD o in attachs) + { + if (o.Type == OSDType.Map) + { + Appearance.AppendAttachment(new AvatarAttachment((OSDMap)o)); + } + } + } + if (args["packed_appearance"] != null) { if (args["packed_appearance"].Type == OSDType.Map) @@ -358,36 +387,6 @@ namespace OpenSim.Framework m_log.ErrorFormat("[AGENTCIRCUITDATA] failed to unpack appearance; {0}",e.Message); } - -/* - if (args["appearance_serial"] != null) - Appearance.Serial = args["appearance_serial"].AsInteger(); - - if ((args["wearables"] != null) && (args["wearables"]).Type == OSDType.Array) - { - OSDArray wears = (OSDArray)(args["wearables"]); - for (int i = 0; i < wears.Count / 2; i++) - { - Appearance.Wearables[i].ItemID = wears[i*2].AsUUID(); - Appearance.Wearables[i].AssetID = wears[(i*2)+1].AsUUID(); - } - } - - if ((args["attachments"] != null) && (args["attachments"]).Type == OSDType.Array) - { - OSDArray attachs = (OSDArray)(args["attachments"]); - AvatarAttachment[] attachments = new AvatarAttachment[attachs.Count]; - int i = 0; - foreach (OSD o in attachs) - { - if (o.Type == OSDType.Map) - { - attachments[i++] = new AvatarAttachment((OSDMap)o); - } - } - Appearance.SetAttachments(attachments); - } -*/ ServiceURLs = new Dictionary(); if (args.ContainsKey("service_urls") && args["service_urls"] != null && (args["service_urls"]).Type == OSDType.Array) { diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index fdebba3d2e..d7a7d1e4af 100644 --- a/OpenSim/Framework/ChildAgentDataUpdate.cs +++ b/OpenSim/Framework/ChildAgentDataUpdate.cs @@ -387,31 +387,37 @@ namespace OpenSim.Framework // args["agent_textures"] = textures; //} -/* - if ((AgentTextures != null) && (AgentTextures.Length > 0)) - args["texture_entry"] = OSD.FromBinary(AgentTextures); + // The code to pack textures, visuals, wearables and attachments + // should be removed; packed appearance contains the full appearance + // This is retained for backward compatibility only + if ((Appearance.Texture != null) && (Appearance.Texture.Length > 0)) + args["texture_entry"] = OSD.FromBinary(Appearance.Texture); - if ((VisualParams != null) && (VisualParams.Length > 0)) - args["visual_params"] = OSD.FromBinary(VisualParams); + if ((Appearance.VisualParams != null) && (Appearance.VisualParams.Length > 0)) + args["visual_params"] = OSD.FromBinary(Appearance.VisualParams); // We might not pass this in all cases... - if ((Wearables != null) && (Wearables.Length > 0)) + if ((Appearance.Wearables != null) && (Appearance.Wearables.Length > 0)) { - OSDArray wears = new OSDArray(Wearables.Length); - foreach (UUID uuid in Wearables) - wears.Add(OSD.FromUUID(uuid)); + OSDArray wears = new OSDArray(Appearance.Wearables.Length * 2); + foreach (AvatarWearable awear in Appearance.Wearables) + { + wears.Add(OSD.FromUUID(awear.ItemID)); + wears.Add(OSD.FromUUID(awear.AssetID)); + } args["wearables"] = wears; } - - if ((Attachments != null) && (Attachments.Length > 0)) + List attachments = Appearance.GetAttachments(); + if ((attachments != null) && (attachments.Length > 0)) { - OSDArray attachs = new OSDArray(Attachments.Length); - foreach (AvatarAttachment att in Attachments) + OSDArray attachs = new OSDArray(attachments.Length); + foreach (AvatarAttachment att in attachments) attachs.Add(att.Pack()); args["attachments"] = attachs; } -*/ + // End of code to remove + if ((Controllers != null) && (Controllers.Length > 0)) { OSDArray controls = new OSDArray(Controllers.Length); @@ -547,41 +553,47 @@ namespace OpenSim.Framework // AgentTextures[i++] = o.AsUUID(); //} - if (args["packed_appearance"] != null) - Appearance = new AvatarAppearance(AgentID,(OSDMap)args["packed_appearance"]); - else - Appearance = new AvatarAppearance(AgentID); - -/* + + Appearance = new AvatarAppearance(AgentID); + + // The code to pack textures, visuals, wearables and attachments + // should be removed; packed appearance contains the full appearance + // This is retained for backward compatibility only if (args["texture_entry"] != null) - AgentTextures = args["texture_entry"].AsBinary(); + Appearance.SetTextureEntries(args["texture_entry"].AsBinary()); if (args["visual_params"] != null) - VisualParams = args["visual_params"].AsBinary(); + Appearance.SetVisualParams(args["visual_params"].AsBinary()); if ((args["wearables"] != null) && (args["wearables"]).Type == OSDType.Array) { OSDArray wears = (OSDArray)(args["wearables"]); - Wearables = new UUID[wears.Count]; - int i = 0; - foreach (OSD o in wears) - Wearables[i++] = o.AsUUID(); + for (int i = 0; i < wears.Count / 2; i++) + { + Appearance.Wearables[i].ItemID = wears[i*2].AsUUID(); + Appearance.Wearables[i].AssetID = wears[(i*2)+1].AsUUID(); + } } if ((args["attachments"] != null) && (args["attachments"]).Type == OSDType.Array) { OSDArray attachs = (OSDArray)(args["attachments"]); - Attachments = new AvatarAttachment[attachs.Count]; + AvatarAttachment[] attachments = new AvatarAttachment[attachs.Count]; int i = 0; foreach (OSD o in attachs) { if (o.Type == OSDType.Map) { - Attachments[i++] = new AvatarAttachment((OSDMap)o); + attachments[i++] = new AvatarAttachment((OSDMap)o); } } + Appearance.SetAttachments(attachments); } -*/ + // end of code to remove + + if (args["packed_appearance"] != null) + Appearance = new AvatarAppearance(AgentID,(OSDMap)args["packed_appearance"]); + if ((args["controllers"] != null) && (args["controllers"]).Type == OSDType.Array) { OSDArray controls = (OSDArray)(args["controllers"]); From 6e58c3d563b50c5797d1cfffbaec3fe82f18c2ea Mon Sep 17 00:00:00 2001 From: Master ScienceSim Date: Mon, 25 Oct 2010 14:11:47 -0700 Subject: [PATCH 03/12] Half of the compatibility is working. Login into a new region with old data works. Teleport out of a new region with old data works. Teleport into a new region with old data does not trigger the necessary rebake. --- OpenSim/Framework/AgentCircuitData.cs | 13 +++----- OpenSim/Framework/AvatarAppearance.cs | 2 +- OpenSim/Framework/ChildAgentDataUpdate.cs | 33 ++++++++++++------- .../AvatarFactory/AvatarFactoryModule.cs | 2 +- 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs index 30a954837d..098b33cd35 100644 --- a/OpenSim/Framework/AgentCircuitData.cs +++ b/OpenSim/Framework/AgentCircuitData.cs @@ -368,15 +368,12 @@ namespace OpenSim.Framework } } - if (args["packed_appearance"] != null) + if (args.ContainsKey("packed_appearance") && (args["packed_appearance"].Type == OSDType.Map)) { - if (args["packed_appearance"].Type == OSDType.Map) - { - Appearance.Unpack((OSDMap)args["packed_appearance"]); - m_log.WarnFormat("[AGENTCIRCUITDATA] unpacked appearance"); - } - else - m_log.WarnFormat("[AGENTCIRCUITDATA] packed_appearance is not a map:\n{0}",args["packed_appearance"].ToString()); + Appearance.Unpack((OSDMap)args["packed_appearance"]); +// DEBUG ON + m_log.WarnFormat("[AGENTCIRCUITDATA] unpacked appearance"); +// DEBUG OFF } // DEBUG ON else diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index ba0cad2dde..05330c7d78 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -389,7 +389,7 @@ namespace OpenSim.Framework changed = true; // DEBUG ON if (newface != null) - m_log.WarnFormat("[SCENEPRESENCE] index {0}, new texture id {1}",i,newface.TextureID); + m_log.WarnFormat("[AVATAR APPEARANCE] index {0}, new texture id {1}",i,newface.TextureID); // DEBUG OFF } diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index d7a7d1e4af..215682f462 100644 --- a/OpenSim/Framework/ChildAgentDataUpdate.cs +++ b/OpenSim/Framework/ChildAgentDataUpdate.cs @@ -390,8 +390,11 @@ namespace OpenSim.Framework // The code to pack textures, visuals, wearables and attachments // should be removed; packed appearance contains the full appearance // This is retained for backward compatibility only - if ((Appearance.Texture != null) && (Appearance.Texture.Length > 0)) - args["texture_entry"] = OSD.FromBinary(Appearance.Texture); + if (Appearance.Texture != null) + { + byte[] rawtextures = Appearance.Texture.GetBytes(); + args["texture_entry"] = OSD.FromBinary(rawtextures); + } if ((Appearance.VisualParams != null) && (Appearance.VisualParams.Length > 0)) args["visual_params"] = OSD.FromBinary(Appearance.VisualParams); @@ -408,10 +411,10 @@ namespace OpenSim.Framework args["wearables"] = wears; } - List attachments = Appearance.GetAttachments(); - if ((attachments != null) && (attachments.Length > 0)) + List attachments = Appearance.GetAttachments(); + if ((attachments != null) && (attachments.Count > 0)) { - OSDArray attachs = new OSDArray(attachments.Length); + OSDArray attachs = new OSDArray(attachments.Count); foreach (AvatarAttachment att in attachments) attachs.Add(att.Pack()); args["attachments"] = attachs; @@ -560,7 +563,11 @@ namespace OpenSim.Framework // should be removed; packed appearance contains the full appearance // This is retained for backward compatibility only if (args["texture_entry"] != null) - Appearance.SetTextureEntries(args["texture_entry"].AsBinary()); + { + byte[] rawtextures = args["texture_entry"].AsBinary(); + Primitive.TextureEntry textures = new Primitive.TextureEntry(rawtextures,0,rawtextures.Length); + Appearance.SetTextureEntries(textures); + } if (args["visual_params"] != null) Appearance.SetVisualParams(args["visual_params"].AsBinary()); @@ -578,21 +585,25 @@ namespace OpenSim.Framework if ((args["attachments"] != null) && (args["attachments"]).Type == OSDType.Array) { OSDArray attachs = (OSDArray)(args["attachments"]); - AvatarAttachment[] attachments = new AvatarAttachment[attachs.Count]; - int i = 0; foreach (OSD o in attachs) { if (o.Type == OSDType.Map) { - attachments[i++] = new AvatarAttachment((OSDMap)o); + // We know all of these must end up as attachments so we + // append rather than replace to ensure multiple attachments + // per point continues to work + Appearance.AppendAttachment(new AvatarAttachment((OSDMap)o)); } } - Appearance.SetAttachments(attachments); } // end of code to remove - if (args["packed_appearance"] != null) + if (args.ContainsKey("packed_appearance") && (args["packed_appearance"]).Type == OSDType.Map) Appearance = new AvatarAppearance(AgentID,(OSDMap)args["packed_appearance"]); +// DEBUG ON + else + System.Console.WriteLine("No packed appearance in AgentUpdate"); +// DEBUG OFF if ((args["controllers"] != null) && (args["controllers"]).Type == OSDType.Array) { diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 9f7ff7f5a0..b74cdc9461 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -136,7 +136,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory { if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) { - m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}",face.TextureID,j,this.Name); + m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}",face.TextureID,j,client.Name); client.SendRebakeAvatarTextures(face.TextureID); } } From 9132e251aa0d0d7395dc4868fd57799dd679cdb7 Mon Sep 17 00:00:00 2001 From: Master ScienceSim Date: Tue, 26 Oct 2010 12:53:15 -0700 Subject: [PATCH 04/12] Made the check for texture assets asynchronous. This is one part of a bigger clean up that needs to happen around locks on appearance. --- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index b74cdc9461..5444f809b3 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -84,6 +84,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // client.OnAvatarNowWearing -= AvatarIsWearing; } + public void CheckBakedTextureAssets(IClientAPI client, UUID textureID, int idx) + { + if (m_scene.AssetService.Get(textureID.ToString()) == null) + { + m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}",textureID,idx,client.Name); + client.SendRebakeAvatarTextures(textureID); + } + } + /// /// Set appearance data (textureentry and slider settings) received from the client /// @@ -133,13 +142,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory Primitive.TextureEntryFace face = textureEntry.FaceTextures[j]; if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) - { - if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) - { - m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}",face.TextureID,j,client.Name); - client.SendRebakeAvatarTextures(face.TextureID); - } - } + Util.FireAndForget(delegate(object o) { CheckBakedTextureAssets(client,face.TextureID,j); }); } changed = sp.Appearance.SetTextureEntries(textureEntry); From 9cfd3e1d5ac8383087fb09cf076e9ec199808fd7 Mon Sep 17 00:00:00 2001 From: Master ScienceSim Date: Tue, 26 Oct 2010 12:54:28 -0700 Subject: [PATCH 05/12] Small cleanup and add more debugging information --- OpenSim/Framework/AgentCircuitData.cs | 4 ++-- OpenSim/Framework/ChildAgentDataUpdate.cs | 27 ++++++++++++++++++----- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs index 098b33cd35..640a6462e7 100644 --- a/OpenSim/Framework/AgentCircuitData.cs +++ b/OpenSim/Framework/AgentCircuitData.cs @@ -351,8 +351,8 @@ namespace OpenSim.Framework OSDArray wears = (OSDArray)(args["wearables"]); for (int i = 0; i < wears.Count / 2; i++) { - Appearance.Wearables[i].ItemID = wears[i*2].AsUUID(); - Appearance.Wearables[i].AssetID = wears[(i*2)+1].AsUUID(); + AvatarWearable awear = new AvatarWearable(wears[i*2].AsUUID(),wears[(i*2)+1].AsUUID()); + Appearance.SetWearable(i,awear); } } diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index 215682f462..66487f72e0 100644 --- a/OpenSim/Framework/ChildAgentDataUpdate.cs +++ b/OpenSim/Framework/ChildAgentDataUpdate.cs @@ -28,6 +28,8 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Reflection; +using log4net; using OpenMetaverse; using OpenMetaverse.StructuredData; @@ -310,6 +312,12 @@ namespace OpenSim.Framework // Appearance public AvatarAppearance Appearance; +// DEBUG ON + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); +// DEBUG OFF + /* public byte[] AgentTextures; public byte[] VisualParams; @@ -323,6 +331,10 @@ namespace OpenSim.Framework public virtual OSDMap Pack() { +// DEBUG ON + m_log.WarnFormat("[CHILDAGENTDATAUPDATE] Pack data"); +// DEBUG OFF + OSDMap args = new OSDMap(); args["message_type"] = OSD.FromString("AgentData"); @@ -444,6 +456,10 @@ namespace OpenSim.Framework /// public virtual void Unpack(OSDMap args) { +// DEBUG ON + m_log.WarnFormat("[CHILDAGENTDATAUPDATE] Unpack data"); +// DEBUG OFF + if (args.ContainsKey("region_id")) UUID.TryParse(args["region_id"].AsString(), out RegionID); @@ -556,10 +572,9 @@ namespace OpenSim.Framework // AgentTextures[i++] = o.AsUUID(); //} - Appearance = new AvatarAppearance(AgentID); - // The code to pack textures, visuals, wearables and attachments + // The code to unpack textures, visuals, wearables and attachments // should be removed; packed appearance contains the full appearance // This is retained for backward compatibility only if (args["texture_entry"] != null) @@ -577,8 +592,8 @@ namespace OpenSim.Framework OSDArray wears = (OSDArray)(args["wearables"]); for (int i = 0; i < wears.Count / 2; i++) { - Appearance.Wearables[i].ItemID = wears[i*2].AsUUID(); - Appearance.Wearables[i].AssetID = wears[(i*2)+1].AsUUID(); + AvatarWearable awear = new AvatarWearable(wears[i*2].AsUUID(),wears[(i*2)+1].AsUUID()); + Appearance.SetWearable(i,awear); } } @@ -602,8 +617,8 @@ namespace OpenSim.Framework Appearance = new AvatarAppearance(AgentID,(OSDMap)args["packed_appearance"]); // DEBUG ON else - System.Console.WriteLine("No packed appearance in AgentUpdate"); -// DEBUG OFF + m_log.WarnFormat("[CHILDAGENTDATAUPDATE] No packed appearance"); +// DEBUG OFF if ((args["controllers"] != null) && (args["controllers"]).Type == OSDType.Array) { From 0f28fa400d1f853cc3c3ebd2707b08ed06d2f127 Mon Sep 17 00:00:00 2001 From: Master ScienceSim Date: Thu, 28 Oct 2010 09:00:39 -0700 Subject: [PATCH 06/12] Added background thread to handle delayed send and save of appearance to accommodate batching of the many updates that happen on login and teleport. Fixed handling of the serial property in appearance. --- OpenSim/Framework/AvatarAppearance.cs | 11 +- .../AvatarFactory/AvatarFactoryModule.cs | 231 +++++++++++++----- 2 files changed, 177 insertions(+), 65 deletions(-) diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index 05330c7d78..e66a1e7390 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -233,7 +233,7 @@ namespace OpenSim.Framework // DEBUG ON m_log.WarnFormat("[AVATAR APPEARANCE] create empty appearance for {0}",owner); // DEBUG OFF - m_serial = 0; + m_serial = 1; m_owner = owner; SetDefaultWearables(); @@ -289,7 +289,7 @@ namespace OpenSim.Framework // DEBUG OFF if (appearance == null) { - m_serial = 0; + m_serial = 1; m_owner = UUID.Zero; SetDefaultWearables(); @@ -467,6 +467,9 @@ namespace OpenSim.Framework public override String ToString() { String s = ""; + + s += String.Format("Serial: {0}\n",m_serial); + for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++) if (m_texture.FaceTextures[i] != null) s += String.Format("Texture: {0} --> {1}\n",i,m_texture.FaceTextures[i].TextureID); @@ -625,8 +628,8 @@ namespace OpenSim.Framework /// public void Unpack(OSDMap data) { - if ((data != null) && (data["appearance_serial"] != null)) - m_serial = data["appearance_serial"].AsInteger(); + if ((data != null) && (data["serial"] != null)) + m_serial = data["serial"].AsInteger(); if ((data != null) && (data["height"] != null)) m_avatarHeight = (float)data["height"].AsReal(); if ((data != null) && (data["hipoffset"] != null)) diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 5444f809b3..903e94b112 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -32,6 +32,10 @@ using Nini.Config; using OpenMetaverse; using OpenSim.Framework; +using System.Threading; +using System.Timers; +using System.Collections.Generic; + using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; @@ -44,7 +48,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; private Scene m_scene = null; - private bool m_startAnimationSet = false; + private static readonly int m_savetime = 5; // seconds to wait before saving changed appearance + private static readonly int m_sendtime = 2; // seconds to wait before sending changed appearance + + private static readonly int m_checkTime = 500; // milliseconds to wait between checks for appearance updates + private System.Timers.Timer m_updateTimer = new System.Timers.Timer(); + private Dictionary m_savequeue = new Dictionary(); + private Dictionary m_sendqueue = new Dictionary(); + + #region RegionModule Members public void Initialise(Scene scene, IConfigSource source) { @@ -56,6 +68,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory public void PostInitialise() { + m_updateTimer.Enabled = false; + m_updateTimer.AutoReset = true; + m_updateTimer.Interval = m_checkTime; // 500 milliseconds wait to start async ops + m_updateTimer.Elapsed += new ElapsedEventHandler(HandleAppearanceUpdateTimer); } public void Close() @@ -84,15 +100,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // client.OnAvatarNowWearing -= AvatarIsWearing; } - public void CheckBakedTextureAssets(IClientAPI client, UUID textureID, int idx) - { - if (m_scene.AssetService.Get(textureID.ToString()) == null) - { - m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}",textureID,idx,client.Name); - client.SendRebakeAvatarTextures(textureID); - } - } - + #endregion + /// /// Set appearance data (textureentry and slider settings) received from the client /// @@ -100,6 +109,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory /// public void SetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams) { +// DEBUG ON + m_log.WarnFormat("[AVFACTORY] SetAppearance for {0}",client.AgentId); +// DEBUG OFF + ScenePresence sp = m_scene.GetScenePresence(client.AgentId); if (sp == null) { @@ -107,79 +120,175 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory return; } -// DEBUG ON - m_log.WarnFormat("[AVFACTORY] SetAppearance for {0}",client.AgentId); -// DEBUG OFF - -/* - if (m_physicsActor != null) - { - if (!IsChildAgent) - { - // This may seem like it's redundant, remove the avatar from the physics scene - // just to add it back again, but it saves us from having to update - // 3 variables 10 times a second. - bool flyingTemp = m_physicsActor.Flying; - RemoveFromPhysicalScene(); - //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor); - - //PhysicsActor = null; - - AddToPhysicalScene(flyingTemp); - } - } -*/ - #region Bake Cache Check - bool changed = false; // Process the texture entry if (textureEntry != null) { + changed = sp.Appearance.SetTextureEntries(textureEntry); + for (int i = 0; i < BAKE_INDICES.Length; i++) { - int j = BAKE_INDICES[i]; - Primitive.TextureEntryFace face = textureEntry.FaceTextures[j]; - + int idx = BAKE_INDICES[i]; + Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) - Util.FireAndForget(delegate(object o) { CheckBakedTextureAssets(client,face.TextureID,j); }); + Util.FireAndForget(delegate(object o) { CheckBakedTextureAssets(client,face.TextureID,idx); }); } - changed = sp.Appearance.SetTextureEntries(textureEntry); - } - #endregion Bake Cache Check - - changed = sp.Appearance.SetVisualParams(visualParams) || changed; - - // If nothing changed (this happens frequently) just return - if (changed) + // Process the visual params, this may change height as well + if (visualParams != null) { -// DEBUG ON - m_log.Warn("[AVFACTORY] Appearance changed"); -// DEBUG OFF - sp.Appearance.SetAppearance(textureEntry, visualParams); - if (sp.Appearance.AvatarHeight > 0) - sp.SetHeight(sp.Appearance.AvatarHeight); - - m_scene.AvatarService.SetAppearance(client.AgentId, sp.Appearance); + if (sp.Appearance.SetVisualParams(visualParams)) + { + changed = true; + if (sp.Appearance.AvatarHeight > 0) + sp.SetHeight(sp.Appearance.AvatarHeight); + } } -// DEBUG ON - else - m_log.Warn("[AVFACTORY] Appearance did not change"); -// DEBUG OFF + + // If something changed in the appearance then queue an appearance save + if (changed) + QueueAppearanceSave(client.AgentId); + // And always queue up an appearance update to send out + QueueAppearanceSend(client.AgentId); + + // Send the appearance back to the avatar + AvatarAppearance avp = sp.Appearance; + sp.ControllingClient.SendAvatarDataImmediate(sp); + sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes()); + } + + /// + /// Checks for the existance of a baked texture asset and + /// requests the viewer rebake if the asset is not found + /// + /// + /// + /// + private void CheckBakedTextureAssets(IClientAPI client, UUID textureID, int idx) + { + if (m_scene.AssetService.Get(textureID.ToString()) == null) + { + m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}", + textureID,idx,client.Name); + client.SendRebakeAvatarTextures(textureID); + } + } + + #region UpdateAppearanceTimer + + public void QueueAppearanceSend(UUID agentid) + { +// DEBUG ON + m_log.WarnFormat("[AVFACTORY] Queue appearance send for {0}",agentid); +// DEBUG OFF + + // 100 nanoseconds (ticks) we should wait + long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 10000000); + lock (m_sendqueue) + { + m_sendqueue[agentid] = timestamp; + m_updateTimer.Start(); + } + } + + public void QueueAppearanceSave(UUID agentid) + { +// DEBUG ON + m_log.WarnFormat("[AVFACTORY] Queue appearance save for {0}",agentid); +// DEBUG OFF + + // 100 nanoseconds (ticks) we should wait + long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 10000000); + lock (m_savequeue) + { + m_savequeue[agentid] = timestamp; + m_updateTimer.Start(); + } + } + + private void HandleAppearanceSend(UUID agentid) + { + ScenePresence sp = m_scene.GetScenePresence(agentid); + if (sp == null) + { + m_log.WarnFormat("[AVFACTORY] Agent {0} no longer in the scene",agentid); + return; + } + +// DEBUG ON + m_log.WarnFormat("[AVFACTORY] Handle appearance send for {0}\n{1}",agentid,sp.Appearance.ToString()); +// DEBUG OFF + + // Send the appearance to everyone in the scene sp.SendAppearanceToAllOtherAgents(); + + // Send the appearance back to the avatar + AvatarAppearance avp = sp.Appearance; + sp.ControllingClient.SendAvatarDataImmediate(sp); + sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes()); + +/* +// this needs to be fixed, the flag should be on scene presence not the region module + // Start the animations if necessary if (!m_startAnimationSet) { sp.Animator.UpdateMovementAnimations(); m_startAnimationSet = true; } - - client.SendAvatarDataImmediate(sp); - client.SendAppearance(sp.Appearance.Owner,sp.Appearance.VisualParams,sp.Appearance.Texture.GetBytes()); +*/ } + private void HandleAppearanceSave(UUID agentid) + { + ScenePresence sp = m_scene.GetScenePresence(agentid); + if (sp == null) + { + m_log.WarnFormat("[AVFACTORY] Agent {0} no longer in the scene",agentid); + return; + } + + m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); + } + + private void HandleAppearanceUpdateTimer(object sender, EventArgs ea) + { + long now = DateTime.Now.Ticks; + + lock (m_sendqueue) + { + Dictionary sends = new Dictionary(m_sendqueue); + foreach (KeyValuePair kvp in sends) + { + if (kvp.Value < now) + { + Util.FireAndForget(delegate(object o) { HandleAppearanceSend(kvp.Key); }); + m_sendqueue.Remove(kvp.Key); + } + } + } + + lock (m_savequeue) + { + Dictionary saves = new Dictionary(m_savequeue); + foreach (KeyValuePair kvp in saves) + { + if (kvp.Value < now) + { + Util.FireAndForget(delegate(object o) { HandleAppearanceSave(kvp.Key); }); + m_savequeue.Remove(kvp.Key); + } + } + } + + if (m_savequeue.Count == 0 && m_sendqueue.Count == 0) + m_updateTimer.Stop(); + } + + #endregion + /// /// Tell the client for this scene presence what items it should be wearing now /// From 68666efd25f4d094949f31eae08ee17fd821b7e4 Mon Sep 17 00:00:00 2001 From: Master ScienceSim Date: Thu, 28 Oct 2010 12:00:04 -0700 Subject: [PATCH 07/12] Configuration of persistent baked textures and save/send delays. --- OpenSim/Framework/Capabilities/Caps.cs | 14 +++++++++++++- .../AvatarFactory/AvatarFactoryModule.cs | 18 ++++++++++++++---- bin/OpenSimDefaults.ini | 14 ++++++++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/OpenSim/Framework/Capabilities/Caps.cs b/OpenSim/Framework/Capabilities/Caps.cs index 6b64e120db..872de9a082 100644 --- a/OpenSim/Framework/Capabilities/Caps.cs +++ b/OpenSim/Framework/Capabilities/Caps.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using System.IO; using System.Reflection; using log4net; +using Nini.Config; using OpenMetaverse; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; @@ -112,6 +113,8 @@ namespace OpenSim.Framework.Capabilities private string m_regionName; private object m_fetchLock = new Object(); + private bool m_persistBakedTextures = false; + public bool SSLCaps { get { return m_httpListener.UseSSL; } @@ -145,6 +148,15 @@ namespace OpenSim.Framework.Capabilities m_httpListenPort = httpPort; + m_persistBakedTextures = false; + IConfigSource config = m_Scene.Config; + if (config != null) + { + IConfig sconfig = config.Configs["Startup"]; + if (sconfig != null) + m_persistBakedTextures = sconfig.GetBoolean("PersistBakedTextures",m_persistBakedTextures); + } + if (httpServer != null && httpServer.UseSSL) { m_httpListenPort = httpServer.SSLPort; @@ -983,7 +995,7 @@ namespace OpenSim.Framework.Capabilities asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_agentID.ToString()); asset.Data = data; asset.Temporary = true; - asset.Local = true; + asset.Local = ! m_persistBakedTextures; // Local assets aren't persisted, non-local are m_assetCache.Store(asset); } diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 903e94b112..5f8b4f6b0c 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -48,20 +48,30 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; private Scene m_scene = null; - private static readonly int m_savetime = 5; // seconds to wait before saving changed appearance - private static readonly int m_sendtime = 2; // seconds to wait before sending changed appearance + private int m_savetime = 5; // seconds to wait before saving changed appearance + private int m_sendtime = 2; // seconds to wait before sending changed appearance - private static readonly int m_checkTime = 500; // milliseconds to wait between checks for appearance updates + private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates private System.Timers.Timer m_updateTimer = new System.Timers.Timer(); private Dictionary m_savequeue = new Dictionary(); private Dictionary m_sendqueue = new Dictionary(); #region RegionModule Members - public void Initialise(Scene scene, IConfigSource source) + public void Initialise(Scene scene, IConfigSource config) { scene.EventManager.OnNewClient += NewClient; + if (config != null) + { + IConfig sconfig = config.Configs["Startup"]; + if (sconfig != null) + { + m_savetime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime))); + m_sendtime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime))); + } + } + if (m_scene == null) m_scene = scene; } diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 82267edcc9..5ced7d586a 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -255,6 +255,20 @@ ; OpenJPEG if false ; UseCSJ2K = true + ; Persist avatar baked textures + ; Persisting baked textures can speed up login and region border + ; crossings especially with large numbers of users, though it + ; will store potentially large numbers of textures in your asset + ; database + PersistBakedTextures = false + + ; Control the delay before appearance is sent to other avatars and + ; saved in the avatar service. Attempts to limit the impact caused + ; by the very chatty dialog that sets appearance when an avatar + ; logs in or teleports into a region; values are in seconds + DelayBeforeAppearanceSave = 5 + DelayBeforeAppearanceSend = 2 + [SMTP] enabled=false From 5f4badf9e2cd96f4a4a48b0019bd5f39298213ab Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 29 Oct 2010 20:48:37 +0200 Subject: [PATCH 08/12] Add my work on top of cmickeyb's --- OpenSim/Framework/AvatarAppearance.cs | 100 +++++++++++++++++- .../TexturesAssetSet/TexturesAssetSet.xml | 6 ++ .../BodyPartsLibraryItems.xml | 28 +++++ 3 files changed, 133 insertions(+), 1 deletion(-) diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index 55646dda91..4738d881ed 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -35,6 +35,104 @@ using log4net; namespace OpenSim.Framework { + // A special dictionary for avatar appearance + public struct LayerItem + { + public UUID ItemID; + public UUID AssetID; + + public LayerItem(UUID itemID, UUID assetID) + { + ItemID = itemID; + AssetID = assetID; + } + } + + public class Layer + { + protected int m_layerType; + protected Dictionary m_items = new Dictionary(); + protected List m_ids = new List(); + + public Layer(int type) + { + m_layerType = type; + } + + public int LayerType + { + get { return m_layerType; } + } + + public int Count + { + get { return m_ids.Count; } + } + + public void Add(UUID itemID, UUID assetID) + { + if (m_items.ContainsKey(itemID)) + return; + if (m_ids.Count >= 5) + return; + + m_ids.Add(itemID); + m_items[itemID] = assetID; + } + + public void Wear(UUID itemID, UUID assetID) + { + Clear(); + Add(itemID, assetID); + } + + public void Clear() + { + m_ids.Clear(); + m_items.Clear(); + } + + public void RemoveItem(UUID itemID) + { + if (m_items.ContainsKey(itemID)) + { + m_ids.Remove(itemID); + m_items.Remove(itemID); + } + } + + public void RemoveAsset(UUID assetID) + { + UUID itemID = UUID.Zero; + + foreach (KeyValuePair kvp in m_items) + { + if (kvp.Value == assetID) + { + itemID = kvp.Key; + break; + } + } + + if (itemID != UUID.Zero) + { + m_ids.Remove(itemID); + m_items.Remove(itemID); + } + } + + public LayerItem this [int idx] + { + get + { + if (idx >= m_ids.Count || idx < 0) + return new LayerItem(UUID.Zero, UUID.Zero); + + return new LayerItem(m_ids[idx], m_items[m_ids[idx]]); + } + } + } + /// /// Contains the Avatar's Appearance and methods to manipulate the appearance. /// @@ -1456,4 +1554,4 @@ namespace OpenSim.Framework SKIRT_SKIRT_BLUE = 217 } } -} \ No newline at end of file +} diff --git a/bin/assets/TexturesAssetSet/TexturesAssetSet.xml b/bin/assets/TexturesAssetSet/TexturesAssetSet.xml index c5cafa741e..7c74a48823 100644 --- a/bin/assets/TexturesAssetSet/TexturesAssetSet.xml +++ b/bin/assets/TexturesAssetSet/TexturesAssetSet.xml @@ -1,4 +1,10 @@ +
+ + + + +
diff --git a/bin/inventory/BodyPartsLibrary/BodyPartsLibraryItems.xml b/bin/inventory/BodyPartsLibrary/BodyPartsLibraryItems.xml index aa8d9d964b..5cb71c0bbe 100644 --- a/bin/inventory/BodyPartsLibrary/BodyPartsLibraryItems.xml +++ b/bin/inventory/BodyPartsLibrary/BodyPartsLibraryItems.xml @@ -16,6 +16,34 @@
-->