/* * Copyright (c) 2006-2014, openmetaverse.org * All rights reserved. * * - Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * - Neither the name of the openmetaverse.org nor the names * of its contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Net; using System.Collections.Generic; using System.Threading; using OpenMetaverse.Packets; using OpenMetaverse.StructuredData; using System.Reflection; namespace OpenMetaverse { #region Enums /// /// Avatar profile flags /// [Flags] public enum ProfileFlags : uint { AllowPublish = 1, MaturePublish = 2, Identified = 4, Transacted = 8, Online = 16 } #endregion Enums /// /// Represents an avatar (other than your own) /// public class Avatar : Primitive { #region Subclasses /// /// Positive and negative ratings /// public struct Statistics { /// Positive ratings for Behavior public int BehaviorPositive; /// Negative ratings for Behavior public int BehaviorNegative; /// Positive ratings for Appearance public int AppearancePositive; /// Negative ratings for Appearance public int AppearanceNegative; /// Positive ratings for Building public int BuildingPositive; /// Negative ratings for Building public int BuildingNegative; /// Positive ratings given by this avatar public int GivenPositive; /// Negative ratings given by this avatar public int GivenNegative; public OSD GetOSD() { OSDMap tex = new OSDMap(8); tex["behavior_positive"] = OSD.FromInteger(BehaviorPositive); tex["behavior_negative"] = OSD.FromInteger(BehaviorNegative); tex["appearance_positive"] = OSD.FromInteger(AppearancePositive); tex["appearance_negative"] = OSD.FromInteger(AppearanceNegative); tex["buildings_positive"] = OSD.FromInteger(BuildingPositive); tex["buildings_negative"] = OSD.FromInteger(BuildingNegative); tex["given_positive"] = OSD.FromInteger(GivenPositive); tex["given_negative"] = OSD.FromInteger(GivenNegative); return tex; } public static Statistics FromOSD(OSD O) { Statistics S = new Statistics(); OSDMap tex = (OSDMap)O; S.BehaviorPositive = tex["behavior_positive"].AsInteger(); S.BuildingNegative = tex["behavior_negative"].AsInteger(); S.AppearancePositive = tex["appearance_positive"].AsInteger(); S.AppearanceNegative = tex["appearance_negative"].AsInteger(); S.BuildingPositive = tex["buildings_positive"].AsInteger(); S.BuildingNegative = tex["buildings_negative"].AsInteger(); S.GivenPositive = tex["given_positive"].AsInteger(); S.GivenNegative = tex["given_negative"].AsInteger(); return S; } } /// /// Avatar properties including about text, profile URL, image IDs and /// publishing settings /// public struct AvatarProperties { /// First Life about text public string FirstLifeText; /// First Life image ID public UUID FirstLifeImage; /// public UUID Partner; /// public string AboutText; /// public string BornOn; /// public string CharterMember; /// Profile image ID public UUID ProfileImage; /// Flags of the profile public ProfileFlags Flags; /// Web URL for this profile public string ProfileURL; #region Properties /// Should this profile be published on the web public bool AllowPublish { get { return ((Flags & ProfileFlags.AllowPublish) != 0); } set { if (value == true) Flags |= ProfileFlags.AllowPublish; else Flags &= ~ProfileFlags.AllowPublish; } } /// Avatar Online Status public bool Online { get { return ((Flags & ProfileFlags.Online) != 0); } set { if (value == true) Flags |= ProfileFlags.Online; else Flags &= ~ProfileFlags.Online; } } /// Is this a mature profile public bool MaturePublish { get { return ((Flags & ProfileFlags.MaturePublish) != 0); } set { if (value == true) Flags |= ProfileFlags.MaturePublish; else Flags &= ~ProfileFlags.MaturePublish; } } /// public bool Identified { get { return ((Flags & ProfileFlags.Identified) != 0); } set { if (value == true) Flags |= ProfileFlags.Identified; else Flags &= ~ProfileFlags.Identified; } } /// public bool Transacted { get { return ((Flags & ProfileFlags.Transacted) != 0); } set { if (value == true) Flags |= ProfileFlags.Transacted; else Flags &= ~ProfileFlags.Transacted; } } public OSD GetOSD() { OSDMap tex = new OSDMap(9); tex["first_life_text"] = OSD.FromString(FirstLifeText); tex["first_life_image"] = OSD.FromUUID(FirstLifeImage); tex["partner"] = OSD.FromUUID(Partner); tex["about_text"] = OSD.FromString(AboutText); tex["born_on"] = OSD.FromString(BornOn); tex["charter_member"] = OSD.FromString(CharterMember); tex["profile_image"] = OSD.FromUUID(ProfileImage); tex["flags"] = OSD.FromInteger((byte)Flags); tex["profile_url"] = OSD.FromString(ProfileURL); return tex; } public static AvatarProperties FromOSD(OSD O) { AvatarProperties A = new AvatarProperties(); OSDMap tex = (OSDMap)O; A.FirstLifeText = tex["first_life_text"].AsString(); A.FirstLifeImage = tex["first_life_image"].AsUUID(); A.Partner = tex["partner"].AsUUID(); A.AboutText = tex["about_text"].AsString(); A.BornOn = tex["born_on"].AsString(); A.CharterMember = tex["chart_member"].AsString(); A.ProfileImage = tex["profile_image"].AsUUID(); A.Flags = (ProfileFlags)tex["flags"].AsInteger(); A.ProfileURL = tex["profile_url"].AsString(); return A; } #endregion Properties } /// /// Avatar interests including spoken languages, skills, and "want to" /// choices /// public struct Interests { /// Languages profile field public string LanguagesText; /// // FIXME: public uint SkillsMask; /// public string SkillsText; /// // FIXME: public uint WantToMask; /// public string WantToText; public OSD GetOSD() { OSDMap InterestsOSD = new OSDMap(5); InterestsOSD["languages_text"] = OSD.FromString(LanguagesText); InterestsOSD["skills_mask"] = OSD.FromUInteger(SkillsMask); InterestsOSD["skills_text"] = OSD.FromString(SkillsText); InterestsOSD["want_to_mask"] = OSD.FromUInteger(WantToMask); InterestsOSD["want_to_text"] = OSD.FromString(WantToText); return InterestsOSD; } public static Interests FromOSD(OSD O) { Interests I = new Interests(); OSDMap tex = (OSDMap)O; I.LanguagesText = tex["languages_text"].AsString(); I.SkillsMask = tex["skills_mask"].AsUInteger(); I.SkillsText = tex["skills_text"].AsString(); I.WantToMask = tex["want_to_mask"].AsUInteger(); I.WantToText = tex["want_to_text"].AsString(); return I; } } #endregion Subclasses #region Public Members /// Groups that this avatar is a member of public List Groups = new List(); /// Positive and negative ratings public Statistics ProfileStatistics; /// Avatar properties including about text, profile URL, image IDs and /// publishing settings public AvatarProperties ProfileProperties; /// Avatar interests including spoken languages, skills, and "want to" /// choices public Interests ProfileInterests; /// Movement control flags for avatars. Typically not set or used by /// clients. To move your avatar, use Client.Self.Movement instead public AgentManager.ControlFlags ControlFlags; /// /// Contains the visual parameters describing the deformation of the avatar /// public byte[] VisualParameters = null; /// /// Appearance version. Value greater than 0 indicates using server side baking /// public byte AppearanceVersion = 0; /// /// Version of the Current Outfit Folder that the appearance is based on /// public int COFVersion = 0; /// /// Appearance flags. Introduced with server side baking, currently unused. /// public AppearanceFlags AppearanceFlags = AppearanceFlags.None; /// /// List of current avatar animations /// public List Animations; #endregion Public Members protected string name; protected string groupName; #region Properties /// First name public string FirstName { get { for (int i = 0; i < NameValues.Length; i++) { if (NameValues[i].Name == "FirstName" && NameValues[i].Type == NameValue.ValueType.String) return (string)NameValues[i].Value; } return String.Empty; } } /// Last name public string LastName { get { for (int i = 0; i < NameValues.Length; i++) { if (NameValues[i].Name == "LastName" && NameValues[i].Type == NameValue.ValueType.String) return (string)NameValues[i].Value; } return String.Empty; } } /// Full name public string Name { get { if (!String.IsNullOrEmpty(name)) { return name; } else if (NameValues != null && NameValues.Length > 0) { lock (NameValues) { string firstName = String.Empty; string lastName = String.Empty; for (int i = 0; i < NameValues.Length; i++) { if (NameValues[i].Name == "FirstName" && NameValues[i].Type == NameValue.ValueType.String) firstName = (string)NameValues[i].Value; else if (NameValues[i].Name == "LastName" && NameValues[i].Type == NameValue.ValueType.String) lastName = (string)NameValues[i].Value; } if (firstName != String.Empty && lastName != String.Empty) { name = String.Format("{0} {1}", firstName, lastName); return name; } else { return String.Empty; } } } else { return String.Empty; } } } /// Active group public string GroupName { get { if (!String.IsNullOrEmpty(groupName)) { return groupName; } else { if (NameValues == null || NameValues.Length == 0) { return String.Empty; } else { lock (NameValues) { for (int i = 0; i < NameValues.Length; i++) { if (NameValues[i].Name == "Title" && NameValues[i].Type == NameValue.ValueType.String) { groupName = (string)NameValues[i].Value; return groupName; } } } return String.Empty; } } } } public override OSD GetOSD() { OSDMap Avi = (OSDMap)base.GetOSD(); OSDArray grp = new OSDArray(); Groups.ForEach(delegate(UUID u) { grp.Add(OSD.FromUUID(u)); }); OSDArray vp = new OSDArray(); for (int i = 0; i < VisualParameters.Length; i++) { vp.Add(OSD.FromInteger(VisualParameters[i])); } Avi["groups"] = grp; Avi["profile_statistics"] = ProfileStatistics.GetOSD(); Avi["profile_properties"] = ProfileProperties.GetOSD(); Avi["profile_interest"] = ProfileInterests.GetOSD(); Avi["control_flags"] = OSD.FromInteger((byte)ControlFlags); Avi["visual_parameters"] = vp; Avi["first_name"] = OSD.FromString(FirstName); Avi["last_name"] = OSD.FromString(LastName); Avi["group_name"] = OSD.FromString(GroupName); return Avi; } public static new Avatar FromOSD(OSD O) { OSDMap tex = (OSDMap)O; Avatar A = new Avatar(); Primitive P = Primitive.FromOSD(O); Type Prim = typeof(Primitive); FieldInfo[] Fields = Prim.GetFields(); for (int x = 0; x < Fields.Length; x++) { Logger.Log("Field Matched in FromOSD: "+Fields[x].Name, Helpers.LogLevel.Debug); Fields[x].SetValue(A, Fields[x].GetValue(P)); } A.Groups = new List(); foreach (OSD U in (OSDArray)tex["groups"]) { A.Groups.Add(U.AsUUID()); } A.ProfileStatistics = Statistics.FromOSD(tex["profile_statistics"]); A.ProfileProperties = AvatarProperties.FromOSD(tex["profile_properties"]); A.ProfileInterests = Interests.FromOSD(tex["profile_interest"]); A.ControlFlags = (AgentManager.ControlFlags)tex["control_flags"].AsInteger(); OSDArray vp = (OSDArray)tex["visual_parameters"]; A.VisualParameters = new byte[vp.Count]; for (int i = 0; i < vp.Count; i++) { A.VisualParameters[i] = (byte)vp[i].AsInteger(); } // *********************From Code Above ******************************* /*if (NameValues[i].Name == "FirstName" && NameValues[i].Type == NameValue.ValueType.String) firstName = (string)NameValues[i].Value; else if (NameValues[i].Name == "LastName" && NameValues[i].Type == NameValue.ValueType.String) lastName = (string)NameValues[i].Value;*/ // ******************************************************************** A.NameValues = new NameValue[3]; NameValue First = new NameValue(); First.Name = "FirstName"; First.Type = NameValue.ValueType.String; First.Value = tex["first_name"].AsString(); NameValue Last = new NameValue(); Last.Name = "LastName"; Last.Type = NameValue.ValueType.String; Last.Value = tex["last_name"].AsString(); // ***************From Code Above*************** // if (NameValues[i].Name == "Title" && NameValues[i].Type == NameValue.ValueType.String) // ********************************************* NameValue Group = new NameValue(); Group.Name = "Title"; Group.Type = NameValue.ValueType.String; Group.Value = tex["group_name"].AsString(); A.NameValues[0] = First; A.NameValues[1] = Last; A.NameValues[2] = Group; return A; } #endregion Properties #region Constructors /// /// Default constructor /// public Avatar() { } #endregion Constructors } }