diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index aeed467cab..1829c8d47e 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -1472,12 +1472,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController { m_log.DebugFormat("[RADMIN] Initializing inventory for {0} from {1}", destination, source); Scene scene = m_application.SceneManager.CurrentOrFirstScene; - AvatarAppearance avatarAppearance = null; - AvatarData avatar = scene.AvatarService.GetAvatar(source); - if (avatar != null) - avatarAppearance = avatar.ToAvatarAppearance(source); // If the model has no associated appearance we're done. + AvatarAppearance avatarAppearance = scene.AvatarService.GetAppearance(source); if (avatarAppearance == null) return; @@ -1491,8 +1488,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController { CopyWearablesAndAttachments(destination, source, avatarAppearance); - AvatarData avatarData = new AvatarData(avatarAppearance); - scene.AvatarService.SetAvatar(destination, avatarData); + scene.AvatarService.SetAppearance(destination, avatarAppearance); } catch (Exception e) { @@ -1523,8 +1519,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } } - AvatarData avatarData = new AvatarData(avatarAppearance); - scene.AvatarService.SetAvatar(destination, avatarData); + scene.AvatarService.SetAppearance(destination, avatarAppearance); } catch (Exception e) { @@ -1619,12 +1614,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController } // Attachments - Dictionary attachments = avatarAppearance.GetAttachmentDictionary(); + List attachments = avatarAppearance.GetAttachments(); - foreach (KeyValuePair attachment in attachments) + foreach (AvatarAttachment attachment in attachments) { - int attachpoint = attachment.Key; - UUID itemID = attachment.Value[0]; + int attachpoint = attachment.AttachPoint; + UUID itemID = attachment.ItemID; if (itemID != UUID.Zero) { @@ -1908,10 +1903,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController if (include) { // Setup for appearance processing - AvatarData avatarData = scene.AvatarService.GetAvatar(ID); - if (avatarData != null) - avatarAppearance = avatarData.ToAvatarAppearance(ID); - else + avatarAppearance = scene.AvatarService.GetAppearance(ID); + if (avatarAppearance == null) avatarAppearance = new AvatarAppearance(); AvatarWearable[] wearables = avatarAppearance.Wearables; @@ -2076,8 +2069,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController m_log.DebugFormat("[RADMIN] Outfit {0} load completed", outfitName); } // foreach outfit m_log.DebugFormat("[RADMIN] Inventory update complete for {0}", name); - AvatarData avatarData2 = new AvatarData(avatarAppearance); - scene.AvatarService.SetAvatar(ID, avatarData2); + scene.AvatarService.SetAppearance(ID, avatarAppearance); } catch (Exception e) { 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/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs index af9478e5e0..19331c68bf 100644 --- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs +++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs @@ -596,7 +596,7 @@ namespace OpenSim.Client.MXP.ClientStack public event TeleportLandmarkRequest OnTeleportLandmarkRequest; public event DeRezObject OnDeRezObject; public event Action OnRegionHandShakeReply; - public event GenericCall2 OnRequestWearables; + public event GenericCall1 OnRequestWearables; public event GenericCall1 OnCompleteMovementToRegion; public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate; @@ -861,7 +861,7 @@ namespace OpenSim.Client.MXP.ClientStack OpenSim.Region.Framework.Scenes.Scene scene=(OpenSim.Region.Framework.Scenes.Scene)Scene; AvatarAppearance appearance; scene.GetAvatarAppearance(this,out appearance); - OnSetAppearance(appearance.Texture, (byte[])appearance.VisualParams.Clone()); + OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone()); } public void Stop() diff --git a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs index 7056e0110b..dcecb8b384 100644 --- a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs +++ b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs @@ -533,9 +533,7 @@ namespace OpenSim.Client.MXP.PacketHandler agent.InventoryFolder = UUID.Zero; agent.startpos = new Vector3(0, 0, 0); // TODO Fill in region start position agent.CapsPath = "http://localhost/"; - AvatarData avatar = scene.AvatarService.GetAvatar(account.PrincipalID); - if (avatar != null) - agent.Appearance = avatar.ToAvatarAppearance(account.PrincipalID); //userService.GetUserAppearance(userProfile.ID); + agent.Appearance = scene.AvatarService.GetAppearance(account.PrincipalID); if (agent.Appearance == null) { diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index 99a46dc884..0d2323251d 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs @@ -245,7 +245,7 @@ namespace OpenSim.Client.VWoHTTP.ClientStack public event TeleportLandmarkRequest OnTeleportLandmarkRequest = delegate { }; public event DeRezObject OnDeRezObject = delegate { }; public event Action OnRegionHandShakeReply = delegate { }; - public event GenericCall2 OnRequestWearables = delegate { }; + public event GenericCall1 OnRequestWearables = delegate { }; public event GenericCall1 OnCompleteMovementToRegion = delegate { }; public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate = delegate { }; diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs index 4f89d78c0e..640a6462e7 100644 --- a/OpenSim/Framework/AgentCircuitData.cs +++ b/OpenSim/Framework/AgentCircuitData.cs @@ -26,7 +26,9 @@ */ using System; +using System.Reflection; using System.Collections.Generic; +using log4net; using OpenMetaverse; using OpenMetaverse.StructuredData; @@ -38,6 +40,12 @@ namespace OpenSim.Framework /// public class AgentCircuitData { +// DEBUG ON + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); +// DEBUG OFF + /// /// Avatar Unique Agent Identifier /// @@ -198,15 +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)) { @@ -221,20 +232,25 @@ namespace OpenSim.Framework } //System.Console.WriteLine("XXX Before packing Attachments"); - Dictionary attachments = Appearance.GetAttachmentDictionary(); + 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) { - AttachmentData adata = new AttachmentData(kvp.Key, kvp.Value[0], kvp.Value[1]); - attachs.Add(adata.PackUpdateMessage()); + 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(); + args["packed_appearance"] = appmap; + } + if (ServiceURLs != null && ServiceURLs.Count > 0) { OSDArray urls = new OSDArray(ServiceURLs.Count * 2); @@ -317,34 +333,57 @@ namespace OpenSim.Framework if (args["start_pos"] != null) Vector3.TryParse(args["start_pos"].AsString(), out startpos); +// DEBUG ON + m_log.WarnFormat("[AGENTCIRCUITDATA] agentid={0}, child={1}, startpos={2}",AgentID,child,startpos.ToString()); +// DEBUG OFF + + 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(); + AvatarWearable awear = new AvatarWearable(wears[i*2].AsUUID(),wears[(i*2)+1].AsUUID()); + Appearance.SetWearable(i,awear); } - } + } if ((args["attachments"] != null) && (args["attachments"]).Type == OSDType.Array) { OSDArray attachs = (OSDArray)(args["attachments"]); - AttachmentData[] attachments = new AttachmentData[attachs.Count]; - int i = 0; foreach (OSD o in attachs) { if (o.Type == OSDType.Map) { - attachments[i++] = new AttachmentData((OSDMap)o); + Appearance.AppendAttachment(new AvatarAttachment((OSDMap)o)); } } - Appearance.SetAttachments(attachments); } + if (args.ContainsKey("packed_appearance") && (args["packed_appearance"].Type == OSDType.Map)) + { + Appearance.Unpack((OSDMap)args["packed_appearance"]); +// DEBUG ON + m_log.WarnFormat("[AGENTCIRCUITDATA] unpacked appearance"); +// DEBUG OFF + } +// DEBUG ON + else + m_log.Warn("[AGENTCIRCUITDATA] failed to find a valid packed_appearance"); +// DEBUG OFF + } catch (Exception e) + { + m_log.ErrorFormat("[AGENTCIRCUITDATA] failed to unpack appearance; {0}",e.Message); + } + ServiceURLs = new Dictionary(); if (args.ContainsKey("service_urls") && args["service_urls"] != null && (args["service_urls"]).Type == OSDType.Array) { diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index 5da8ba1368..e66a1e7390 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -26,9 +26,12 @@ */ using System; +using System.Reflection; using System.Collections; using System.Collections.Generic; using OpenMetaverse; +using OpenMetaverse.StructuredData; +using log4net; namespace OpenSim.Framework { @@ -37,48 +40,26 @@ namespace OpenSim.Framework /// public class AvatarAppearance { - //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - // these are guessed at by the list here - - // http://wiki.secondlife.com/wiki/Avatar_Appearance. We'll - // correct them over time for when were are wrong. - public readonly static int BODY = 0; - public readonly static int SKIN = 1; - public readonly static int HAIR = 2; - public readonly static int EYES = 3; - public readonly static int SHIRT = 4; - public readonly static int PANTS = 5; - public readonly static int SHOES = 6; - public readonly static int SOCKS = 7; - public readonly static int JACKET = 8; - public readonly static int GLOVES = 9; - public readonly static int UNDERSHIRT = 10; - public readonly static int UNDERPANTS = 11; - public readonly static int SKIRT = 12; - - private readonly static int MAX_WEARABLES = 13; - - private static UUID BODY_ASSET = new UUID("66c41e39-38f9-f75a-024e-585989bfab73"); - private static UUID BODY_ITEM = new UUID("66c41e39-38f9-f75a-024e-585989bfaba9"); - private static UUID SKIN_ASSET = new UUID("77c41e39-38f9-f75a-024e-585989bbabbb"); - private static UUID SKIN_ITEM = new UUID("77c41e39-38f9-f75a-024e-585989bfabc9"); - private static UUID SHIRT_ASSET = new UUID("00000000-38f9-1111-024e-222222111110"); - private static UUID SHIRT_ITEM = new UUID("77c41e39-38f9-f75a-0000-585989bf0000"); - private static UUID PANTS_ASSET = new UUID("00000000-38f9-1111-024e-222222111120"); - private static UUID PANTS_ITEM = new UUID("77c41e39-38f9-f75a-0000-5859892f1111"); - private static UUID HAIR_ASSET = new UUID("d342e6c0-b9d2-11dc-95ff-0800200c9a66"); - private static UUID HAIR_ITEM = new UUID("d342e6c1-b9d2-11dc-95ff-0800200c9a66"); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public readonly static int VISUALPARAM_COUNT = 218; + public readonly static int TEXTURE_COUNT = 21; + protected UUID m_owner; + protected int m_serial = 1; + protected byte[] m_visualparams; + protected Primitive.TextureEntry m_texture; + protected AvatarWearable[] m_wearables; + protected Dictionary> m_attachments; + protected float m_avatarHeight = 0; + protected float m_hipOffset = 0; public virtual UUID Owner { get { return m_owner; } set { m_owner = value; } } - protected int m_serial = 1; public virtual int Serial { @@ -86,15 +67,17 @@ namespace OpenSim.Framework set { m_serial = value; } } - protected byte[] m_visualparams; - public virtual byte[] VisualParams { get { return m_visualparams; } set { m_visualparams = value; } } - protected AvatarWearable[] m_wearables; + public virtual Primitive.TextureEntry Texture + { + get { return m_texture; } + set { m_texture = value; } + } public virtual AvatarWearable[] Wearables { @@ -103,178 +86,135 @@ namespace OpenSim.Framework } public virtual UUID BodyItem { - get { return m_wearables[BODY].ItemID; } - set { m_wearables[BODY].ItemID = value; } + get { return m_wearables[AvatarWearable.BODY].ItemID; } + set { m_wearables[AvatarWearable.BODY].ItemID = value; } } public virtual UUID BodyAsset { - get { return m_wearables[BODY].AssetID; } - set { m_wearables[BODY].AssetID = value; } + get { return m_wearables[AvatarWearable.BODY].AssetID; } + set { m_wearables[AvatarWearable.BODY].AssetID = value; } } public virtual UUID SkinItem { - get { return m_wearables[SKIN].ItemID; } - set { m_wearables[SKIN].ItemID = value; } + get { return m_wearables[AvatarWearable.SKIN].ItemID; } + set { m_wearables[AvatarWearable.SKIN].ItemID = value; } } public virtual UUID SkinAsset { - get { return m_wearables[SKIN].AssetID; } - set { m_wearables[SKIN].AssetID = value; } + get { return m_wearables[AvatarWearable.SKIN].AssetID; } + set { m_wearables[AvatarWearable.SKIN].AssetID = value; } } public virtual UUID HairItem { - get { return m_wearables[HAIR].ItemID; } - set { m_wearables[HAIR].ItemID = value; } + get { return m_wearables[AvatarWearable.HAIR].ItemID; } + set { m_wearables[AvatarWearable.HAIR].ItemID = value; } } public virtual UUID HairAsset { - get { return m_wearables[HAIR].AssetID; } - set { m_wearables[HAIR].AssetID = value; } + get { return m_wearables[AvatarWearable.HAIR].AssetID; } + set { m_wearables[AvatarWearable.HAIR].AssetID = value; } } public virtual UUID EyesItem { - get { return m_wearables[EYES].ItemID; } - set { m_wearables[EYES].ItemID = value; } + get { return m_wearables[AvatarWearable.EYES].ItemID; } + set { m_wearables[AvatarWearable.EYES].ItemID = value; } } public virtual UUID EyesAsset { - get { return m_wearables[EYES].AssetID; } - set { m_wearables[EYES].AssetID = value; } + get { return m_wearables[AvatarWearable.EYES].AssetID; } + set { m_wearables[AvatarWearable.EYES].AssetID = value; } } public virtual UUID ShirtItem { - get { return m_wearables[SHIRT].ItemID; } - set { m_wearables[SHIRT].ItemID = value; } + get { return m_wearables[AvatarWearable.SHIRT].ItemID; } + set { m_wearables[AvatarWearable.SHIRT].ItemID = value; } } public virtual UUID ShirtAsset { - get { return m_wearables[SHIRT].AssetID; } - set { m_wearables[SHIRT].AssetID = value; } + get { return m_wearables[AvatarWearable.SHIRT].AssetID; } + set { m_wearables[AvatarWearable.SHIRT].AssetID = value; } } public virtual UUID PantsItem { - get { return m_wearables[PANTS].ItemID; } - set { m_wearables[PANTS].ItemID = value; } + get { return m_wearables[AvatarWearable.PANTS].ItemID; } + set { m_wearables[AvatarWearable.PANTS].ItemID = value; } } public virtual UUID PantsAsset { - get { return m_wearables[PANTS].AssetID; } - set { m_wearables[PANTS].AssetID = value; } + get { return m_wearables[AvatarWearable.PANTS].AssetID; } + set { m_wearables[AvatarWearable.PANTS].AssetID = value; } } public virtual UUID ShoesItem { - get { return m_wearables[SHOES].ItemID; } - set { m_wearables[SHOES].ItemID = value; } + get { return m_wearables[AvatarWearable.SHOES].ItemID; } + set { m_wearables[AvatarWearable.SHOES].ItemID = value; } } public virtual UUID ShoesAsset { - get { return m_wearables[SHOES].AssetID; } - set { m_wearables[SHOES].AssetID = value; } + get { return m_wearables[AvatarWearable.SHOES].AssetID; } + set { m_wearables[AvatarWearable.SHOES].AssetID = value; } } public virtual UUID SocksItem { - get { return m_wearables[SOCKS].ItemID; } - set { m_wearables[SOCKS].ItemID = value; } + get { return m_wearables[AvatarWearable.SOCKS].ItemID; } + set { m_wearables[AvatarWearable.SOCKS].ItemID = value; } } public virtual UUID SocksAsset { - get { return m_wearables[SOCKS].AssetID; } - set { m_wearables[SOCKS].AssetID = value; } + get { return m_wearables[AvatarWearable.SOCKS].AssetID; } + set { m_wearables[AvatarWearable.SOCKS].AssetID = value; } } public virtual UUID JacketItem { - get { return m_wearables[JACKET].ItemID; } - set { m_wearables[JACKET].ItemID = value; } + get { return m_wearables[AvatarWearable.JACKET].ItemID; } + set { m_wearables[AvatarWearable.JACKET].ItemID = value; } } public virtual UUID JacketAsset { - get { return m_wearables[JACKET].AssetID; } - set { m_wearables[JACKET].AssetID = value; } + get { return m_wearables[AvatarWearable.JACKET].AssetID; } + set { m_wearables[AvatarWearable.JACKET].AssetID = value; } } public virtual UUID GlovesItem { - get { return m_wearables[GLOVES].ItemID; } - set { m_wearables[GLOVES].ItemID = value; } + get { return m_wearables[AvatarWearable.GLOVES].ItemID; } + set { m_wearables[AvatarWearable.GLOVES].ItemID = value; } } public virtual UUID GlovesAsset { - get { return m_wearables[GLOVES].AssetID; } - set { m_wearables[GLOVES].AssetID = value; } + get { return m_wearables[AvatarWearable.GLOVES].AssetID; } + set { m_wearables[AvatarWearable.GLOVES].AssetID = value; } } public virtual UUID UnderShirtItem { - get { return m_wearables[UNDERSHIRT].ItemID; } - set { m_wearables[UNDERSHIRT].ItemID = value; } + get { return m_wearables[AvatarWearable.UNDERSHIRT].ItemID; } + set { m_wearables[AvatarWearable.UNDERSHIRT].ItemID = value; } } public virtual UUID UnderShirtAsset { - get { return m_wearables[UNDERSHIRT].AssetID; } - set { m_wearables[UNDERSHIRT].AssetID = value; } + get { return m_wearables[AvatarWearable.UNDERSHIRT].AssetID; } + set { m_wearables[AvatarWearable.UNDERSHIRT].AssetID = value; } } public virtual UUID UnderPantsItem { - get { return m_wearables[UNDERPANTS].ItemID; } - set { m_wearables[UNDERPANTS].ItemID = value; } + get { return m_wearables[AvatarWearable.UNDERPANTS].ItemID; } + set { m_wearables[AvatarWearable.UNDERPANTS].ItemID = value; } } public virtual UUID UnderPantsAsset { - get { return m_wearables[UNDERPANTS].AssetID; } - set { m_wearables[UNDERPANTS].AssetID = value; } + get { return m_wearables[AvatarWearable.UNDERPANTS].AssetID; } + set { m_wearables[AvatarWearable.UNDERPANTS].AssetID = value; } } public virtual UUID SkirtItem { - get { return m_wearables[SKIRT].ItemID; } - set { m_wearables[SKIRT].ItemID = value; } + get { return m_wearables[AvatarWearable.SKIRT].ItemID; } + set { m_wearables[AvatarWearable.SKIRT].ItemID = value; } } public virtual UUID SkirtAsset { - get { return m_wearables[SKIRT].AssetID; } - set { m_wearables[SKIRT].AssetID = value; } + get { return m_wearables[AvatarWearable.SKIRT].AssetID; } + set { m_wearables[AvatarWearable.SKIRT].AssetID = value; } } - public virtual void SetDefaultWearables() - { - m_wearables[BODY].AssetID = BODY_ASSET; - m_wearables[BODY].ItemID = BODY_ITEM; - m_wearables[SKIN].AssetID = SKIN_ASSET; - m_wearables[SKIN].ItemID = SKIN_ITEM; - m_wearables[HAIR].AssetID = HAIR_ASSET; - m_wearables[HAIR].ItemID = HAIR_ITEM; - m_wearables[SHIRT].AssetID = SHIRT_ASSET; - m_wearables[SHIRT].ItemID = SHIRT_ITEM; - m_wearables[PANTS].AssetID = PANTS_ASSET; - m_wearables[PANTS].ItemID = PANTS_ITEM; - } - - public virtual void ClearWearables() - { - for (int i = 0; i < 13; i++) - { - m_wearables[i].AssetID = UUID.Zero; - m_wearables[i].ItemID = UUID.Zero; - } - } - - public virtual void SetDefaultParams(byte[] vparams) - { - // TODO: Figure out better values then 'fat scientist 150' or 'alien 0' - for (int i = 0; i < VISUALPARAM_COUNT; i++) - { - vparams[i] = 150; - } - } - - protected Primitive.TextureEntry m_texture; - - public virtual Primitive.TextureEntry Texture - { - get { return m_texture; } - set { m_texture = value; } - } - - protected float m_avatarHeight = 0; - protected float m_hipOffset = 0; - public virtual float AvatarHeight { get { return m_avatarHeight; } @@ -286,103 +226,218 @@ namespace OpenSim.Framework get { return m_hipOffset; } } - //Builds the VisualParam Enum using LIBOMV's Visual Param NameValues - /* - public void BuildVisualParamEnum() - { - Dictionary IndexedParams = new Dictionary(); - int vpIndex = 0; - IndexedParams = new Dictionary(); - - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - - sb.Append("public enum VPElement: int\n"); - sb.Append("{\n"); - foreach (KeyValuePair kvp in OpenMetaverse.VisualParams.Params) - { - VisualParam vp = kvp.Value; - - // Only Group-0 parameters are sent in AgentSetAppearance packets - if (kvp.Value.Group == 0) - { - - if (!IndexedParams.ContainsKey(vp.Name)) - { - - if (vp.Label.Length > 0 || vp.LabelMin.Length > 0 || vp.LabelMax.Length > 0) - { - - sb.Append("/// \n"); - if (vp.LabelMin.Length > 0 && vp.LabelMax.Length > 0) - sb.Append(string.Format("/// {0} - {1} 0--+255 {2}\n", vp.Label, vp.LabelMin, - vp.LabelMax)); - - else - sb.Append(string.Format("/// {0}\n", vp.Label)); - - sb.Append("/// \n"); - } - sb.Append(string.Format(" {0}_{1} = {2}", vp.Wearable.ToUpper(), vp.Name.ToUpper().Replace(" ", "_"),vpIndex)); - - IndexedParams.Add(vp.Name, vpIndex++); - } - else - { - sb.Append(string.Format(" {0}_{1}_{2} = {2}", vp.Wearable.ToUpper(), vp.Name.ToUpper().Replace(" ", "_"), vpIndex)); - vpIndex++; - //int i = 0; - } - } - if (vpIndex < 217) - sb.Append(",\n"); - else - sb.Append("\n"); - - } - sb.Append("}\n"); - - } - */ - public AvatarAppearance() : this(UUID.Zero) {} public AvatarAppearance(UUID owner) { - m_wearables = new AvatarWearable[MAX_WEARABLES]; - for (int i = 0; i < MAX_WEARABLES; i++) - { - // this makes them all null - m_wearables[i] = new AvatarWearable(); - } - m_serial = 0; +// DEBUG ON + m_log.WarnFormat("[AVATAR APPEARANCE] create empty appearance for {0}",owner); +// DEBUG OFF + m_serial = 1; m_owner = owner; - //BuildVisualParamEnum() - m_visualparams = new byte[VISUALPARAM_COUNT]; - // This sets Visual Params with *less* weirder values then default. Instead of a ugly alien, it looks like a fat scientist - SetDefaultParams(m_visualparams); + SetDefaultWearables(); - m_texture = GetDefaultTexture(); + SetDefaultTexture(); + SetDefaultParams(); + SetHeight(); + + m_attachments = new Dictionary>(); } - public AvatarAppearance(UUID avatarID, AvatarWearable[] wearables, byte[] visualParams) + public AvatarAppearance(UUID avatarID, OSDMap map) { +// DEBUG ON + m_log.WarnFormat("[AVATAR APPEARANCE] create appearance for {0} from OSDMap",avatarID); +// DEBUG OFF m_owner = avatarID; + Unpack(map); + SetHeight(); + } + + public AvatarAppearance(UUID avatarID, AvatarWearable[] wearables, Primitive.TextureEntry textureEntry, byte[] visualParams) + { +// DEBUG ON + m_log.WarnFormat("[AVATAR APPEARANCE] create initialized appearance for {0}",avatarID); +// DEBUG OFF m_serial = 1; - m_wearables = wearables; - m_visualparams = visualParams; - m_texture = GetDefaultTexture(); + m_owner = avatarID; + + if (wearables != null) + m_wearables = wearables; + else + SetDefaultWearables(); + + if (textureEntry != null) + m_texture = textureEntry; + else + SetDefaultTexture(); + + if (visualParams != null) + m_visualparams = visualParams; + else + SetDefaultParams(); + + SetHeight(); + + m_attachments = new Dictionary>(); + } + + public AvatarAppearance(AvatarAppearance appearance) + { +// DEBUG ON + m_log.WarnFormat("[AVATAR APPEARANCE] create from an existing appearance"); +// DEBUG OFF + if (appearance == null) + { + m_serial = 1; + m_owner = UUID.Zero; + + SetDefaultWearables(); + SetDefaultTexture(); + SetDefaultParams(); + SetHeight(); + + m_attachments = new Dictionary>(); + + return; + } + + m_serial = appearance.Serial; + m_owner = appearance.Owner; + + m_wearables = null; + if (appearance.Wearables != null) + { + m_wearables = new AvatarWearable[AvatarWearable.MAX_WEARABLES]; //should be 13 of these + for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) + SetWearable(i,appearance.Wearables[i]); + } + + m_texture = null; + if (appearance.Texture != null) + { + byte[] tbytes = appearance.Texture.GetBytes(); + m_texture = new Primitive.TextureEntry(tbytes,0,tbytes.Length); + } + + m_visualparams = null; + if (appearance.VisualParams != null) + m_visualparams = (byte[])appearance.VisualParams.Clone(); + + // 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() + { + m_wearables = AvatarWearable.DefaultWearables; + } + + protected virtual void SetDefaultParams() + { + m_visualparams = new byte[VISUALPARAM_COUNT]; + for (int i = 0; i < VISUALPARAM_COUNT; i++) + { + m_visualparams[i] = 150; + } + } + + protected virtual void SetDefaultTexture() + { + m_texture = new Primitive.TextureEntry(new UUID("C228D1CF-4B5D-4BA8-84F4-899A0796AA97")); + // The initialization of these seems to force a rebake regardless of whether it is needed + // m_textures.CreateFace(0).TextureID = new UUID("00000000-0000-1111-9999-000000000012"); + // m_textures.CreateFace(1).TextureID = Util.BLANK_TEXTURE_UUID; + // m_textures.CreateFace(2).TextureID = Util.BLANK_TEXTURE_UUID; + // m_textures.CreateFace(3).TextureID = new UUID("6522E74D-1660-4E7F-B601-6F48C1659A77"); + // m_textures.CreateFace(4).TextureID = new UUID("7CA39B4C-BD19-4699-AFF7-F93FD03D3E7B"); + // m_textures.CreateFace(5).TextureID = new UUID("00000000-0000-1111-9999-000000000010"); + // m_textures.CreateFace(6).TextureID = new UUID("00000000-0000-1111-9999-000000000011"); } /// - /// Set up appearance textures and avatar parameters, including a height calculation + /// Set up appearance textures. + /// Returns boolean that indicates whether the new entries actually change the + /// existing values. /// + public virtual bool SetTextureEntries(Primitive.TextureEntry textureEntry) + { + if (textureEntry == null) + return false; + + // There are much simpler versions of this copy that could be + // made. We determine if any of the textures actually + // changed to know if the appearance should be saved later + bool changed = false; + for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++) + { + Primitive.TextureEntryFace newface = textureEntry.FaceTextures[i]; + Primitive.TextureEntryFace oldface = m_texture.FaceTextures[i]; + + if (newface == null) + { + if (oldface == null) continue; + } + else + { + if (oldface != null && oldface.TextureID == newface.TextureID) continue; + } + + m_texture.FaceTextures[i] = (newface != null) ? new Primitive.TextureEntryFace(newface) : null; + changed = true; +// DEBUG ON + if (newface != null) + m_log.WarnFormat("[AVATAR APPEARANCE] index {0}, new texture id {1}",i,newface.TextureID); +// DEBUG OFF + } + + return changed; + } + + /// + /// Set up visual parameters for the avatar and refresh the avatar height + /// Returns boolean that indicates whether the new entries actually change the + /// existing values. + /// + public virtual bool SetVisualParams(byte[] visualParams) + { + if (visualParams == null) + return false; + + // There are much simpler versions of this copy that could be + // made. We determine if any of the visual parameters actually + // changed to know if the appearance should be saved later + bool changed = false; + for (int i = 0; i < AvatarAppearance.VISUALPARAM_COUNT; i++) + { + if (visualParams[i] != m_visualparams[i]) + { +// DEBUG ON + m_log.WarnFormat("[AVATARAPPEARANCE] vparams changed [{0}] {1} ==> {2}", + i,m_visualparams[i],visualParams[i]); +// DEBUG OFF + m_visualparams[i] = visualParams[i]; + changed = true; + } + } + + // Reset the height if the visual parameters actually changed + if (changed) + SetHeight(); + + return changed; + } + public virtual void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams) { - if (textureEntry != null) - m_texture = textureEntry; - if (visualParams != null) - m_visualparams = visualParams; - + SetTextureEntries(textureEntry); + SetVisualParams(visualParams); + } + + public virtual void SetHeight() + { m_avatarHeight = 1.23077f // Shortest possible avatar height + 0.516945f * (float)m_visualparams[(int)VPElement.SHAPE_HEIGHT] / 255.0f // Body height + 0.072514f * (float)m_visualparams[(int)VPElement.SHAPE_HEAD_SIZE] / 255.0f // Head size @@ -390,262 +445,82 @@ namespace OpenSim.Framework + 0.08f * (float)m_visualparams[(int)VPElement.SHOES_PLATFORM_HEIGHT] / 255.0f // Shoe platform height + 0.07f * (float)m_visualparams[(int)VPElement.SHOES_HEEL_HEIGHT] / 255.0f // Shoe heel height + 0.076f * (float)m_visualparams[(int)VPElement.SHAPE_NECK_LENGTH] / 255.0f; // Neck length + m_hipOffset = (((1.23077f // Half of avatar + 0.516945f * (float)m_visualparams[(int)VPElement.SHAPE_HEIGHT] / 255.0f // Body height + 0.3836f * (float)m_visualparams[(int)VPElement.SHAPE_LEG_LENGTH] / 255.0f // Leg length + 0.08f * (float)m_visualparams[(int)VPElement.SHOES_PLATFORM_HEIGHT] / 255.0f // Shoe platform height + 0.07f * (float)m_visualparams[(int)VPElement.SHOES_HEEL_HEIGHT] / 255.0f // Shoe heel height ) / 2) - m_avatarHeight / 2) * 0.31f - 0.0425f; - - - - //System.Console.WriteLine(">>>>>>> [APPEARANCE]: Height {0} Hip offset {1}" + m_avatarHeight + " " + m_hipOffset); - //m_log.Debug("------------- Set Appearance Texture ---------------"); - //Primitive.TextureEntryFace[] faces = Texture.FaceTextures; - //foreach (Primitive.TextureEntryFace face in faces) - //{ - // if (face != null) - // m_log.Debug(" ++ " + face.TextureID); - // else - // m_log.Debug(" ++ NULL "); - //} - //m_log.Debug("----------------------------"); - } public virtual void SetWearable(int wearableId, AvatarWearable wearable) { - m_wearables[wearableId] = wearable; +// DEBUG ON +// m_log.WarnFormat("[AVATARAPPEARANCE] set wearable {0} --> {1}:{2}",wearableId,wearable.ItemID,wearable.AssetID); +// DEBUG OFF + m_wearables[wearableId] = new AvatarWearable(wearable.ItemID,wearable.AssetID); } - public static Primitive.TextureEntry GetDefaultTexture() - { - Primitive.TextureEntry textu = new Primitive.TextureEntry(new UUID("C228D1CF-4B5D-4BA8-84F4-899A0796AA97")); - textu.CreateFace(0).TextureID = new UUID("00000000-0000-1111-9999-000000000012"); - textu.CreateFace(1).TextureID = Util.BLANK_TEXTURE_UUID; - textu.CreateFace(2).TextureID = Util.BLANK_TEXTURE_UUID; - textu.CreateFace(3).TextureID = new UUID("6522E74D-1660-4E7F-B601-6F48C1659A77"); - textu.CreateFace(4).TextureID = new UUID("7CA39B4C-BD19-4699-AFF7-F93FD03D3E7B"); - textu.CreateFace(5).TextureID = new UUID("00000000-0000-1111-9999-000000000010"); - textu.CreateFace(6).TextureID = new UUID("00000000-0000-1111-9999-000000000011"); - return textu; - } - - public static byte[] GetDefaultVisualParams() - { - byte[] visualParams; - visualParams = new byte[VISUALPARAM_COUNT]; - for (int i = 0; i < VISUALPARAM_COUNT; i++) - { - visualParams[i] = 100; - } - return visualParams; - } +// DEBUG ON public override String ToString() { - String s = "[Wearables] =>"; - s += " Body Item: " + BodyItem.ToString() + ";"; - s += " Skin Item: " + SkinItem.ToString() + ";"; - s += " Shirt Item: " + ShirtItem.ToString() + ";"; - s += " Pants Item: " + PantsItem.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); + + foreach (AvatarWearable awear in m_wearables) + s += String.Format("Wearable: item={0}, asset={1}\n",awear.ItemID,awear.AssetID); + + s += "Visual Params: "; + for (uint j = 0; j < AvatarAppearance.VISUALPARAM_COUNT; j++) + s += String.Format("{0},",m_visualparams[j]); + s += "\n"; + return s; } +// DEBUG OFF - // this is used for OGS1 - public virtual Hashtable ToHashTable() + /// + /// Get a list of the attachments, note that there may be + /// duplicate attachpoints + /// + public List GetAttachments() { - Hashtable h = new Hashtable(); - h["owner"] = Owner.ToString(); - h["serial"] = Serial.ToString(); - h["visual_params"] = VisualParams; - h["texture"] = Texture.GetBytes(); - h["avatar_height"] = AvatarHeight.ToString(); - h["body_item"] = BodyItem.ToString(); - h["body_asset"] = BodyAsset.ToString(); - h["skin_item"] = SkinItem.ToString(); - h["skin_asset"] = SkinAsset.ToString(); - h["hair_item"] = HairItem.ToString(); - h["hair_asset"] = HairAsset.ToString(); - h["eyes_item"] = EyesItem.ToString(); - h["eyes_asset"] = EyesAsset.ToString(); - h["shirt_item"] = ShirtItem.ToString(); - h["shirt_asset"] = ShirtAsset.ToString(); - h["pants_item"] = PantsItem.ToString(); - h["pants_asset"] = PantsAsset.ToString(); - h["shoes_item"] = ShoesItem.ToString(); - h["shoes_asset"] = ShoesAsset.ToString(); - h["socks_item"] = SocksItem.ToString(); - h["socks_asset"] = SocksAsset.ToString(); - h["jacket_item"] = JacketItem.ToString(); - h["jacket_asset"] = JacketAsset.ToString(); - h["gloves_item"] = GlovesItem.ToString(); - h["gloves_asset"] = GlovesAsset.ToString(); - h["undershirt_item"] = UnderShirtItem.ToString(); - h["undershirt_asset"] = UnderShirtAsset.ToString(); - h["underpants_item"] = UnderPantsItem.ToString(); - h["underpants_asset"] = UnderPantsAsset.ToString(); - h["skirt_item"] = SkirtItem.ToString(); - h["skirt_asset"] = SkirtAsset.ToString(); - - string attachments = GetAttachmentsString(); - if (attachments != String.Empty) - h["attachments"] = attachments; - - return h; - } - - public AvatarAppearance(Hashtable h) - { - Owner = new UUID((string)h["owner"]); - Serial = Convert.ToInt32((string)h["serial"]); - VisualParams = (byte[])h["visual_params"]; - - if (h.Contains("texture")) + List alist = new List(); + foreach (KeyValuePair> kvp in m_attachments) { - byte[] te = h["texture"] as byte[]; - if (te != null && te.Length > 0) - Texture = new Primitive.TextureEntry(te, 0, te.Length); + foreach (AvatarAttachment attach in kvp.Value) + alist.Add(new AvatarAttachment(attach)); } - else - { - // We shouldn't be receiving appearance hashtables without a TextureEntry, - // but in case we do this will prevent a failure when saving to the database - Texture = GetDefaultTexture(); - } - - AvatarHeight = (float)Convert.ToDouble((string)h["avatar_height"]); - - m_wearables = new AvatarWearable[MAX_WEARABLES]; - for (int i = 0; i < MAX_WEARABLES; i++) - { - // this makes them all null - m_wearables[i] = new AvatarWearable(); - } - - BodyItem = new UUID((string)h["body_item"]); - BodyAsset = new UUID((string)h["body_asset"]); - SkinItem = new UUID((string)h["skin_item"]); - SkinAsset = new UUID((string)h["skin_asset"]); - HairItem = new UUID((string)h["hair_item"]); - HairAsset = new UUID((string)h["hair_asset"]); - EyesItem = new UUID((string)h["eyes_item"]); - EyesAsset = new UUID((string)h["eyes_asset"]); - ShirtItem = new UUID((string)h["shirt_item"]); - ShirtAsset = new UUID((string)h["shirt_asset"]); - PantsItem = new UUID((string)h["pants_item"]); - PantsAsset = new UUID((string)h["pants_asset"]); - ShoesItem = new UUID((string)h["shoes_item"]); - ShoesAsset = new UUID((string)h["shoes_asset"]); - SocksItem = new UUID((string)h["socks_item"]); - SocksAsset = new UUID((string)h["socks_asset"]); - JacketItem = new UUID((string)h["jacket_item"]); - JacketAsset = new UUID((string)h["jacket_asset"]); - GlovesItem = new UUID((string)h["gloves_item"]); - GlovesAsset = new UUID((string)h["gloves_asset"]); - UnderShirtItem = new UUID((string)h["undershirt_item"]); - UnderShirtAsset = new UUID((string)h["undershirt_asset"]); - UnderPantsItem = new UUID((string)h["underpants_item"]); - UnderPantsAsset = new UUID((string)h["underpants_asset"]); - SkirtItem = new UUID((string)h["skirt_item"]); - SkirtAsset = new UUID((string)h["skirt_asset"]); - - if (h.ContainsKey("attachments")) - { - SetAttachmentsString(h["attachments"].ToString()); - } + return alist; } - - private Dictionary m_attachments = new Dictionary(); - - public void SetAttachments(AttachmentData[] data) + + internal void AppendAttachment(AvatarAttachment attach) { - foreach (AttachmentData a in data) - { - m_attachments[a.AttachPoint] = new UUID[2]; - m_attachments[a.AttachPoint][0] = a.ItemID; - m_attachments[a.AttachPoint][1] = a.AssetID; - } + if (! m_attachments.ContainsKey(attach.AttachPoint)) + m_attachments[attach.AttachPoint] = new List(); + m_attachments[attach.AttachPoint].Add(attach); } - public void SetAttachments(Hashtable data) + internal void ReplaceAttachment(AvatarAttachment attach) { - m_attachments.Clear(); - - if (data == null) - return; - - foreach (DictionaryEntry e in data) - { - int attachpoint = Convert.ToInt32(e.Key); - - if (m_attachments.ContainsKey(attachpoint)) - continue; - - UUID item; - UUID asset; - - Hashtable uuids = (Hashtable) e.Value; - UUID.TryParse(uuids["item"].ToString(), out item); - UUID.TryParse(uuids["asset"].ToString(), out asset); - - UUID[] attachment = new UUID[2]; - attachment[0] = item; - attachment[1] = asset; - - m_attachments[attachpoint] = attachment; - } + m_attachments[attach.AttachPoint] = new List(); + m_attachments[attach.AttachPoint].Add(attach); } - - public Dictionary GetAttachmentDictionary() - { - return m_attachments; - } - - public Hashtable GetAttachments() - { - if (m_attachments.Count == 0) - return null; - - Hashtable ret = new Hashtable(); - - foreach (KeyValuePair kvp in m_attachments) - { - int attachpoint = kvp.Key; - UUID[] uuids = kvp.Value; - - Hashtable data = new Hashtable(); - data["item"] = uuids[0].ToString(); - data["asset"] = uuids[1].ToString(); - - ret[attachpoint] = data; - } - - 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][0]; - } - - public UUID GetAttachedAsset(int attachpoint) - { - if (!m_attachments.ContainsKey(attachpoint)) - return UUID.Zero; - - return m_attachments[attachpoint][1]; - } - + + /// + /// 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) @@ -658,31 +533,47 @@ namespace OpenSim.Framework return; } - if (!m_attachments.ContainsKey(attachpoint)) - m_attachments[attachpoint] = new UUID[2]; - - m_attachments[attachpoint][0] = item; - m_attachments[attachpoint][1] = 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)); + } } public int GetAttachpoint(UUID itemID) { - foreach (KeyValuePair kvp in m_attachments) + foreach (KeyValuePair> kvp in m_attachments) { - if (kvp.Value[0] == 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() @@ -690,42 +581,123 @@ namespace OpenSim.Framework m_attachments.Clear(); } - string GetAttachmentsString() + /// + /// Create an OSDMap from the appearance data + /// + public OSDMap Pack() { - List strings = new List(); + OSDMap data = new OSDMap(); - foreach (KeyValuePair e in m_attachments) + data["serial"] = OSD.FromInteger(m_serial); + data["height"] = OSD.FromReal(m_avatarHeight); + data["hipoffset"] = OSD.FromReal(m_hipOffset); + + // Wearables + OSDArray wears = new OSDArray(AvatarWearable.MAX_WEARABLES); + for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) + wears.Add(m_wearables[i].Pack()); + data["wearables"] = wears; + + // Avatar Textures + OSDArray textures = new OSDArray(AvatarAppearance.TEXTURE_COUNT); + for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++) { - strings.Add(e.Key.ToString()); - strings.Add(e.Value[0].ToString()); - strings.Add(e.Value[1].ToString()); + if (m_texture.FaceTextures[i] != null) + textures.Add(OSD.FromUUID(m_texture.FaceTextures[i].TextureID)); + else + textures.Add(OSD.FromUUID(UUID.Zero)); } + data["textures"] = textures; - return String.Join(",", strings.ToArray()); + // Visual Parameters + OSDBinary visualparams = new OSDBinary(m_visualparams); + data["visualparams"] = visualparams; + + // Attachments + OSDArray attachs = new OSDArray(m_attachments.Count); + foreach (AvatarAttachment attach in GetAttachments()) + attachs.Add(attach.Pack()); + data["attachments"] = attachs; + + return data; } - void SetAttachmentsString(string data) + /// + /// Unpack and OSDMap and initialize the appearance + /// from it + /// + public void Unpack(OSDMap data) { - string[] strings = data.Split(new char[] {','}); - int i = 0; + 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)) + m_hipOffset = (float)data["hipoffset"].AsReal(); - m_attachments.Clear(); - - while (strings.Length - i > 2) + try { - int attachpoint = Int32.Parse(strings[i]); - UUID item = new UUID(strings[i+1]); - UUID asset = new UUID(strings[i+2]); - i += 3; - - if (!m_attachments.ContainsKey(attachpoint)) + // Wearables + SetDefaultWearables(); + if ((data != null) && (data["wearables"] != null) && (data["wearables"]).Type == OSDType.Array) { - m_attachments[attachpoint] = new UUID[2]; - m_attachments[attachpoint][0] = item; - m_attachments[attachpoint][1] = asset; + OSDArray wears = (OSDArray)(data["wearables"]); + for (int i = 0; i < wears.Count; i++) + m_wearables[i] = new AvatarWearable((OSDMap)wears[i]); + } + else + { + m_log.Warn("[AVATARAPPEARANCE] failed to unpack wearables"); + } + + // Avatar Textures + SetDefaultTexture(); + if ((data != null) && (data["textures"] != null) && (data["textures"]).Type == OSDType.Array) + { + OSDArray textures = (OSDArray)(data["textures"]); + for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT && i < textures.Count; i++) + { + if (textures[i] != null) + { + UUID textureID = textures[i].AsUUID(); + if (textureID != UUID.Zero) + m_texture.CreateFace((uint)i).TextureID = textureID; + } + } + } + else + { + m_log.Warn("[AVATARAPPEARANCE] failed to unpack textures"); + } + + // Visual Parameters + SetDefaultParams(); + if ((data != null) && (data["visualparams"] != null)) + { + if ((data["visualparams"].Type == OSDType.Binary) || (data["visualparams"].Type == OSDType.Array)) + m_visualparams = data["visualparams"].AsBinary(); + } + else + { + m_log.Warn("[AVATARAPPEARANCE] failed to unpack visual parameters"); + } + + // Attachments + 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++) + AppendAttachment(new AvatarAttachment((OSDMap)attachs[i])); } } + catch (Exception e) + { + m_log.ErrorFormat("[AVATARAPPEARANCE] unpack failed badly: {0}",e.Message); + } } + + /// /// Viewer Params Array Element for AgentSetAppearance /// Generated from LibOMV's Visual Params list diff --git a/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs b/OpenSim/Framework/AvatarAttachment.cs similarity index 56% rename from OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs rename to OpenSim/Framework/AvatarAttachment.cs index c967f30d9d..c68d78d74e 100644 --- a/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs +++ b/OpenSim/Framework/AvatarAttachment.cs @@ -25,14 +25,54 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using OpenMetaverse; -using OpenSim.Framework; +using OpenMetaverse.StructuredData; -namespace OpenSim.Region.Framework.Interfaces +namespace OpenSim.Framework { - public interface IAvatarFactory + public class AvatarAttachment { - bool TryGetAvatarAppearance(UUID avatarId, out AvatarAppearance appearance); - void UpdateDatabase(UUID userID, AvatarAppearance avatAppearance); + public int AttachPoint; + public UUID ItemID; + public UUID AssetID; + + public AvatarAttachment(AvatarAttachment attach) + { + AttachPoint = attach.AttachPoint; + ItemID = attach.ItemID; + AssetID = attach.AssetID; + } + + public AvatarAttachment(int point, UUID item, UUID asset) + { + AttachPoint = point; + ItemID = item; + AssetID = asset; + } + + public AvatarAttachment(OSDMap args) + { + Unpack(args); + } + + public OSDMap Pack() + { + OSDMap attachdata = new OSDMap(); + attachdata["point"] = OSD.FromInteger(AttachPoint); + attachdata["item"] = OSD.FromUUID(ItemID); + attachdata["asset"] = OSD.FromUUID(AssetID); + + return attachdata; + } + + + public void Unpack(OSDMap args) + { + if (args["point"] != null) + AttachPoint = args["point"].AsInteger(); + ItemID = (args["item"] != null) ? args["item"].AsUUID() : UUID.Zero; + AssetID = (args["asset"] != null) ? args["asset"].AsUUID() : UUID.Zero; + } } } diff --git a/OpenSim/Framework/AvatarWearable.cs b/OpenSim/Framework/AvatarWearable.cs index 30c5172ad4..87098bf6d0 100644 --- a/OpenSim/Framework/AvatarWearable.cs +++ b/OpenSim/Framework/AvatarWearable.cs @@ -26,14 +26,32 @@ */ using System; -using System.Runtime.Serialization; -using System.Security.Permissions; using OpenMetaverse; +using OpenMetaverse.StructuredData; namespace OpenSim.Framework { public class AvatarWearable { + // these are guessed at by the list here - + // http://wiki.secondlife.com/wiki/Avatar_Appearance. We'll + // correct them over time for when were are wrong. + public static readonly int BODY = 0; + public static readonly int SKIN = 1; + public static readonly int HAIR = 2; + public static readonly int EYES = 3; + public static readonly int SHIRT = 4; + public static readonly int PANTS = 5; + public static readonly int SHOES = 6; + public static readonly int SOCKS = 7; + public static readonly int JACKET = 8; + public static readonly int GLOVES = 9; + public static readonly int UNDERSHIRT = 10; + public static readonly int UNDERPANTS = 11; + public static readonly int SKIRT = 12; + + public static readonly int MAX_WEARABLES = 13; + public static readonly UUID DEFAULT_BODY_ITEM = new UUID("66c41e39-38f9-f75a-024e-585989bfaba9"); public static readonly UUID DEFAULT_BODY_ASSET = new UUID("66c41e39-38f9-f75a-024e-585989bfab73"); @@ -62,12 +80,32 @@ namespace OpenSim.Framework ItemID = itemId; } + public AvatarWearable(OSDMap args) + { + Unpack(args); + } + + public OSDMap Pack() + { + OSDMap weardata = new OSDMap(); + weardata["item"] = OSD.FromUUID(ItemID); + weardata["asset"] = OSD.FromUUID(AssetID); + + return weardata; + } + + public void Unpack(OSDMap args) + { + ItemID = (args["item"] != null) ? args["item"].AsUUID() : UUID.Zero; + AssetID = (args["asset"] != null) ? args["asset"].AsUUID() : UUID.Zero; + } + public static AvatarWearable[] DefaultWearables { get { - AvatarWearable[] defaultWearables = new AvatarWearable[13]; //should be 13 of these - for (int i = 0; i < 13; i++) + AvatarWearable[] defaultWearables = new AvatarWearable[MAX_WEARABLES]; //should be 13 of these + for (int i = 0; i < MAX_WEARABLES; i++) { defaultWearables[i] = new AvatarWearable(); } diff --git a/OpenSim/Framework/Capabilities/Caps.cs b/OpenSim/Framework/Capabilities/Caps.cs index 72283de7bb..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; @@ -976,12 +988,14 @@ namespace OpenSim.Framework.Capabilities public void BakedTextureUploaded(UUID assetID, byte[] data) { - m_log.DebugFormat("[CAPS]: Received baked texture {0}", assetID.ToString()); +// DEBUG ON + m_log.WarnFormat("[CAPS]: Received baked texture {0}", assetID.ToString()); +// DEBUG OFF AssetBase asset; 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/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index 0dc5dbc292..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; @@ -225,46 +227,6 @@ namespace OpenSim.Framework } } - public class AttachmentData - { - public int AttachPoint; - public UUID ItemID; - public UUID AssetID; - - public AttachmentData(int point, UUID item, UUID asset) - { - AttachPoint = point; - ItemID = item; - AssetID = asset; - } - - public AttachmentData(OSDMap args) - { - UnpackUpdateMessage(args); - } - - public OSDMap PackUpdateMessage() - { - OSDMap attachdata = new OSDMap(); - attachdata["point"] = OSD.FromInteger(AttachPoint); - attachdata["item"] = OSD.FromUUID(ItemID); - attachdata["asset"] = OSD.FromUUID(AssetID); - - return attachdata; - } - - - public void UnpackUpdateMessage(OSDMap args) - { - if (args["point"] != null) - AttachPoint = args["point"].AsInteger(); - if (args["item"] != null) - ItemID = args["item"].AsUUID(); - if (args["asset"] != null) - AssetID = args["asset"].AsUUID(); - } - } - public class ControllerData { public UUID ItemID; @@ -348,11 +310,20 @@ namespace OpenSim.Framework public UUID GranterID; // 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; public UUID[] Wearables; - public AttachmentData[] Attachments; - + public AvatarAttachment[] Attachments; +*/ // Scripted public ControllerData[] Controllers; @@ -360,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"); @@ -413,6 +388,9 @@ namespace OpenSim.Framework args["animations"] = anims; } + if (Appearance != null) + args["packed_appearance"] = Appearance.Pack(); + //if ((AgentTextures != null) && (AgentTextures.Length > 0)) //{ // OSDArray textures = new OSDArray(AgentTextures.Length); @@ -421,30 +399,39 @@ 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) + { + byte[] rawtextures = Appearance.Texture.GetBytes(); + args["texture_entry"] = OSD.FromBinary(rawtextures); + } - 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.Count > 0)) { - OSDArray attachs = new OSDArray(Attachments.Length); - foreach (AttachmentData att in Attachments) - attachs.Add(att.PackUpdateMessage()); + OSDArray attachs = new OSDArray(attachments.Count); + foreach (AvatarAttachment att in attachments) + attachs.Add(att.Pack()); args["attachments"] = attachs; } + // End of code to remove if ((Controllers != null) && (Controllers.Length > 0)) { @@ -469,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); @@ -581,34 +572,53 @@ namespace OpenSim.Framework // AgentTextures[i++] = o.AsUUID(); //} + Appearance = new AvatarAppearance(AgentID); + + // 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) - AgentTextures = 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) - 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++) + { + AvatarWearable awear = new AvatarWearable(wears[i*2].AsUUID(),wears[(i*2)+1].AsUUID()); + Appearance.SetWearable(i,awear); + } } if ((args["attachments"] != null) && (args["attachments"]).Type == OSDType.Array) { OSDArray attachs = (OSDArray)(args["attachments"]); - Attachments = new AttachmentData[attachs.Count]; - int i = 0; foreach (OSD o in attachs) { if (o.Type == OSDType.Map) { - Attachments[i++] = new AttachmentData((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)); } } } + // end of code to remove + + if (args.ContainsKey("packed_appearance") && (args["packed_appearance"]).Type == OSDType.Map) + Appearance = new AvatarAppearance(AgentID,(OSDMap)args["packed_appearance"]); +// DEBUG ON + else + m_log.WarnFormat("[CHILDAGENTDATAUPDATE] No packed appearance"); +// DEBUG OFF if ((args["controllers"] != null) && (args["controllers"]).Type == OSDType.Array) { diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 94815cd238..027f9c54b1 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -43,7 +43,7 @@ namespace OpenSim.Framework public delegate void TextureRequest(Object sender, TextureRequestArgs e); - public delegate void AvatarNowWearing(Object sender, AvatarWearingArgs e); + public delegate void AvatarNowWearing(IClientAPI sender, AvatarWearingArgs e); public delegate void ImprovedInstantMessage(IClientAPI remoteclient, GridInstantMessage im); @@ -65,7 +65,7 @@ namespace OpenSim.Framework public delegate void NetworkStats(int inPackets, int outPackets, int unAckedBytes); - public delegate void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams); + public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams); public delegate void StartAnim(IClientAPI remoteClient, UUID animID); @@ -711,7 +711,7 @@ namespace OpenSim.Framework event TeleportLandmarkRequest OnTeleportLandmarkRequest; event DeRezObject OnDeRezObject; event Action OnRegionHandShakeReply; - event GenericCall2 OnRequestWearables; + event GenericCall1 OnRequestWearables; event GenericCall1 OnCompleteMovementToRegion; event UpdateAgent OnPreAgentUpdate; event UpdateAgent OnAgentUpdate; diff --git a/OpenSim/Framework/Tests/AgentCircuitDataTest.cs b/OpenSim/Framework/Tests/AgentCircuitDataTest.cs index 2fda6f31cc..05d8469728 100644 --- a/OpenSim/Framework/Tests/AgentCircuitDataTest.cs +++ b/OpenSim/Framework/Tests/AgentCircuitDataTest.cs @@ -65,9 +65,7 @@ namespace OpenSim.Framework.Tests SessionId = UUID.Random(); AvAppearance = new AvatarAppearance(AgentId); - AvAppearance.SetDefaultWearables(); VisualParams = new byte[218]; - AvAppearance.SetDefaultParams(VisualParams); //body VisualParams[(int)AvatarAppearance.VPElement.SHAPE_HEIGHT] = 155; diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 74ad485bba..14f923dd1f 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -79,7 +79,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event DeRezObject OnDeRezObject; public event ModifyTerrain OnModifyTerrain; public event Action OnRegionHandShakeReply; - public event GenericCall2 OnRequestWearables; + public event GenericCall1 OnRequestWearables; public event SetAppearance OnSetAppearance; public event AvatarNowWearing OnAvatarNowWearing; public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; @@ -5647,11 +5647,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP private bool HandlerAgentWearablesRequest(IClientAPI sender, Packet Pack) { - GenericCall2 handlerRequestWearables = OnRequestWearables; + GenericCall1 handlerRequestWearables = OnRequestWearables; if (handlerRequestWearables != null) { - handlerRequestWearables(); + handlerRequestWearables(sender); } Action handlerRequestAvatarsData = OnRequestAvatarsData; @@ -5694,7 +5694,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (appear.ObjectData.TextureEntry.Length > 1) te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); - handlerSetAppearance(te, visualparams); + handlerSetAppearance(sender, te, visualparams); } catch (Exception e) { diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 2a0c0b11e6..ad6b1deba4 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -124,13 +124,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // Save avatar attachment information ScenePresence presence; - if (m_scene.AvatarFactory != null && m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) + if (m_scene.AvatarService != null && m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) { m_log.Info( "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId + ", AttachmentPoint: " + AttachmentPt); - m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + m_scene.AvatarService.SetAppearance(remoteClient.AgentId, presence.Appearance); } } } @@ -382,8 +382,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments item = m_scene.InventoryService.GetItem(item); presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /* att.UUID */); - if (m_scene.AvatarFactory != null) - m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + if (m_scene.AvatarService != null) + m_scene.AvatarService.SetAppearance(remoteClient.AgentId, presence.Appearance); } } @@ -405,10 +405,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments presence.Appearance.DetachAttachment(itemID); // Save avatar attachment information - if (m_scene.AvatarFactory != null) + if (m_scene.AvatarService != null) { m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID); - m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + m_scene.AvatarService.SetAppearance(remoteClient.AgentId, presence.Appearance); } } @@ -435,9 +435,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments presence.Appearance.DetachAttachment(itemID); - if (m_scene.AvatarFactory != null) + if (m_scene.AvatarService != null) { - m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + m_scene.AvatarService.SetAppearance(remoteClient.AgentId, presence.Appearance); } part.ParentGroup.DetachToGround(); diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 22c89370a7..5f8b4f6b0c 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -32,58 +32,56 @@ 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; namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory { - public class AvatarFactoryModule : IAvatarFactory, IRegionModule + public class AvatarFactoryModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; private Scene m_scene = null; - private static readonly AvatarAppearance def = new AvatarAppearance(); - public bool TryGetAvatarAppearance(UUID avatarId, out AvatarAppearance 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 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 config) { - AvatarData avatar = m_scene.AvatarService.GetAvatar(avatarId); - //if ((profile != null) && (profile.RootFolder != null)) - if (avatar != null) - { - appearance = avatar.ToAvatarAppearance(avatarId); - return true; - } - - m_log.ErrorFormat("[APPEARANCE]: Appearance not found for {0}, creating default", avatarId); - appearance = CreateDefault(avatarId); - return false; - } - - private AvatarAppearance CreateDefault(UUID avatarId) - { - AvatarAppearance appearance = null; - AvatarWearable[] wearables; - byte[] visualParams; - GetDefaultAvatarAppearance(out wearables, out visualParams); - appearance = new AvatarAppearance(avatarId, wearables, visualParams); - - return appearance; - } - - public void Initialise(Scene scene, IConfigSource source) - { - scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += NewClient; - if (m_scene == null) + if (config != null) { - m_scene = scene; + 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; } 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() @@ -102,6 +100,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory public void NewClient(IClientAPI client) { + client.OnRequestWearables += SendWearables; + client.OnSetAppearance += SetAppearance; client.OnAvatarNowWearing += AvatarIsWearing; } @@ -110,13 +110,263 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // client.OnAvatarNowWearing -= AvatarIsWearing; } - public void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) + #endregion + + /// + /// Set appearance data (textureentry and slider settings) received from the client + /// + /// + /// + 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) + { + m_log.WarnFormat("[AVFACTORY] SetAppearance unable to find presence for {0}",client.AgentId); + return; + } + + 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 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,idx); }); + } + } + + // Process the visual params, this may change height as well + if (visualParams != null) + { + if (sp.Appearance.SetVisualParams(visualParams)) + { + changed = true; + if (sp.Appearance.AvatarHeight > 0) + sp.SetHeight(sp.Appearance.AvatarHeight); + } + } + + // 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; + } +*/ + } + + 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 + /// + public void SendWearables(IClientAPI client) + { + ScenePresence sp = m_scene.GetScenePresence(client.AgentId); + if (sp == null) + { + m_log.WarnFormat("[AVFACTORY] SendWearables unable to find presence for {0}",client.AgentId); + return; + } + +// DEBUG ON + m_log.WarnFormat("[AVFACTORY]: Received request for wearables of {0}", client.AgentId); +// DEBUG OFF + client.SendWearables(sp.Appearance.Wearables,sp.Appearance.Serial++); + } + + /// + /// Update what the avatar is wearing using an item from their inventory. + /// + /// + /// + public void AvatarIsWearing(IClientAPI client, AvatarWearingArgs e) + { + ScenePresence sp = m_scene.GetScenePresence(client.AgentId); + if (sp == null) + { + m_log.WarnFormat("[AVFACTORY] AvatarIsWearing unable to find presence for {0}",client.AgentId); + return; + } + +// DEBUG ON + m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing called for {0}",client.AgentId); +// DEBUG OFF + + AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance); + + //if (!TryGetAvatarAppearance(client.AgentId, out avatAppearance)) + //{ + // m_log.Warn("[AVFACTORY]: We didn't seem to find the appearance, falling back to ScenePresence"); + // avatAppearance = sp.Appearance; + //} + + //m_log.DebugFormat("[AVFACTORY]: Received wearables for {0}", client.Name); + + foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) + { + if (wear.Type < AvatarWearable.MAX_WEARABLES) + { + AvatarWearable newWearable = new AvatarWearable(wear.ItemID,UUID.Zero); + avatAppearance.SetWearable(wear.Type, newWearable); + } + } + + SetAppearanceAssets(sp.UUID, ref avatAppearance); + + m_scene.AvatarService.SetAppearance(client.AgentId, avatAppearance); + sp.Appearance = avatAppearance; + } + + private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) { IInventoryService invService = m_scene.InventoryService; if (invService.GetRootFolder(userID) != null) { - for (int i = 0; i < 13; i++) + for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) { if (appearance.Wearables[i].ItemID == UUID.Zero) { @@ -134,84 +384,19 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory else { m_log.ErrorFormat( - "[APPEARANCE]: Can't find inventory item {0} for {1}, setting to default", + "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", appearance.Wearables[i].ItemID, (WearableType)i); - appearance.Wearables[i].AssetID = def.Wearables[i].AssetID; + appearance.Wearables[i].ItemID = UUID.Zero; + appearance.Wearables[i].AssetID = UUID.Zero; } } } } else { - m_log.WarnFormat("[APPEARANCE]: user {0} has no inventory, appearance isn't going to work", userID); + m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); } } - - /// - /// Update what the avatar is wearing using an item from their inventory. - /// - /// - /// - public void AvatarIsWearing(Object sender, AvatarWearingArgs e) - { - m_log.DebugFormat("[APPEARANCE]: AvatarIsWearing"); - - IClientAPI clientView = (IClientAPI)sender; - ScenePresence sp = m_scene.GetScenePresence(clientView.AgentId); - - if (sp == null) - { - m_log.Error("[APPEARANCE]: Avatar is child agent, ignoring AvatarIsWearing event"); - return; - } - - AvatarAppearance avatAppearance = sp.Appearance; - //if (!TryGetAvatarAppearance(clientView.AgentId, out avatAppearance)) - //{ - // m_log.Warn("[APPEARANCE]: We didn't seem to find the appearance, falling back to ScenePresence"); - // avatAppearance = sp.Appearance; - //} - - //m_log.DebugFormat("[APPEARANCE]: Received wearables for {0}", clientView.Name); - - foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) - { - if (wear.Type < 13) - { - avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID; - } - } - - SetAppearanceAssets(sp.UUID, ref avatAppearance); - AvatarData adata = new AvatarData(avatAppearance); - m_scene.AvatarService.SetAvatar(clientView.AgentId, adata); - - sp.Appearance = avatAppearance; - } - - public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams) - { - visualParams = GetDefaultVisualParams(); - wearables = AvatarWearable.DefaultWearables; - } - - public void UpdateDatabase(UUID user, AvatarAppearance appearance) - { - //m_log.DebugFormat("[APPEARANCE]: UpdateDatabase"); - AvatarData adata = new AvatarData(appearance); - m_scene.AvatarService.SetAvatar(user, adata); - } - - private static byte[] GetDefaultVisualParams() - { - byte[] visualParams; - visualParams = new byte[218]; - for (int i = 0; i < 218; i++) - { - visualParams[i] = 100; - } - return visualParams; - } } } diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index d76ff47f87..4359c01d5d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -238,7 +238,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat } (scene as Scene).EventManager.TriggerOnChatToClients( - fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); + fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); } static private Vector3 CenterOfRegion = new Vector3(128, 128, 30); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 55005572ba..046b05f48e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -143,7 +143,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { LoadControlFile(filePath, data); - } + } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) { if (LoadAsset(filePath, data)) @@ -479,11 +479,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// protected void LoadControlFile(string path, byte[] data) - { + { XDocument doc = XDocument.Parse(Encoding.ASCII.GetString(data)); XElement archiveElement = doc.Element("archive"); int majorVersion = int.Parse(archiveElement.Attribute("major_version").Value); - int minorVersion = int.Parse(archiveElement.Attribute("minor_version").Value); + int minorVersion = int.Parse(archiveElement.Attribute("minor_version").Value); string version = string.Format("{0}.{1}", majorVersion, minorVersion); if (majorVersion > MAX_MAJOR_VERSION) @@ -492,7 +492,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver string.Format( "The IAR you are trying to load has major version number of {0} but this version of OpenSim can only load IARs with major version number {1} and below", majorVersion, MAX_MAJOR_VERSION)); - } + } m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version); } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index 249a8b4b9c..9080e1c92f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -213,7 +213,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver public void Execute() { try - { + { InventoryFolderBase inventoryFolder = null; InventoryItemBase inventoryItem = null; InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); @@ -277,7 +277,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // Write out control file. This has to be done first so that subsequent loaders will see this file first // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p1ControlFile()); - m_log.InfoFormat("[INVENTORY ARCHIVER]: Added control file to archive."); + m_log.InfoFormat("[INVENTORY ARCHIVER]: Added control file to archive."); if (inventoryFolder != null) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/LocalAvatarServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/LocalAvatarServiceConnector.cs index 47f19a3038..9ee19f8f25 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/LocalAvatarServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/LocalAvatarServiceConnector.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using System.Reflection; using log4net; using Nini.Config; +using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Server.Base; @@ -137,6 +138,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar #region IAvatarService + public AvatarAppearance GetAppearance(UUID userID) + { + return m_AvatarService.GetAppearance(userID); + } + + public bool SetAppearance(UUID userID, AvatarAppearance appearance) + { + return m_AvatarService.SetAppearance(userID,appearance); + } + public AvatarData GetAvatar(UUID userID) { return m_AvatarService.GetAvatar(userID); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 1687d06350..31820794b8 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -199,13 +199,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver { majorVersion = 1; minorVersion = 0; - } + } */ m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); // if (majorVersion == 1) // { -// m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR"); +// m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR"); // } @@ -232,6 +232,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver sw.Close(); return s; - } + } } } diff --git a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs index a6dc2ec79a..cea7c78ce8 100644 --- a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs +++ b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs @@ -44,10 +44,8 @@ namespace OpenSim.Region.CoreModules /// it is not based on ~06:00 == Sun Rise. Rather it is based on 00:00 being sun-rise. /// - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - // // Global Constants used to determine where in the sky the sun is // @@ -108,26 +106,25 @@ namespace OpenSim.Region.CoreModules private Scene m_scene = null; // Calculated Once in the lifetime of a region - private long TicksToEpoch; // Elapsed time for 1/1/1970 - private uint SecondsPerSunCycle; // Length of a virtual day in RW seconds - private uint SecondsPerYear; // Length of a virtual year in RW seconds - private double SunSpeed; // Rate of passage in radians/second - private double SeasonSpeed; // Rate of change for seasonal effects - // private double HoursToRadians; // Rate of change for seasonal effects - private long TicksUTCOffset = 0; // seconds offset from UTC + private long TicksToEpoch; // Elapsed time for 1/1/1970 + private uint SecondsPerSunCycle; // Length of a virtual day in RW seconds + private uint SecondsPerYear; // Length of a virtual year in RW seconds + private double SunSpeed; // Rate of passage in radians/second + private double SeasonSpeed; // Rate of change for seasonal effects + // private double HoursToRadians; // Rate of change for seasonal effects + private long TicksUTCOffset = 0; // seconds offset from UTC // Calculated every update - private float OrbitalPosition; // Orbital placement at a point in time - private double HorizonShift; // Axis offset to skew day and night - private double TotalDistanceTravelled; // Distance since beginning of time (in radians) - private double SeasonalOffset; // Seaonal variation of tilt - private float Magnitude; // Normal tilt - // private double VWTimeRatio; // VW time as a ratio of real time + private float OrbitalPosition; // Orbital placement at a point in time + private double HorizonShift; // Axis offset to skew day and night + private double TotalDistanceTravelled; // Distance since beginning of time (in radians) + private double SeasonalOffset; // Seaonal variation of tilt + private float Magnitude; // Normal tilt + // private double VWTimeRatio; // VW time as a ratio of real time // Working values private Vector3 Position = Vector3.Zero; private Vector3 Velocity = Vector3.Zero; - private Quaternion Tilt = new Quaternion(1.0f, 0.0f, 0.0f, 0.0f); - + private Quaternion Tilt = new Quaternion(1.0f, 0.0f, 0.0f, 0.0f); // Used to fix the sun in the sky so it doesn't move based on current time private bool m_SunFixed = false; @@ -135,8 +132,6 @@ namespace OpenSim.Region.CoreModules private const int TICKS_PER_SECOND = 10000000; - - // Current time in elapsed seconds since Jan 1st 1970 private ulong CurrentTime { @@ -149,8 +144,6 @@ namespace OpenSim.Region.CoreModules // Time in seconds since UTC to use to calculate sun position. ulong PosTime = 0; - - /// /// Calculate the sun's orbital position and its velocity. /// @@ -202,7 +195,6 @@ namespace OpenSim.Region.CoreModules PosTime += (ulong)(((CurDayPercentage - 0.5) / .5) * NightSeconds); } } - } TotalDistanceTravelled = SunSpeed * PosTime; // distance measured in radians @@ -251,7 +243,6 @@ namespace OpenSim.Region.CoreModules Velocity.X = 0; Velocity.Y = 0; Velocity.Z = 0; - } else { @@ -271,9 +262,7 @@ namespace OpenSim.Region.CoreModules private float GetCurrentTimeAsLindenSunHour() { if (m_SunFixed) - { return m_SunFixedHour + 6; - } return GetCurrentSunHour() + 6.0f; } @@ -297,8 +286,6 @@ namespace OpenSim.Region.CoreModules m_scene.AddCommand(this, String.Format("sun {0}", kvp.Key), String.Format("{0} - {1}", kvp.Key, kvp.Value), "", HandleSunConsoleCommand); } - - TimeZone local = TimeZone.CurrentTimeZone; TicksUTCOffset = local.GetUtcOffset(local.ToLocalTime(DateTime.Now)).Ticks; m_log.Debug("[SUN]: localtime offset is " + TicksUTCOffset); @@ -325,13 +312,11 @@ namespace OpenSim.Region.CoreModules // must hard code to ~.5 to match sun position in LL based viewers m_HorizonShift = config.Configs["Sun"].GetDouble("day_night_offset", d_day_night); - // Scales the sun hours 0...12 vs 12...24, essentially makes daylight hours longer/shorter vs nighttime hours m_DayTimeSunHourScale = config.Configs["Sun"].GetDouble("day_time_sun_hour_scale", d_DayTimeSunHourScale); // Update frequency in frames m_UpdateInterval = config.Configs["Sun"].GetInt("update_interval", d_frame_mod); - } catch (Exception e) { @@ -391,10 +376,8 @@ namespace OpenSim.Region.CoreModules } scene.RegisterModuleInterface(this); - } - public void PostInitialise() { } @@ -402,7 +385,7 @@ namespace OpenSim.Region.CoreModules public void Close() { ready = false; - + // Remove our hooks m_scene.EventManager.OnFrame -= SunUpdate; m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; @@ -419,6 +402,7 @@ namespace OpenSim.Region.CoreModules { get { return false; } } + #endregion #region EventManager Events @@ -446,9 +430,7 @@ namespace OpenSim.Region.CoreModules public void SunUpdate() { if (((m_frame++ % m_UpdateInterval) != 0) || !ready || m_SunFixed || !receivedEstateToolsSunUpdate) - { return; - } GenSunPos(); // Generate shared values once @@ -467,7 +449,7 @@ namespace OpenSim.Region.CoreModules } /// - /// + /// /// /// /// Is the sun's position fixed? @@ -484,7 +466,6 @@ namespace OpenSim.Region.CoreModules while (FixedSunHour < 0) FixedSunHour += 24; - m_SunFixedHour = FixedSunHour; m_SunFixed = FixedSun; @@ -499,14 +480,12 @@ namespace OpenSim.Region.CoreModules // When sun settings are updated, we should update all clients with new settings. SunUpdateToAllClients(); - m_log.DebugFormat("[SUN]: PosTime : {0}", PosTime.ToString()); } } #endregion - private void SunUpdateToAllClients() { m_scene.ForEachScenePresence(delegate(ScenePresence sp) @@ -553,7 +532,6 @@ namespace OpenSim.Region.CoreModules { float ticksleftover = CurrentTime % SecondsPerSunCycle; - return (24.0f * (ticksleftover / SecondsPerSunCycle)); } @@ -666,7 +644,6 @@ namespace OpenSim.Region.CoreModules // When sun settings are updated, we should update all clients with new settings. SunUpdateToAllClients(); - } return Output; diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 268612efda..f128aa2da4 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -82,7 +82,7 @@ namespace OpenSim.Region.Examples.SimpleModule public event DeRezObject OnDeRezObject; public event Action OnRegionHandShakeReply; - public event GenericCall2 OnRequestWearables; + public event GenericCall1 OnRequestWearables; public event GenericCall1 OnCompleteMovementToRegion; public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate; diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 4feb3fc3de..c321a15866 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -296,7 +296,7 @@ namespace OpenSim.Region.Framework.Scenes /// ChatToClientsEvent is triggered via ChatModule (or /// substitutes thereof) when a chat message is actually sent to clients. Clients will only be sent a /// received chat message if they satisfy various conditions (within audible range, etc.) - /// + /// public delegate void ChatToClientsEvent( UUID senderID, HashSet receiverIDs, string message, ChatTypeEnum type, Vector3 fromPos, string fromName, @@ -1636,8 +1636,8 @@ namespace OpenSim.Region.Framework.Scenes e.Message, e.StackTrace); } } - } - } + } + } public void TriggerOnChatBroadcast(Object sender, OSChatMessage chat) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 4878b3e46d..f77fb2c0c0 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -119,7 +119,6 @@ namespace OpenSim.Region.Framework.Scenes protected IXMLRPC m_xmlrpcModule; protected IWorldComm m_worldCommModule; - protected IAvatarFactory m_AvatarFactory; protected IConfigSource m_config; protected IRegionSerialiserModule m_serialiser; protected IDialogModule m_dialogModule; @@ -399,11 +398,6 @@ namespace OpenSim.Region.Framework.Scenes public IAttachmentsModule AttachmentsModule { get; set; } - public IAvatarFactory AvatarFactory - { - get { return m_AvatarFactory; } - } - public ICapabilitiesModule CapsModule { get { return m_capsModule; } @@ -1159,7 +1153,6 @@ namespace OpenSim.Region.Framework.Scenes m_xmlrpcModule = RequestModuleInterface(); m_worldCommModule = RequestModuleInterface(); XferManager = RequestModuleInterface(); - m_AvatarFactory = RequestModuleInterface(); AttachmentsModule = RequestModuleInterface(); m_serialiser = RequestModuleInterface(); m_dialogModule = RequestModuleInterface(); @@ -3278,7 +3271,6 @@ namespace OpenSim.Region.Framework.Scenes m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", m_regInfo.RegionName); } - /// /// Do the work necessary to initiate a new user connection for a particular scene. /// At the moment, this consists of setting up the caps infrastructure @@ -3290,6 +3282,23 @@ namespace OpenSim.Region.Framework.Scenes /// True if the region accepts this agent. False if it does not. False will /// also return a reason. public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason) + { + return NewUserConnection(agent, teleportFlags, out reason, true); + } + + /// + /// Do the work necessary to initiate a new user connection for a particular scene. + /// At the moment, this consists of setting up the caps infrastructure + /// The return bool should allow for connections to be refused, but as not all calling paths + /// take proper notice of it let, we allowed banned users in still. + /// + /// CircuitData of the agent who is connecting + /// Outputs the reason for the false response on this string + /// True for normal presence. False for NPC + /// or other applications where a full grid/Hypergrid presence may not be required. + /// True if the region accepts this agent. False if it does not. False will + /// also return a reason. + public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) { bool vialogin = ((teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0 || (teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0); @@ -3339,16 +3348,18 @@ namespace OpenSim.Region.Framework.Scenes if (sp == null) // We don't have an [child] agent here already { - - try + if (requirePresenceLookup) { - if (!VerifyUserPresence(agent, out reason)) + try + { + if (!VerifyUserPresence(agent, out reason)) + return false; + } + catch (Exception e) + { + m_log.ErrorFormat("[CONNECTION BEGIN]: Exception verifying presence " + e.ToString()); return false; - } - catch (Exception e) - { - m_log.ErrorFormat("[CONNECTION BEGIN]: Exception verifying presence " + e.ToString()); - return false; + } } try diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index f81c551768..24d73346ff 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -406,11 +406,14 @@ namespace OpenSim.Region.Framework.Scenes public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked) { EntityBase entity; - if (!Entities.TryGetValue(uuid, out entity) && entity is SceneObjectGroup) + if (!Entities.TryGetValue(uuid, out entity) || (!(entity is SceneObjectGroup))) return false; SceneObjectGroup grp = (SceneObjectGroup)entity; + if (entity == null) + return false; + if (!resultOfObjectLinked) { m_numPrim -= grp.PrimCount; diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 68ac178e50..1abd134203 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -75,7 +75,6 @@ namespace OpenSim.Region.Framework.Scenes private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; // private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); @@ -137,8 +136,6 @@ namespace OpenSim.Region.Framework.Scenes private SendCourseLocationsMethod m_sendCourseLocationsMethod; - private bool m_startAnimationSet; - //private Vector3 m_requestedSitOffset = new Vector3(); private Vector3 m_LastFinitePos; @@ -713,13 +710,14 @@ namespace OpenSim.Region.Framework.Scenes SetDirectionVectors(); } +/* public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams, AvatarWearable[] wearables) : this(client, world, reginfo) { m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams); } - +*/ public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance) : this(client, world, reginfo) { @@ -733,8 +731,6 @@ namespace OpenSim.Region.Framework.Scenes public void RegisterToEvents() { - m_controllingClient.OnRequestWearables += SendWearables; - m_controllingClient.OnSetAppearance += SetAppearance; m_controllingClient.OnCompleteMovementToRegion += CompleteMovement; //m_controllingClient.OnCompleteMovementToRegion += SendInitialData; m_controllingClient.OnAgentUpdate += HandleAgentUpdate; @@ -1068,7 +1064,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// Sets avatar height in the phyiscs plugin /// - internal void SetHeight(float height) + public void SetHeight(float height) { m_avHeight = height; if (PhysicsActor != null && !IsChildAgent) @@ -1133,7 +1129,6 @@ namespace OpenSim.Region.Framework.Scenes if (friendsModule != null) friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); } - } /// @@ -2392,9 +2387,12 @@ namespace OpenSim.Region.Framework.Scenes if (m_appearance.Texture == null) return; - Vector3 pos = m_pos; - pos.Z += m_appearance.HipOffset; - + if (IsChildAgent) + { + m_log.WarnFormat("[SCENEPRESENCE] A child agent is attempting to send out avatar data"); + return; + } + remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this); m_scene.StatsReporter.AddAgentUpdates(1); } @@ -2437,6 +2435,12 @@ namespace OpenSim.Region.Framework.Scenes m_perfMonMS = Util.EnvironmentTickCount(); // only send update from root agents to other clients; children are only "listening posts" + if (IsChildAgent) + { + m_log.Warn("[SCENEPRESENCE] attempt to send update from a childagent"); + return; + } + int count = 0; m_scene.ForEachScenePresence(delegate(ScenePresence sp) { @@ -2460,29 +2464,20 @@ namespace OpenSim.Region.Framework.Scenes // the inventory arrives // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); - Vector3 pos = m_pos; - pos.Z += m_appearance.HipOffset; - m_controllingClient.SendAvatarDataImmediate(this); + m_controllingClient.SendAppearance(m_appearance.Owner,m_appearance.VisualParams,m_appearance.Texture.GetBytes()); SendInitialFullUpdateToAllClients(); } - /// - /// Tell the client for this scene presence what items it should be wearing now - /// - public void SendWearables() - { - m_log.DebugFormat("[SCENE]: Received request for wearables of {0}", Name); - - ControllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++); - } - /// /// /// public void SendAppearanceToAllOtherAgents() { +// DEBUG ON + m_log.WarnFormat("[SP] Send appearance from {0} to all other agents",m_uuid); +// DEBUG OFF m_perfMonMS = Util.EnvironmentTickCount(); m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) @@ -2502,87 +2497,13 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendAppearanceToOtherAgent(ScenePresence avatar) { +// DEBUG ON + m_log.WarnFormat("[SP] Send appearance from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId); +// DEBUG OFF avatar.ControllingClient.SendAppearance( m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes()); } - /// - /// Set appearance data (textureentry and slider settings) received from the client - /// - /// - /// - public void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams) - { - 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 - - if (textureEntry != null) - { - for (int i = 0; i < BAKE_INDICES.Length; i++) - { - int j = BAKE_INDICES[i]; - 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.Warn("[APPEARANCE]: Missing baked texture " + face.TextureID + " (" + j + ") for avatar " + this.Name); - this.ControllingClient.SendRebakeAvatarTextures(face.TextureID); - } - } - } - - } - - - #endregion Bake Cache Check - - m_appearance.SetAppearance(textureEntry, visualParams); - if (m_appearance.AvatarHeight > 0) - SetHeight(m_appearance.AvatarHeight); - - // This is not needed, because only the transient data changed - //AvatarData adata = new AvatarData(m_appearance); - //m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata); - - SendAppearanceToAllOtherAgents(); - if (!m_startAnimationSet) - { - Animator.UpdateMovementAnimations(); - m_startAnimationSet = true; - } - - Vector3 pos = m_pos; - pos.Z += m_appearance.HipOffset; - - m_controllingClient.SendAvatarDataImmediate(this); - } - - public void SetWearable(int wearableId, AvatarWearable wearable) - { - m_appearance.SetWearable(wearableId, wearable); - AvatarData adata = new AvatarData(m_appearance); - m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata); - m_controllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++); - } - // Because appearance setting is in a module, we actually need // to give it access to our appearance directly, otherwise we // get a synchronization issue. @@ -3017,6 +2938,9 @@ namespace OpenSim.Region.Framework.Scenes cAgent.AlwaysRun = m_setAlwaysRun; + cAgent.Appearance = new AvatarAppearance(m_appearance); + +/* try { // We might not pass the Wearables in all cases... @@ -3056,14 +2980,14 @@ namespace OpenSim.Region.Framework.Scenes { //m_log.DebugFormat("[SCENE PRESENCE]: attachments {0}", attPoints.Count); int i = 0; - AttachmentData[] attachs = new AttachmentData[attPoints.Count]; + AvatarAttachment[] attachs = new AvatarAttachment[attPoints.Count]; foreach (int point in attPoints) { - attachs[i++] = new AttachmentData(point, m_appearance.GetAttachedItem(point), m_appearance.GetAttachedAsset(point)); + attachs[i++] = new AvatarAttachment(point, m_appearance.GetAttachedItem(point), m_appearance.GetAttachedAsset(point)); } cAgent.Attachments = attachs; } - +*/ lock (scriptedcontrols) { ControllerData[] controls = new ControllerData[scriptedcontrols.Count]; @@ -3090,6 +3014,9 @@ namespace OpenSim.Region.Framework.Scenes public void CopyFrom(AgentData cAgent) { +// DEBUG ON + m_log.ErrorFormat("[SCENEPRESENCE] CALLING COPYFROM"); +// DEBUG OFF m_originRegionID = cAgent.RegionID; m_callbackURI = cAgent.CallbackURI; @@ -3115,6 +3042,9 @@ namespace OpenSim.Region.Framework.Scenes m_godLevel = cAgent.GodLevel; m_setAlwaysRun = cAgent.AlwaysRun; + m_appearance = new AvatarAppearance(cAgent.Appearance); + +/* uint i = 0; try { @@ -3127,15 +3057,17 @@ namespace OpenSim.Region.Framework.Scenes UUID assetId = cAgent.Wearables[n + 1]; wears[i++] = new AvatarWearable(itemId, assetId); } - m_appearance.Wearables = wears; - Primitive.TextureEntry te; + // m_appearance.Wearables = wears; + Primitive.TextureEntry textures = null; if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1) - te = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length); - else - te = AvatarAppearance.GetDefaultTexture(); - if ((cAgent.VisualParams == null) || (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT)) - cAgent.VisualParams = AvatarAppearance.GetDefaultVisualParams(); - m_appearance.SetAppearance(te, (byte[])cAgent.VisualParams.Clone()); + textures = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length); + + byte[] visuals = null; + + if ((cAgent.VisualParams != null) && (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT)) + visuals = (byte[])cAgent.VisualParams.Clone(); + + m_appearance = new AvatarAppearance(cAgent.AgentID,wears,textures,visuals); } catch (Exception e) { @@ -3148,14 +3080,14 @@ namespace OpenSim.Region.Framework.Scenes if (cAgent.Attachments != null) { m_appearance.ClearAttachments(); - foreach (AttachmentData att in cAgent.Attachments) + foreach (AvatarAttachment att in cAgent.Attachments) { m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID); } } } catch { } - +*/ try { lock (scriptedcontrols) @@ -3724,15 +3656,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/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 95908fc274..e661ca9da1 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -804,7 +804,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization private static void ProcessShpTextureEntry(PrimitiveBaseShape shp, XmlTextReader reader) { byte[] teData = Convert.FromBase64String(reader.ReadElementString("TextureEntry")); - shp.Textures = new Primitive.TextureEntry(teData, 0, teData.Length); + shp.Textures = new Primitive.TextureEntry(teData, 0, teData.Length); } private static void ProcessShpExtraParams(PrimitiveBaseShape shp, XmlTextReader reader) diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 159af79ace..fc17192b50 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -676,7 +676,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public event TeleportLandmarkRequest OnTeleportLandmarkRequest; public event DeRezObject OnDeRezObject; public event Action OnRegionHandShakeReply; - public event GenericCall2 OnRequestWearables; + public event GenericCall1 OnRequestWearables; public event GenericCall1 OnCompleteMovementToRegion; public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate; @@ -899,7 +899,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server Scene scene = (Scene)Scene; AvatarAppearance appearance; scene.GetAvatarAppearance(this, out appearance); - OnSetAppearance(appearance.Texture, (byte[])appearance.VisualParams.Clone()); + OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone()); } public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 25dba7f45e..3d34441a90 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -220,7 +220,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups groupID, groupMembers.Count); foreach (GroupMembersData member in groupMembers) - { + { if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) { // Don't deliver messages to people who have dropped this session @@ -266,7 +266,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups void OnClientLogin(IClientAPI client) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: OnInstantMessage registered for {0}", client.Name); + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: OnInstantMessage registered for {0}", client.Name); } private void OnNewClient(IClientAPI client) diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/ExtensionHandler.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/ExtensionHandler.cs index d8f7a84022..3f1bd54ee7 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/ExtensionHandler.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/ExtensionHandler.cs @@ -32,7 +32,7 @@ using OpenSim.Region.OptionalModules.Scripting.Minimodule.Interfaces; namespace OpenSim.Region.OptionalModules.Scripting.Minimodule { - class ExtensionHandler : IExtension + class ExtensionHandler : IExtension { private readonly Dictionary m_instances; diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs index 2ddc31bd07..df60709535 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs @@ -50,7 +50,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; - + private readonly Dictionary m_scripts = new Dictionary(); private readonly Dictionary m_extensions = new Dictionary(); @@ -77,7 +77,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule { m_log.Info("[MRM] Enabling MRM Module"); m_scene = scene; - + // when hidden, we don't listen for client initiated script events // only making the MRM engine available for region modules if (!source.Configs["MRM"].GetBoolean("Hidden", false)) @@ -85,7 +85,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule scene.EventManager.OnRezScript += EventManager_OnRezScript; scene.EventManager.OnStopScript += EventManager_OnStopScript; } - + scene.EventManager.OnFrame += EventManager_OnFrame; scene.RegisterModuleInterface(this); @@ -291,7 +291,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule public void InitializeMRM(MRMBase mmb, uint localID, UUID itemID) { - m_log.Info("[MRM] Created MRM Instance"); IWorld world; @@ -304,7 +303,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule public void PostInitialise() { - } public void Close() @@ -350,7 +348,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule if (!Directory.Exists(tmp)) Directory.CreateDirectory(tmp); - m_log.Info("MRM 2"); try @@ -396,8 +393,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule parameters.IncludeDebugInformation = true; - string rootPath = - Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory); + string rootPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory); List libraries = new List(); string[] lines = Script.Split(new string[] {"\n"}, StringSplitOptions.RemoveEmptyEntries); 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/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index fae12b6fc0..6928c4efbc 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -188,7 +188,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC public event DeRezObject OnDeRezObject; public event Action OnRegionHandShakeReply; - public event GenericCall2 OnRequestWearables; + public event GenericCall1 OnRequestWearables; public event GenericCall1 OnCompleteMovementToRegion; public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs index ab0be77715..c471636743 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs @@ -64,15 +64,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC if (m_appearanceCache.ContainsKey(target)) return m_appearanceCache[target]; - AvatarData adata = scene.AvatarService.GetAvatar(target); - if (adata != null) + AvatarAppearance appearance = scene.AvatarService.GetAppearance(target); + if (appearance != null) { - AvatarAppearance x = adata.ToAvatarAppearance(target); - - m_appearanceCache.Add(target, x); - - return x; + m_appearanceCache.Add(target, appearance); + return appearance; } + return new AvatarAppearance(); } @@ -169,7 +167,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC { AvatarAppearance x = GetAppearance(p_cloneAppearanceFrom, p_scene); - sp.SetAppearance(x.Texture, (byte[])x.VisualParams.Clone()); + sp.Appearance.SetTextureEntries(x.Texture); + sp.Appearance.SetVisualParams((byte[])x.VisualParams.Clone()); + sp.SendAppearanceToAllOtherAgents(); } m_avatars.Add(npcAvatar.AgentId, npcAvatar); diff --git a/OpenSim/Services/AvatarService/AvatarService.cs b/OpenSim/Services/AvatarService/AvatarService.cs index 19e662ca19..a8ad4130e5 100644 --- a/OpenSim/Services/AvatarService/AvatarService.cs +++ b/OpenSim/Services/AvatarService/AvatarService.cs @@ -51,6 +51,20 @@ namespace OpenSim.Services.AvatarService m_log.Debug("[AVATAR SERVICE]: Starting avatar service"); } + // Get|SetAppearance should preserve existing semantics + // until AvatarData can be removed completely + public AvatarAppearance GetAppearance(UUID principalID) + { + AvatarData avatar = GetAvatar(principalID); + return avatar.ToAvatarAppearance(principalID); + } + + public bool SetAppearance(UUID principalID, AvatarAppearance appearance) + { + AvatarData avatar = new AvatarData(appearance); + return SetAvatar(principalID,avatar); + } + public AvatarData GetAvatar(UUID principalID) { AvatarBaseData[] av = m_Database.Get("PrincipalID", principalID.ToString()); diff --git a/OpenSim/Services/Connectors/Avatar/AvatarServiceConnector.cs b/OpenSim/Services/Connectors/Avatar/AvatarServiceConnector.cs index 96c05a99f5..1cd6bf8e1a 100644 --- a/OpenSim/Services/Connectors/Avatar/AvatarServiceConnector.cs +++ b/OpenSim/Services/Connectors/Avatar/AvatarServiceConnector.cs @@ -87,6 +87,18 @@ namespace OpenSim.Services.Connectors #region IAvatarService + public AvatarAppearance GetAppearance(UUID userID) + { + AvatarData avatar = GetAvatar(userID); + return avatar.ToAvatarAppearance(userID); + } + + public bool SetAppearance(UUID userID, AvatarAppearance appearance) + { + AvatarData avatar = new AvatarData(appearance); + return SetAvatar(userID,avatar); + } + public AvatarData GetAvatar(UUID userID) { Dictionary sendData = new Dictionary(); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs index 4d0d53ec0b..ea9b4b430d 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs @@ -28,6 +28,9 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +// DEBUG ON +using System.Diagnostics; +// DEBUG OFF using System.Reflection; using log4net; using Mono.Addins; @@ -106,6 +109,80 @@ namespace OpenSim.Services.Connectors.SimianGrid #region IAvatarService + // + // Retrieves the LLPackedAppearance field from user data and unpacks + // it into an AvatarAppearance structure + // + // + public AvatarAppearance GetAppearance(UUID userID) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetUser" }, + { "UserID", userID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + { + OSDMap map = null; + try { map = OSDParser.DeserializeJson(response["LLPackedAppearance"].AsString()) as OSDMap; } + catch { } + + if (map != null) + { + AvatarAppearance appearance = new AvatarAppearance(map); +// DEBUG ON + m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR] retrieved appearance for {0}:\n{1}",userID,appearance.ToString()); +// DEBUG OFF + return appearance; + } + + m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR]: Failed to decode appearance for {0}",userID); + return null; + } + + m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR]: Failed to get appearance for {0}: {1}", + userID,response["Message"].AsString()); + return null; + } + + // + // + // + public bool SetAppearance(UUID userID, AvatarAppearance appearance) + { + OSDMap map = appearance.Pack(); + if (map == null) + { + m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR]: Failed to encode appearance for {0}",userID); + return false; + } + +// DEBUG ON + m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR] save appearance for {0}",userID); +// DEBUG OFF + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddUserData" }, + { "UserID", userID.ToString() }, + { "LLPackedAppearance", OSDParser.SerializeJsonString(map) } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (! success) + m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR]: Failed to save appearance for {0}: {1}", + userID,response["Message"].AsString()); + + return success; + } + + // + // + // public AvatarData GetAvatar(UUID userID) { NameValueCollection requestArgs = new NameValueCollection @@ -154,7 +231,7 @@ namespace OpenSim.Services.Connectors.SimianGrid foreach (KeyValuePair kvp in map) avatar.Data[kvp.Key] = kvp.Value.AsString(); } - + return avatar; } else @@ -173,6 +250,9 @@ namespace OpenSim.Services.Connectors.SimianGrid return null; } + // + // + // public bool SetAvatar(UUID userID, AvatarData avatar) { m_log.Debug("[SIMIAN AVATAR CONNECTOR]: SetAvatar called for " + userID); diff --git a/OpenSim/Services/Interfaces/IAvatarService.cs b/OpenSim/Services/Interfaces/IAvatarService.cs index de3bcf9679..eaa653439e 100644 --- a/OpenSim/Services/Interfaces/IAvatarService.cs +++ b/OpenSim/Services/Interfaces/IAvatarService.cs @@ -37,6 +37,21 @@ namespace OpenSim.Services.Interfaces { public interface IAvatarService { + /// + /// Called by the login service + /// + /// + /// + AvatarAppearance GetAppearance(UUID userID); + + /// + /// Called by everyone who can change the avatar data (so, regions) + /// + /// + /// + /// + bool SetAppearance(UUID userID, AvatarAppearance appearance); + /// /// Called by the login service /// @@ -163,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) @@ -217,23 +226,26 @@ namespace OpenSim.Services.Interfaces foreach (KeyValuePair _kvp in Data) if (_kvp.Key.StartsWith("_ap_")) attchs[_kvp.Key] = _kvp.Value; - Hashtable aaAttachs = new Hashtable(); + foreach (KeyValuePair _kvp in attchs) { string pointStr = _kvp.Key.Substring(4); int point = 0; if (!Int32.TryParse(pointStr, out point)) continue; - Hashtable tmp = new Hashtable(); + UUID uuid = UUID.Zero; UUID.TryParse(_kvp.Value, out uuid); - tmp["item"] = uuid; - tmp["asset"] = UUID.Zero.ToString(); - aaAttachs[point] = tmp; + + appearance.SetAttachment(point,uuid,UUID.Zero); } - appearance.SetAttachments(aaAttachs); } - catch { } + catch + { + // We really should report something here, returning null + // will at least break the wrapper + return null; + } return appearance; } diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index b0b51c48b8..f6ee9acda7 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -330,10 +330,10 @@ namespace OpenSim.Services.LLLoginService // // Get the avatar // - AvatarData avatar = null; + AvatarAppearance avatar = null; if (m_AvatarService != null) { - avatar = m_AvatarService.GetAvatar(account.PrincipalID); + avatar = m_AvatarService.GetAppearance(account.PrincipalID); } // @@ -602,7 +602,7 @@ namespace OpenSim.Services.LLLoginService } } - protected AgentCircuitData LaunchAgentAtGrid(GridRegion gatekeeper, GridRegion destination, UserAccount account, AvatarData avatar, + protected AgentCircuitData LaunchAgentAtGrid(GridRegion gatekeeper, GridRegion destination, UserAccount account, AvatarAppearance avatar, UUID session, UUID secureSession, Vector3 position, string currentWhere, string viewer, string channel, string mac, string id0, IPEndPoint clientIP, out string where, out string reason, out GridRegion dest) { @@ -696,14 +696,14 @@ namespace OpenSim.Services.LLLoginService } private AgentCircuitData MakeAgent(GridRegion region, UserAccount account, - AvatarData avatar, UUID session, UUID secureSession, uint circuit, Vector3 position, + AvatarAppearance avatar, UUID session, UUID secureSession, uint circuit, Vector3 position, string ipaddress, string viewer, string channel, string mac, string id0) { AgentCircuitData aCircuit = new AgentCircuitData(); aCircuit.AgentID = account.PrincipalID; if (avatar != null) - aCircuit.Appearance = avatar.ToAvatarAppearance(account.PrincipalID); + aCircuit.Appearance = new AvatarAppearance(avatar); else aCircuit.Appearance = new AvatarAppearance(account.PrincipalID); diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index e46f9b75ad..b2c8b35ec7 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -94,7 +94,7 @@ namespace OpenSim.Tests.Common.Mock public event DeRezObject OnDeRezObject; public event Action OnRegionHandShakeReply; - public event GenericCall2 OnRequestWearables; + public event GenericCall1 OnRequestWearables; public event GenericCall1 OnCompleteMovementToRegion; public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate; 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