diff --git a/OpenMetaverse.StructuredData/JSON/JsonMapper.cs b/OpenMetaverse.StructuredData/JSON/JsonMapper.cs index 3240af70..263417e4 100644 --- a/OpenMetaverse.StructuredData/JSON/JsonMapper.cs +++ b/OpenMetaverse.StructuredData/JSON/JsonMapper.cs @@ -1,911 +1,901 @@ -#region Header -/* - * JsonMapper.cs - * JSON to .Net object and object to JSON conversions. - * - * The authors disclaim copyright to this source code. For more details, see - * the COPYING file included with this distribution. - */ -#endregion - - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Reflection; - - -namespace LitJson -{ - internal struct PropertyMetadata - { - public MemberInfo Info; - public bool IsField; - public Type Type; - } - - - internal struct ArrayMetadata - { - private Type element_type; - private bool is_array; - private bool is_list; - - - public Type ElementType { - get { - if (element_type == null) - return typeof (JsonData); - - return element_type; - } - - set { element_type = value; } - } - - public bool IsArray { - get { return is_array; } - set { is_array = value; } - } - - public bool IsList { - get { return is_list; } - set { is_list = value; } - } - } - - - internal struct ObjectMetadata - { - private Type element_type; - private bool is_dictionary; - - private IDictionary properties; - - - public Type ElementType { - get { - if (element_type == null) - return typeof (JsonData); - - return element_type; - } - - set { element_type = value; } - } - - public bool IsDictionary { - get { return is_dictionary; } - set { is_dictionary = value; } - } - - public IDictionary Properties { - get { return properties; } - set { properties = value; } - } - } - - - internal delegate void ExporterFunc (object obj, JsonWriter writer); - public delegate void ExporterFunc (T obj, JsonWriter writer); - - internal delegate object ImporterFunc (object input); - public delegate TValue ImporterFunc (TJson input); - - public delegate IJsonWrapper WrapperFactory (); - - - public class JsonMapper - { - #region Fields - private static int max_nesting_depth; - - private static IFormatProvider datetime_format; - - private static IDictionary base_exporters_table; - private static IDictionary custom_exporters_table; - - private static IDictionary> base_importers_table; - private static IDictionary> custom_importers_table; - - private static IDictionary array_metadata; - private static readonly object array_metadata_lock = new Object (); - - private static IDictionary> conv_ops; - private static readonly object conv_ops_lock = new Object (); - - private static IDictionary object_metadata; - private static readonly object object_metadata_lock = new Object (); - - private static IDictionary> type_properties; - private static readonly object type_properties_lock = new Object (); - - private static JsonWriter static_writer; - private static readonly object static_writer_lock = new Object (); - #endregion - - - #region Constructors - static JsonMapper () - { - max_nesting_depth = 100; - - array_metadata = new Dictionary (); - conv_ops = new Dictionary> (); - object_metadata = new Dictionary (); - type_properties = new Dictionary> (); - - static_writer = new JsonWriter (); - - datetime_format = DateTimeFormatInfo.InvariantInfo; - - base_exporters_table = new Dictionary (); - custom_exporters_table = new Dictionary (); - - base_importers_table = new Dictionary> (); - custom_importers_table = new Dictionary> (); - - RegisterBaseExporters (); - RegisterBaseImporters (); - } - #endregion - - - #region Private Methods - private static void AddArrayMetadata (Type type) - { - if (array_metadata.ContainsKey (type)) - return; - - ArrayMetadata data = new ArrayMetadata (); - - data.IsArray = type.IsArray; - - if (type.GetInterface ("System.Collections.IList") != null) - data.IsList = true; - - foreach (PropertyInfo p_info in type.GetProperties ()) { - if (p_info.Name != "Item") - continue; - - ParameterInfo[] parameters = p_info.GetIndexParameters (); - - if (parameters.Length != 1) - continue; - - if (parameters[0].ParameterType == typeof (int)) - data.ElementType = p_info.PropertyType; - } - - lock (array_metadata_lock) { - try { - array_metadata.Add (type, data); - } catch (ArgumentException) { - return; - } - } - } - - private static void AddObjectMetadata (Type type) - { - if (object_metadata.ContainsKey (type)) - return; - - ObjectMetadata data = new ObjectMetadata (); - - if (type.GetInterface ("System.Collections.IDictionary") != null) - data.IsDictionary = true; - - data.Properties = new Dictionary (); - - foreach (PropertyInfo p_info in type.GetProperties ()) { - if (p_info.Name == "Item") { - ParameterInfo[] parameters = p_info.GetIndexParameters (); - - if (parameters.Length != 1) - continue; - - if (parameters[0].ParameterType == typeof (string)) - data.ElementType = p_info.PropertyType; - - continue; - } - - PropertyMetadata p_data = new PropertyMetadata (); - p_data.Info = p_info; - p_data.Type = p_info.PropertyType; - - data.Properties.Add (p_info.Name, p_data); - } - - foreach (FieldInfo f_info in type.GetFields ()) { - PropertyMetadata p_data = new PropertyMetadata (); - p_data.Info = f_info; - p_data.IsField = true; - p_data.Type = f_info.FieldType; - - data.Properties.Add (f_info.Name, p_data); - } - - lock (object_metadata_lock) { - try { - object_metadata.Add (type, data); - } catch (ArgumentException) { - return; - } - } - } - - private static void AddTypeProperties (Type type) - { - if (type_properties.ContainsKey (type)) - return; - - IList props = new List (); - - foreach (PropertyInfo p_info in type.GetProperties ()) { - if (p_info.Name == "Item") - continue; - - PropertyMetadata p_data = new PropertyMetadata (); - p_data.Info = p_info; - p_data.IsField = false; - props.Add (p_data); - } - - foreach (FieldInfo f_info in type.GetFields ()) { - PropertyMetadata p_data = new PropertyMetadata (); - p_data.Info = f_info; - p_data.IsField = true; - - props.Add (p_data); - } - - lock (type_properties_lock) { - try { - type_properties.Add (type, props); - } catch (ArgumentException) { - return; - } - } - } - - private static MethodInfo GetConvOp (Type t1, Type t2) - { - lock (conv_ops_lock) { - if (! conv_ops.ContainsKey (t1)) - conv_ops.Add (t1, new Dictionary ()); - } - - if (conv_ops[t1].ContainsKey (t2)) - return conv_ops[t1][t2]; - - MethodInfo op = t1.GetMethod ( - "op_Implicit", new Type[] { t2 }); - - lock (conv_ops_lock) { - try { - conv_ops[t1].Add (t2, op); - } catch (ArgumentException) { - return conv_ops[t1][t2]; - } - } - - return op; - } - - private static object ReadValue (Type inst_type, JsonReader reader) - { - reader.Read (); - - if (reader.Token == JsonToken.ArrayEnd) - return null; - - if (reader.Token == JsonToken.Null) { - - if (! inst_type.IsClass) - throw new JsonException (String.Format ( - "Can't assign null to an instance of type {0}", - inst_type)); - - return null; - } - - if (reader.Token == JsonToken.Double || - reader.Token == JsonToken.Int || - reader.Token == JsonToken.Long || - reader.Token == JsonToken.String || - reader.Token == JsonToken.Boolean) { - - Type json_type = reader.Value.GetType (); - - if (inst_type.IsAssignableFrom (json_type)) - return reader.Value; - - // If there's a custom importer that fits, use it - if (custom_importers_table.ContainsKey (json_type) && - custom_importers_table[json_type].ContainsKey ( - inst_type)) { - - ImporterFunc importer = - custom_importers_table[json_type][inst_type]; - - return importer (reader.Value); - } - - // Maybe there's a base importer that works - if (base_importers_table.ContainsKey (json_type) && - base_importers_table[json_type].ContainsKey ( - inst_type)) { - - ImporterFunc importer = - base_importers_table[json_type][inst_type]; - - return importer (reader.Value); - } - - // Maybe it's an enum - if (inst_type.IsEnum) - return Enum.ToObject (inst_type, reader.Value); - - // Try using an implicit conversion operator - MethodInfo conv_op = GetConvOp (inst_type, json_type); - - if (conv_op != null) - return conv_op.Invoke (null, - new object[] { reader.Value }); - - // No luck - throw new JsonException (String.Format ( - "Can't assign value '{0}' (type {1}) to type {2}", - reader.Value, json_type, inst_type)); - } - - object instance = null; - - if (reader.Token == JsonToken.ArrayStart) { - - AddArrayMetadata (inst_type); - ArrayMetadata t_data = array_metadata[inst_type]; - - if (! t_data.IsArray && ! t_data.IsList) - throw new JsonException (String.Format ( - "Type {0} can't act as an array", - inst_type)); - - IList list; - Type elem_type; - - if (! t_data.IsArray) { - list = (IList) Activator.CreateInstance (inst_type); - elem_type = t_data.ElementType; - } else { - list = new ArrayList (); - elem_type = inst_type.GetElementType (); - } - - while (true) { - object item = ReadValue (elem_type, reader); - if (reader.Token == JsonToken.ArrayEnd) - break; - - list.Add (item); - } - - if (t_data.IsArray) { - int n = list.Count; - instance = Array.CreateInstance (elem_type, n); - - for (int i = 0; i < n; i++) - ((Array) instance).SetValue (list[i], i); - } else - instance = list; - - } else if (reader.Token == JsonToken.ObjectStart) { - - AddObjectMetadata (inst_type); - ObjectMetadata t_data = object_metadata[inst_type]; - - instance = Activator.CreateInstance (inst_type); - - while (true) { - reader.Read (); - - if (reader.Token == JsonToken.ObjectEnd) - break; - - string property = (string) reader.Value; - - if (t_data.Properties.ContainsKey (property)) { - PropertyMetadata prop_data = - t_data.Properties[property]; - - if (prop_data.IsField) { - ((FieldInfo) prop_data.Info).SetValue ( - instance, ReadValue (prop_data.Type, reader)); - } else { - PropertyInfo p_info = - (PropertyInfo) prop_data.Info; - - if (p_info.CanWrite) - p_info.SetValue ( - instance, - ReadValue (prop_data.Type, reader), - null); - else - ReadValue (prop_data.Type, reader); - } - - } else { - if (! t_data.IsDictionary) - throw new JsonException (String.Format ( - "The type {0} doesn't have the " + - "property '{1}'", inst_type, property)); - - ((IDictionary) instance).Add ( - property, ReadValue ( - t_data.ElementType, reader)); - } - - } - - } - - return instance; - } - - private static IJsonWrapper ReadValue (WrapperFactory factory, - JsonReader reader) - { - reader.Read (); - - if (reader.Token == JsonToken.ArrayEnd || - reader.Token == JsonToken.Null) - return null; - - IJsonWrapper instance = factory (); - - if (reader.Token == JsonToken.String) { - instance.SetString ((string) reader.Value); - return instance; - } - - if (reader.Token == JsonToken.Double) { - instance.SetDouble ((double) reader.Value); - return instance; - } - - if (reader.Token == JsonToken.Int) { - instance.SetInt ((int) reader.Value); - return instance; - } - - if (reader.Token == JsonToken.Long) { - instance.SetLong ((long) reader.Value); - return instance; - } - - if (reader.Token == JsonToken.Boolean) { - instance.SetBoolean ((bool) reader.Value); - return instance; - } - - if (reader.Token == JsonToken.ArrayStart) { - instance.SetJsonType (JsonType.Array); - - while (true) { - IJsonWrapper item = ReadValue (factory, reader); - if (reader.Token == JsonToken.ArrayEnd) - break; - - ((IList) instance).Add (item); - } - } - else if (reader.Token == JsonToken.ObjectStart) { - instance.SetJsonType (JsonType.Object); - - while (true) { - reader.Read (); - - if (reader.Token == JsonToken.ObjectEnd) - break; - - string property = (string) reader.Value; - - ((IDictionary) instance)[property] = ReadValue ( - factory, reader); - } - - } - - return instance; - } - - private static void RegisterBaseExporters () - { - base_exporters_table[typeof (byte)] = - delegate (object obj, JsonWriter writer) { - writer.Write (Convert.ToInt32 ((byte) obj)); - }; - - base_exporters_table[typeof (char)] = - delegate (object obj, JsonWriter writer) { - writer.Write (Convert.ToString ((char) obj)); - }; - - base_exporters_table[typeof (DateTime)] = - delegate (object obj, JsonWriter writer) { - writer.Write (Convert.ToString ((DateTime) obj, - datetime_format)); - }; - - base_exporters_table[typeof (decimal)] = - delegate (object obj, JsonWriter writer) { - writer.Write ((decimal) obj); - }; - - base_exporters_table[typeof (sbyte)] = - delegate (object obj, JsonWriter writer) { - writer.Write (Convert.ToInt32 ((sbyte) obj)); - }; - - base_exporters_table[typeof (short)] = - delegate (object obj, JsonWriter writer) { - writer.Write (Convert.ToInt32 ((short) obj)); - }; - - base_exporters_table[typeof (ushort)] = - delegate (object obj, JsonWriter writer) { - writer.Write (Convert.ToInt32 ((ushort) obj)); - }; - - base_exporters_table[typeof (uint)] = - delegate (object obj, JsonWriter writer) { - writer.Write (Convert.ToUInt64 ((uint) obj)); - }; - - base_exporters_table[typeof (ulong)] = - delegate (object obj, JsonWriter writer) { - writer.Write ((ulong) obj); - }; - } - - private static void RegisterBaseImporters () - { - ImporterFunc importer; - - importer = delegate (object input) { - return Convert.ToByte ((int) input); - }; - RegisterImporter (base_importers_table, typeof (int), - typeof (byte), importer); - - importer = delegate (object input) { - return Convert.ToUInt64 ((int) input); - }; - RegisterImporter (base_importers_table, typeof (int), - typeof (ulong), importer); - - importer = delegate (object input) { - return Convert.ToSByte ((int) input); - }; - RegisterImporter (base_importers_table, typeof (int), - typeof (sbyte), importer); - - importer = delegate (object input) { - return Convert.ToInt16 ((int) input); - }; - RegisterImporter (base_importers_table, typeof (int), - typeof (short), importer); - - importer = delegate (object input) { - return Convert.ToUInt16 ((int) input); - }; - RegisterImporter (base_importers_table, typeof (int), - typeof (ushort), importer); - - importer = delegate (object input) { - return Convert.ToUInt32 ((int) input); - }; - RegisterImporter (base_importers_table, typeof (int), - typeof (uint), importer); - - importer = delegate (object input) { - return Convert.ToSingle ((int) input); - }; - RegisterImporter (base_importers_table, typeof (int), - typeof (float), importer); - - importer = delegate (object input) { - return Convert.ToDouble ((int) input); - }; - RegisterImporter (base_importers_table, typeof (int), - typeof (double), importer); - - importer = delegate (object input) { - return Convert.ToDecimal ((double) input); - }; - RegisterImporter (base_importers_table, typeof (double), - typeof (decimal), importer); - - - importer = delegate (object input) { - return Convert.ToUInt32 ((long) input); - }; - RegisterImporter (base_importers_table, typeof (long), - typeof (uint), importer); - - importer = delegate (object input) { - return Convert.ToChar ((string) input); - }; - RegisterImporter (base_importers_table, typeof (string), - typeof (char), importer); - - importer = delegate (object input) { - return Convert.ToDateTime ((string) input, datetime_format); - }; - RegisterImporter (base_importers_table, typeof (string), - typeof (DateTime), importer); - } - - private static void RegisterImporter ( - IDictionary> table, - Type json_type, Type value_type, ImporterFunc importer) - { - if (! table.ContainsKey (json_type)) - table.Add (json_type, new Dictionary ()); - - table[json_type][value_type] = importer; - } - - private static void WriteValue (object obj, JsonWriter writer, - bool writer_is_private, - int depth) - { - if (depth > max_nesting_depth) - throw new JsonException ( - String.Format ("Max allowed object depth reached while " + - "trying to export from type {0}", - obj.GetType ())); - - if (obj == null) { - writer.Write (null); - return; - } - - if (obj is IJsonWrapper) { - if (writer_is_private) - writer.TextWriter.Write (((IJsonWrapper) obj).ToJson ()); - else - ((IJsonWrapper) obj).ToJson (writer); - - return; - } - - if (obj is String) { - writer.Write ((string) obj); - return; - } - - if (obj is Double) { - writer.Write ((double) obj); - return; - } - - if (obj is Int32) { - writer.Write ((int) obj); - return; - } - - if (obj is Boolean) { - writer.Write ((bool) obj); - return; - } - - if (obj is Int64) { - writer.Write ((long) obj); - return; - } - - if (obj is Array) { - writer.WriteArrayStart (); - - foreach (object elem in (Array) obj) - WriteValue (elem, writer, writer_is_private, depth + 1); - - writer.WriteArrayEnd (); - - return; - } - - if (obj is IList) { - writer.WriteArrayStart (); - foreach (object elem in (IList) obj) - WriteValue (elem, writer, writer_is_private, depth + 1); - writer.WriteArrayEnd (); - - return; - } - - if (obj is IDictionary) { - writer.WriteObjectStart (); - foreach (DictionaryEntry entry in (IDictionary) obj) { - writer.WritePropertyName ((string) entry.Key); - WriteValue (entry.Value, writer, writer_is_private, - depth + 1); - } - writer.WriteObjectEnd (); - - return; - } - - Type obj_type = obj.GetType (); - - // See if there's a custom exporter for the object - if (custom_exporters_table.ContainsKey (obj_type)) { - ExporterFunc exporter = custom_exporters_table[obj_type]; - exporter (obj, writer); - - return; - } - - // If not, maybe there's a base exporter - if (base_exporters_table.ContainsKey (obj_type)) { - ExporterFunc exporter = base_exporters_table[obj_type]; - exporter (obj, writer); - - return; - } - - // Last option, let's see if it's an enum - if (obj is Enum) { - Type e_type = Enum.GetUnderlyingType (obj_type); - - if (e_type == typeof (long) - || e_type == typeof (uint) - || e_type == typeof (ulong)) - writer.Write ((ulong) obj); - else - writer.Write ((int) obj); - - return; - } - - // Okay, so it looks like the input should be exported as an - // object - AddTypeProperties (obj_type); - IList props = type_properties[obj_type]; - - writer.WriteObjectStart (); - foreach (PropertyMetadata p_data in props) { - if (p_data.IsField) { - writer.WritePropertyName (p_data.Info.Name); - WriteValue (((FieldInfo) p_data.Info).GetValue (obj), - writer, writer_is_private, depth + 1); - } - else { - PropertyInfo p_info = (PropertyInfo) p_data.Info; - - if (p_info.CanRead) { - writer.WritePropertyName (p_data.Info.Name); - WriteValue (p_info.GetValue (obj, null), - writer, writer_is_private, depth + 1); - } - } - } - writer.WriteObjectEnd (); - } - #endregion - - - public static string ToJson (object obj) - { - lock (static_writer_lock) { - static_writer.Reset (); - - WriteValue (obj, static_writer, true, 0); - - return static_writer.ToString (); - } - } - - public static void ToJson (object obj, JsonWriter writer) - { - WriteValue (obj, writer, false, 0); - } - - public static JsonData ToObject (JsonReader reader) - { - return (JsonData) ToWrapper ( - delegate { return new JsonData (); }, reader); - } - - public static JsonData ToObject (TextReader reader) - { - JsonReader json_reader = new JsonReader (reader); - - return (JsonData) ToWrapper ( - delegate { return new JsonData (); }, json_reader); - } - - public static JsonData ToObject (string json) - { - return (JsonData) ToWrapper ( - delegate { return new JsonData (); }, json); - } - - public static T ToObject (JsonReader reader) - { - return (T) ReadValue (typeof (T), reader); - } - - public static T ToObject (TextReader reader) - { - JsonReader json_reader = new JsonReader (reader); - - return (T) ReadValue (typeof (T), json_reader); - } - - public static T ToObject (string json) - { - JsonReader reader = new JsonReader (json); - - return (T) ReadValue (typeof (T), reader); - } - - public static IJsonWrapper ToWrapper (WrapperFactory factory, - JsonReader reader) - { - return ReadValue (factory, reader); - } - - public static IJsonWrapper ToWrapper (WrapperFactory factory, - string json) - { - JsonReader reader = new JsonReader (json); - - return ReadValue (factory, reader); - } - - public static void RegisterExporter (ExporterFunc exporter) - { - ExporterFunc exporter_wrapper = - delegate (object obj, JsonWriter writer) { - exporter ((T) obj, writer); - }; - - custom_exporters_table[typeof (T)] = exporter_wrapper; - } - - public static void RegisterImporter ( - ImporterFunc importer) - { - ImporterFunc importer_wrapper = - delegate (object input) { - return importer ((TJson) input); - }; - - RegisterImporter (custom_importers_table, typeof (TJson), - typeof (TValue), importer_wrapper); - } - - public static void UnregisterExporters () - { - custom_exporters_table.Clear (); - } - - public static void UnregisterImporters () - { - custom_importers_table.Clear (); - } - } -} +#region Header +/* + * JsonMapper.cs + * JSON to .Net object and object to JSON conversions. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + */ +#endregion + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Reflection; + + +namespace LitJson +{ + internal struct PropertyMetadata + { + public MemberInfo Info; + public bool IsField; + public Type Type; + } + + + internal struct ArrayMetadata + { + private Type element_type; + private bool is_array; + private bool is_list; + + + public Type ElementType { + get { + if (element_type == null) + return typeof (JsonData); + + return element_type; + } + + set { element_type = value; } + } + + public bool IsArray { + get { return is_array; } + set { is_array = value; } + } + + public bool IsList { + get { return is_list; } + set { is_list = value; } + } + } + + + internal struct ObjectMetadata + { + private Type element_type; + private bool is_dictionary; + + private IDictionary properties; + + + public Type ElementType { + get { + if (element_type == null) + return typeof (JsonData); + + return element_type; + } + + set { element_type = value; } + } + + public bool IsDictionary { + get { return is_dictionary; } + set { is_dictionary = value; } + } + + public IDictionary Properties { + get { return properties; } + set { properties = value; } + } + } + + + internal delegate void ExporterFunc (object obj, JsonWriter writer); + public delegate void ExporterFunc (T obj, JsonWriter writer); + + internal delegate object ImporterFunc (object input); + public delegate TValue ImporterFunc (TJson input); + + public delegate IJsonWrapper WrapperFactory (); + + + public class JsonMapper + { + #region Fields + private static int max_nesting_depth; + + private static IFormatProvider datetime_format; + + private static IDictionary base_exporters_table; + private static IDictionary custom_exporters_table; + + private static IDictionary> base_importers_table; + private static IDictionary> custom_importers_table; + + private static IDictionary array_metadata; + private static readonly object array_metadata_lock = new Object (); + + private static IDictionary> conv_ops; + private static readonly object conv_ops_lock = new Object (); + + private static IDictionary object_metadata; + private static readonly object object_metadata_lock = new Object (); + + private static IDictionary> type_properties; + private static readonly object type_properties_lock = new Object (); + + private static JsonWriter static_writer; + private static readonly object static_writer_lock = new Object (); + #endregion + + + #region Constructors + static JsonMapper () + { + max_nesting_depth = 100; + + array_metadata = new Dictionary (); + conv_ops = new Dictionary> (); + object_metadata = new Dictionary (); + type_properties = new Dictionary> (); + + static_writer = new JsonWriter (); + + datetime_format = DateTimeFormatInfo.InvariantInfo; + + base_exporters_table = new Dictionary (); + custom_exporters_table = new Dictionary (); + + base_importers_table = new Dictionary> (); + custom_importers_table = new Dictionary> (); + + RegisterBaseExporters (); + RegisterBaseImporters (); + } + #endregion + + + #region Private Methods + private static void AddArrayMetadata (Type type) + { + if (array_metadata.ContainsKey (type)) + return; + + ArrayMetadata data = new ArrayMetadata (); + + data.IsArray = type.IsArray; + + if (type.GetInterface ("System.Collections.IList") != null) + data.IsList = true; + + foreach (PropertyInfo p_info in type.GetProperties ()) { + if (p_info.Name != "Item") + continue; + + ParameterInfo[] parameters = p_info.GetIndexParameters (); + + if (parameters.Length != 1) + continue; + + if (parameters[0].ParameterType == typeof (int)) + data.ElementType = p_info.PropertyType; + } + + lock (array_metadata_lock) { + try { + array_metadata.Add (type, data); + } catch (ArgumentException) { + return; + } + } + } + + private static void AddObjectMetadata (Type type) + { + if (object_metadata.ContainsKey (type)) + return; + + ObjectMetadata data = new ObjectMetadata (); + + if (type.GetInterface ("System.Collections.IDictionary") != null) + data.IsDictionary = true; + + data.Properties = new Dictionary (); + + foreach (PropertyInfo p_info in type.GetProperties ()) { + if (p_info.Name == "Item") { + ParameterInfo[] parameters = p_info.GetIndexParameters (); + + if (parameters.Length != 1) + continue; + + if (parameters[0].ParameterType == typeof (string)) + data.ElementType = p_info.PropertyType; + + continue; + } + + PropertyMetadata p_data = new PropertyMetadata (); + p_data.Info = p_info; + p_data.Type = p_info.PropertyType; + + data.Properties.Add (p_info.Name, p_data); + } + + foreach (FieldInfo f_info in type.GetFields ()) { + PropertyMetadata p_data = new PropertyMetadata (); + p_data.Info = f_info; + p_data.IsField = true; + p_data.Type = f_info.FieldType; + + data.Properties.Add (f_info.Name, p_data); + } + + lock (object_metadata_lock) { + try { + object_metadata.Add (type, data); + } catch (ArgumentException) { + return; + } + } + } + + private static void AddTypeProperties (Type type) + { + if (type_properties.ContainsKey (type)) + return; + + IList props = new List (); + + foreach (PropertyInfo p_info in type.GetProperties ()) { + if (p_info.Name == "Item") + continue; + + PropertyMetadata p_data = new PropertyMetadata (); + p_data.Info = p_info; + p_data.IsField = false; + props.Add (p_data); + } + + foreach (FieldInfo f_info in type.GetFields ()) { + PropertyMetadata p_data = new PropertyMetadata (); + p_data.Info = f_info; + p_data.IsField = true; + + props.Add (p_data); + } + + lock (type_properties_lock) { + try { + type_properties.Add (type, props); + } catch (ArgumentException) { + return; + } + } + } + + private static MethodInfo GetConvOp (Type t1, Type t2) + { + lock (conv_ops_lock) { + if (! conv_ops.ContainsKey (t1)) + conv_ops.Add (t1, new Dictionary ()); + } + + if (conv_ops[t1].ContainsKey (t2)) + return conv_ops[t1][t2]; + + MethodInfo op = t1.GetMethod ( + "op_Implicit", new Type[] { t2 }); + + lock (conv_ops_lock) { + try { + conv_ops[t1].Add (t2, op); + } catch (ArgumentException) { + return conv_ops[t1][t2]; + } + } + + return op; + } + + private static object ReadValue (Type inst_type, JsonReader reader) + { + reader.Read (); + + if (reader.Token == JsonToken.ArrayEnd) + return null; + + if (reader.Token == JsonToken.Null) { + + if (! inst_type.IsClass) + throw new JsonException (String.Format ( + "Can't assign null to an instance of type {0}", + inst_type)); + + return null; + } + + if (reader.Token == JsonToken.Double || + reader.Token == JsonToken.Int || + reader.Token == JsonToken.Long || + reader.Token == JsonToken.String || + reader.Token == JsonToken.Boolean) { + + Type json_type = reader.Value.GetType (); + + if (inst_type.IsAssignableFrom (json_type)) + return reader.Value; + + // If there's a custom importer that fits, use it + if (custom_importers_table.ContainsKey (json_type) && + custom_importers_table[json_type].ContainsKey ( + inst_type)) { + + ImporterFunc importer = + custom_importers_table[json_type][inst_type]; + + return importer (reader.Value); + } + + // Maybe there's a base importer that works + if (base_importers_table.ContainsKey (json_type) && + base_importers_table[json_type].ContainsKey ( + inst_type)) { + + ImporterFunc importer = + base_importers_table[json_type][inst_type]; + + return importer (reader.Value); + } + + // Maybe it's an enum + if (inst_type.IsEnum) + return Enum.ToObject (inst_type, reader.Value); + + // Try using an implicit conversion operator + MethodInfo conv_op = GetConvOp (inst_type, json_type); + + if (conv_op != null) + return conv_op.Invoke (null, + new object[] { reader.Value }); + + // No luck + throw new JsonException (String.Format ( + "Can't assign value '{0}' (type {1}) to type {2}", + reader.Value, json_type, inst_type)); + } + + object instance = null; + + if (reader.Token == JsonToken.ArrayStart) { + + AddArrayMetadata (inst_type); + ArrayMetadata t_data = array_metadata[inst_type]; + + if (! t_data.IsArray && ! t_data.IsList) + throw new JsonException (String.Format ( + "Type {0} can't act as an array", + inst_type)); + + IList list; + Type elem_type; + + if (! t_data.IsArray) { + list = (IList) Activator.CreateInstance (inst_type); + elem_type = t_data.ElementType; + } else { + list = new ArrayList (); + elem_type = inst_type.GetElementType (); + } + + while (true) { + object item = ReadValue (elem_type, reader); + if (reader.Token == JsonToken.ArrayEnd) + break; + + list.Add (item); + } + + if (t_data.IsArray) { + int n = list.Count; + instance = Array.CreateInstance (elem_type, n); + + for (int i = 0; i < n; i++) + ((Array) instance).SetValue (list[i], i); + } else + instance = list; + + } else if (reader.Token == JsonToken.ObjectStart) { + + AddObjectMetadata (inst_type); + ObjectMetadata t_data = object_metadata[inst_type]; + + instance = Activator.CreateInstance (inst_type); + + while (true) { + reader.Read (); + + if (reader.Token == JsonToken.ObjectEnd) + break; + + string property = (string) reader.Value; + + if (t_data.Properties.ContainsKey (property)) { + PropertyMetadata prop_data = + t_data.Properties[property]; + + if (prop_data.IsField) { + ((FieldInfo) prop_data.Info).SetValue ( + instance, ReadValue (prop_data.Type, reader)); + } else { + PropertyInfo p_info = + (PropertyInfo) prop_data.Info; + + if (p_info.CanWrite) + p_info.SetValue ( + instance, + ReadValue (prop_data.Type, reader), + null); + else + ReadValue (prop_data.Type, reader); + } + + } else { + if (! t_data.IsDictionary) + throw new JsonException (String.Format ( + "The type {0} doesn't have the " + + "property '{1}'", inst_type, property)); + + ((IDictionary) instance).Add ( + property, ReadValue ( + t_data.ElementType, reader)); + } + + } + + } + + return instance; + } + + private static IJsonWrapper ReadValue (WrapperFactory factory, + JsonReader reader) + { + reader.Read (); + + if (reader.Token == JsonToken.ArrayEnd || + reader.Token == JsonToken.Null) + return null; + + IJsonWrapper instance = factory (); + + switch (reader.Token) + { + case JsonToken.String: + instance.SetString ((string) reader.Value); + break; + case JsonToken.Double: + instance.SetDouble ((double) reader.Value); + break; + case JsonToken.Int: + instance.SetInt ((int) reader.Value); + break; + case JsonToken.Long: + instance.SetLong ((long) reader.Value); + break; + case JsonToken.Boolean: + instance.SetBoolean ((bool) reader.Value); + break; + case JsonToken.ArrayStart: + instance.SetJsonType (JsonType.Array); + + while (true) { + IJsonWrapper item = ReadValue (factory, reader); + if (reader.Token == JsonToken.ArrayEnd) + break; + + ((IList) instance).Add (item); + } + break; + case JsonToken.ObjectStart: + instance.SetJsonType (JsonType.Object); + + while (true) { + reader.Read (); + if (reader.Token == JsonToken.ObjectEnd) + break; + + string property = (string) reader.Value; + ((IDictionary) instance)[property] = ReadValue ( + factory, reader); + } + break; + } + + return instance; + } + + private static void RegisterBaseExporters () + { + base_exporters_table[typeof (byte)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((byte) obj)); + }; + + base_exporters_table[typeof (char)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToString ((char) obj)); + }; + + base_exporters_table[typeof (DateTime)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToString ((DateTime) obj, + datetime_format)); + }; + + base_exporters_table[typeof (decimal)] = + delegate (object obj, JsonWriter writer) { + writer.Write ((decimal) obj); + }; + + base_exporters_table[typeof (sbyte)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((sbyte) obj)); + }; + + base_exporters_table[typeof (short)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((short) obj)); + }; + + base_exporters_table[typeof (ushort)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((ushort) obj)); + }; + + base_exporters_table[typeof (uint)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToUInt64 ((uint) obj)); + }; + + base_exporters_table[typeof (ulong)] = + delegate (object obj, JsonWriter writer) { + writer.Write ((ulong) obj); + }; + } + + private static void RegisterBaseImporters () + { + ImporterFunc importer; + + importer = delegate (object input) { + return Convert.ToByte ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (byte), importer); + + importer = delegate (object input) { + return Convert.ToUInt64 ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (ulong), importer); + + importer = delegate (object input) { + return Convert.ToSByte ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (sbyte), importer); + + importer = delegate (object input) { + return Convert.ToInt16 ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (short), importer); + + importer = delegate (object input) { + return Convert.ToUInt16 ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (ushort), importer); + + importer = delegate (object input) { + return Convert.ToUInt32 ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (uint), importer); + + importer = delegate (object input) { + return Convert.ToSingle ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (float), importer); + + importer = delegate (object input) { + return Convert.ToDouble ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (double), importer); + + importer = delegate (object input) { + return Convert.ToDecimal ((double) input); + }; + RegisterImporter (base_importers_table, typeof (double), + typeof (decimal), importer); + + + importer = delegate (object input) { + return Convert.ToUInt32 ((long) input); + }; + RegisterImporter (base_importers_table, typeof (long), + typeof (uint), importer); + + importer = delegate (object input) { + return Convert.ToChar ((string) input); + }; + RegisterImporter (base_importers_table, typeof (string), + typeof (char), importer); + + importer = delegate (object input) { + return Convert.ToDateTime ((string) input, datetime_format); + }; + RegisterImporter (base_importers_table, typeof (string), + typeof (DateTime), importer); + } + + private static void RegisterImporter ( + IDictionary> table, + Type json_type, Type value_type, ImporterFunc importer) + { + if (! table.ContainsKey (json_type)) + table.Add (json_type, new Dictionary ()); + + table[json_type][value_type] = importer; + } + + private static void WriteValue (object obj, JsonWriter writer, + bool writer_is_private, + int depth) + { + if (depth > max_nesting_depth) + throw new JsonException ( + String.Format ("Max allowed object depth reached while " + + "trying to export from type {0}", + obj.GetType ())); + + if (obj == null) { + writer.Write (null); + return; + } + + if (obj is IJsonWrapper) { + if (writer_is_private) + writer.TextWriter.Write (((IJsonWrapper) obj).ToJson ()); + else + ((IJsonWrapper) obj).ToJson (writer); + + return; + } + + if (obj is String) { + writer.Write ((string) obj); + return; + } + + if (obj is Double) { + writer.Write ((double) obj); + return; + } + + if (obj is Int32) { + writer.Write ((int) obj); + return; + } + + if (obj is Boolean) { + writer.Write ((bool) obj); + return; + } + + if (obj is Int64) { + writer.Write ((long) obj); + return; + } + + if (obj is Array) { + writer.WriteArrayStart (); + + foreach (object elem in (Array) obj) + WriteValue (elem, writer, writer_is_private, depth + 1); + + writer.WriteArrayEnd (); + + return; + } + + if (obj is IList) { + writer.WriteArrayStart (); + foreach (object elem in (IList) obj) + WriteValue (elem, writer, writer_is_private, depth + 1); + writer.WriteArrayEnd (); + + return; + } + + if (obj is IDictionary) { + writer.WriteObjectStart (); + foreach (DictionaryEntry entry in (IDictionary) obj) { + writer.WritePropertyName ((string) entry.Key); + WriteValue (entry.Value, writer, writer_is_private, + depth + 1); + } + writer.WriteObjectEnd (); + + return; + } + + Type obj_type = obj.GetType (); + + // See if there's a custom exporter for the object + if (custom_exporters_table.ContainsKey (obj_type)) { + ExporterFunc exporter = custom_exporters_table[obj_type]; + exporter (obj, writer); + + return; + } + + // If not, maybe there's a base exporter + if (base_exporters_table.ContainsKey (obj_type)) { + ExporterFunc exporter = base_exporters_table[obj_type]; + exporter (obj, writer); + + return; + } + + // Last option, let's see if it's an enum + if (obj is Enum) { + Type e_type = Enum.GetUnderlyingType (obj_type); + + if (e_type == typeof (long) + || e_type == typeof (uint) + || e_type == typeof (ulong)) + writer.Write ((ulong) obj); + else + writer.Write ((int) obj); + + return; + } + + // Okay, so it looks like the input should be exported as an + // object + AddTypeProperties (obj_type); + IList props = type_properties[obj_type]; + + writer.WriteObjectStart (); + foreach (PropertyMetadata p_data in props) { + if (p_data.IsField) { + writer.WritePropertyName (p_data.Info.Name); + WriteValue (((FieldInfo) p_data.Info).GetValue (obj), + writer, writer_is_private, depth + 1); + } + else { + PropertyInfo p_info = (PropertyInfo) p_data.Info; + + if (p_info.CanRead) { + writer.WritePropertyName (p_data.Info.Name); + WriteValue (p_info.GetValue (obj, null), + writer, writer_is_private, depth + 1); + } + } + } + writer.WriteObjectEnd (); + } + #endregion + + + public static string ToJson (object obj) + { + lock (static_writer_lock) { + static_writer.Reset (); + + WriteValue (obj, static_writer, true, 0); + + return static_writer.ToString (); + } + } + + public static void ToJson (object obj, JsonWriter writer) + { + WriteValue (obj, writer, false, 0); + } + + public static JsonData ToObject (JsonReader reader) + { + return (JsonData) ToWrapper ( + delegate { return new JsonData (); }, reader); + } + + public static JsonData ToObject (TextReader reader) + { + JsonReader json_reader = new JsonReader (reader); + + return (JsonData) ToWrapper ( + delegate { return new JsonData (); }, json_reader); + } + + public static JsonData ToObject (string json) + { + return (JsonData) ToWrapper ( + delegate { return new JsonData (); }, json); + } + + public static T ToObject (JsonReader reader) + { + return (T) ReadValue (typeof (T), reader); + } + + public static T ToObject (TextReader reader) + { + JsonReader json_reader = new JsonReader (reader); + + return (T) ReadValue (typeof (T), json_reader); + } + + public static T ToObject (string json) + { + JsonReader reader = new JsonReader (json); + + return (T) ReadValue (typeof (T), reader); + } + + public static IJsonWrapper ToWrapper (WrapperFactory factory, + JsonReader reader) + { + return ReadValue (factory, reader); + } + + public static IJsonWrapper ToWrapper (WrapperFactory factory, + string json) + { + JsonReader reader = new JsonReader (json); + + return ReadValue (factory, reader); + } + + public static void RegisterExporter (ExporterFunc exporter) + { + ExporterFunc exporter_wrapper = + delegate (object obj, JsonWriter writer) { + exporter ((T) obj, writer); + }; + + custom_exporters_table[typeof (T)] = exporter_wrapper; + } + + public static void RegisterImporter ( + ImporterFunc importer) + { + ImporterFunc importer_wrapper = + delegate (object input) { + return importer ((TJson) input); + }; + + RegisterImporter (custom_importers_table, typeof (TJson), + typeof (TValue), importer_wrapper); + } + + public static void UnregisterExporters () + { + custom_exporters_table.Clear (); + } + + public static void UnregisterImporters () + { + custom_importers_table.Clear (); + } + } +} diff --git a/OpenMetaverse/Assets/Archiving/OarFile.cs b/OpenMetaverse/Assets/Archiving/OarFile.cs index 727ec4ff..fabac890 100644 --- a/OpenMetaverse/Assets/Archiving/OarFile.cs +++ b/OpenMetaverse/Assets/Archiving/OarFile.cs @@ -36,53 +36,57 @@ namespace OpenMetaverse.Assets { public static class OarFile { - public delegate void AssetLoadedCallback(Asset asset); - public delegate void TerrainLoadedCallback(float[,] terrain); + public delegate void AssetLoadedCallback(Asset asset, long bytesRead, long totalBytes); + public delegate void TerrainLoadedCallback(float[,] terrain, long bytesRead, long totalBytes); + public delegate void SceneObjectLoadedCallback(AssetPrim linkset, long bytesRead, long totalBytes); #region Archive Loading - public static void UnpackageArchive(string filename, AssetLoadedCallback assetCallback, TerrainLoadedCallback terrainCallback) + public static void UnpackageArchive(string filename, AssetLoadedCallback assetCallback, TerrainLoadedCallback terrainCallback, SceneObjectLoadedCallback objectCallback) { int successfulAssetRestores = 0; int failedAssetRestores = 0; - List serialisedSceneObjects = new List(); try { - using (Stream loadStream = new GZipStream(new FileStream(filename, FileMode.Open, FileAccess.Read), CompressionMode.Decompress)) + using (FileStream fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read)) { - TarArchiveReader archive = new TarArchiveReader(loadStream); - - string filePath = "ERROR"; - - byte[] data; - TarArchiveReader.TarEntryType entryType; - - while ((data = archive.ReadEntry(out filePath, out entryType)) != null) + using (GZipStream loadStream = new GZipStream(fileStream, CompressionMode.Decompress)) { - if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) - { - serialisedSceneObjects.Add(data); - } - else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) - { - if (LoadAsset(filePath, data, assetCallback)) - successfulAssetRestores++; - else - failedAssetRestores++; - } - else if (filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) - { - LoadTerrain(filePath, data, terrainCallback); - } - else if (filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) - { - // FIXME: Support this - //LoadRegionSettings(filePath, data); - } - } + TarArchiveReader archive = new TarArchiveReader(loadStream); - archive.Close(); + string filePath = "ERROR"; + + byte[] data; + TarArchiveReader.TarEntryType entryType; + + while ((data = archive.ReadEntry(out filePath, out entryType)) != null) + { + if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) + { + // Deserialize the XML bytes + LoadObjects(data, objectCallback, fileStream.Position, fileStream.Length); + } + else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) + { + if (LoadAsset(filePath, data, assetCallback, fileStream.Position, fileStream.Length)) + successfulAssetRestores++; + else + failedAssetRestores++; + } + else if (filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) + { + LoadTerrain(filePath, data, terrainCallback, fileStream.Position, fileStream.Length); + } + else if (filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) + { + // FIXME: Support this + //LoadRegionSettings(filePath, data); + } + } + + archive.Close(); + } } } catch (Exception e) @@ -93,17 +97,9 @@ namespace OpenMetaverse.Assets if (failedAssetRestores > 0) Logger.Log(String.Format("[OarFile]: Failed to load {0} assets", failedAssetRestores), Helpers.LogLevel.Warning); - - for (int i = 0; i < serialisedSceneObjects.Count; i++) - { - byte[] objectData = serialisedSceneObjects[i]; - - // Deserialize the XML bytes - LoadObjects(objectData, assetCallback); - } } - private static bool LoadAsset(string assetPath, byte[] data, AssetLoadedCallback assetCallback) + private static bool LoadAsset(string assetPath, byte[] data, AssetLoadedCallback assetCallback, long bytesRead, long totalBytes) { // Right now we're nastily obtaining the UUID from the filename string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); @@ -137,6 +133,12 @@ namespace OpenMetaverse.Assets case AssetType.Clothing: asset = new AssetClothing(uuid, data); break; + case AssetType.Gesture: + asset = new AssetGesture(uuid, data); + break; + case AssetType.Landmark: + asset = new AssetLandmark(uuid, data); + break; case AssetType.LSLBytecode: asset = new AssetScriptBinary(uuid, data); break; @@ -146,6 +148,9 @@ namespace OpenMetaverse.Assets case AssetType.Notecard: asset = new AssetNotecard(uuid, data); break; + case AssetType.Object: + asset = new AssetPrim(uuid, data); + break; case AssetType.Sound: asset = new AssetSound(uuid, data); break; @@ -159,7 +164,7 @@ namespace OpenMetaverse.Assets if (asset != null) { - assetCallback(asset); + assetCallback(asset, bytesRead, totalBytes); return true; } } @@ -168,7 +173,7 @@ namespace OpenMetaverse.Assets return false; } - private static bool LoadTerrain(string filePath, byte[] data, TerrainLoadedCallback terrainCallback) + private static bool LoadTerrain(string filePath, byte[] data, TerrainLoadedCallback terrainCallback, long bytesRead, long totalBytes) { float[,] terrain = new float[256, 256]; bool loaded = false; @@ -220,14 +225,13 @@ namespace OpenMetaverse.Assets } if (loaded) - terrainCallback(terrain); + terrainCallback(terrain, bytesRead, totalBytes); return loaded; } - private static void LoadObjects(byte[] objectData, AssetLoadedCallback assetCallback) + private static void LoadObjects(byte[] objectData, SceneObjectLoadedCallback objectCallback, long bytesRead, long totalBytes) { - // TODO: If we can get by without XmlDocument it will fix the memory problems when loading large XML files XmlDocument doc = new XmlDocument(); using (XmlTextReader reader = new XmlTextReader(new MemoryStream(objectData))) @@ -244,14 +248,14 @@ namespace OpenMetaverse.Assets { AssetPrim linkset = new AssetPrim(node.OuterXml); if (linkset != null) - assetCallback(linkset); + objectCallback(linkset, bytesRead, totalBytes); } } else { AssetPrim linkset = new AssetPrim(rootNode.OuterXml); if (linkset != null) - assetCallback(linkset); + objectCallback(linkset, bytesRead, totalBytes); } } diff --git a/OpenMetaverse/Assets/AssetTypes/AssetPrim.cs b/OpenMetaverse/Assets/AssetTypes/AssetPrim.cs index 61a9962a..77c7bd81 100644 --- a/OpenMetaverse/Assets/AssetTypes/AssetPrim.cs +++ b/OpenMetaverse/Assets/AssetTypes/AssetPrim.cs @@ -60,6 +60,13 @@ namespace OpenMetaverse.Assets /// Initializes a new instance of an AssetPrim object public AssetPrim() { } + /// + /// Initializes a new instance of an AssetPrim object + /// + /// A unique specific to this asset + /// A byte array containing the raw asset data + public AssetPrim(UUID assetID, byte[] assetData) : base(assetID, assetData) { } + public AssetPrim(string xmlData) { DecodeXml(xmlData); @@ -79,7 +86,7 @@ namespace OpenMetaverse.Assets /// public override void Encode() { - // FIXME: + AssetData = System.Text.Encoding.UTF8.GetBytes(EncodeXml()); } /// @@ -88,7 +95,17 @@ namespace OpenMetaverse.Assets /// public override bool Decode() { - // FIXME: + if (AssetData != null && AssetData.Length > 0) + { + try + { + string xmlData = System.Text.Encoding.UTF8.GetString(AssetData); + DecodeXml(xmlData); + return true; + } + catch { } + } + return false; } @@ -168,10 +185,49 @@ namespace OpenMetaverse.Assets obj.CreatorID = ReadUUID(reader, "CreatorID"); obj.FolderID = ReadUUID(reader, "FolderID"); obj.Inventory.Serial = reader.ReadElementContentAsInt("InventorySerial", String.Empty); - - // FIXME: Parse TaskInventory - obj.Inventory.Items = new PrimObject.InventoryBlock.ItemBlock[0]; - reader.ReadInnerXml(); + + #region Task Inventory + + List invItems = new List(); + + reader.ReadStartElement("TaskInventory", String.Empty); + while (reader.Name == "TaskInventoryItem") + { + PrimObject.InventoryBlock.ItemBlock item = new PrimObject.InventoryBlock.ItemBlock(); + reader.ReadStartElement("TaskInventoryItem", String.Empty); + + item.AssetID = ReadUUID(reader, "AssetID"); + item.PermsBase = (uint)reader.ReadElementContentAsInt("BasePermissions", String.Empty); + item.CreationDate = Utils.UnixTimeToDateTime((uint)reader.ReadElementContentAsInt("CreationDate", String.Empty)); + item.CreatorID = ReadUUID(reader, "CreatorID"); + item.Description = reader.ReadElementContentAsString("Description", String.Empty); + item.PermsEveryone = (uint)reader.ReadElementContentAsInt("EveryonePermissions", String.Empty); + item.Flags = reader.ReadElementContentAsInt("Flags", String.Empty); + item.GroupID = ReadUUID(reader, "GroupID"); + item.PermsGroup = (uint)reader.ReadElementContentAsInt("GroupPermissions", String.Empty); + item.InvType = (InventoryType)reader.ReadElementContentAsInt("InvType", String.Empty); + item.ID = ReadUUID(reader, "ItemID"); + UUID oldItemID = ReadUUID(reader, "OldItemID"); // TODO: Is this useful? + item.LastOwnerID = ReadUUID(reader, "LastOwnerID"); + item.Name = reader.ReadElementContentAsString("Name", String.Empty); + item.PermsNextOwner = (uint)reader.ReadElementContentAsInt("NextPermissions", String.Empty); + item.OwnerID = ReadUUID(reader, "OwnerID"); + item.PermsOwner = (uint)reader.ReadElementContentAsInt("CurrentPermissions", String.Empty); + UUID parentID = ReadUUID(reader, "ParentID"); + UUID parentPartID = ReadUUID(reader, "ParentPartID"); + item.PermsGranterID = ReadUUID(reader, "PermsGranter"); + item.PermsBase = (uint)reader.ReadElementContentAsInt("PermsMask", String.Empty); + item.Type = (AssetType)reader.ReadElementContentAsInt("Type", String.Empty); + + reader.ReadEndElement(); + invItems.Add(item); + } + if (reader.NodeType == XmlNodeType.EndElement) + reader.ReadEndElement(); + + obj.Inventory.Items = invItems.ToArray(); + + #endregion Task Inventory PrimFlags flags = (PrimFlags)reader.ReadElementContentAsInt("ObjectFlags", String.Empty); obj.UsePhysics = (flags & PrimFlags.Physics) != 0; @@ -185,16 +241,20 @@ namespace OpenMetaverse.Assets obj.LocalID = (uint)reader.ReadElementContentAsLong("LocalId", String.Empty); obj.Name = reader.ReadElementString("Name"); obj.Material = reader.ReadElementContentAsInt("Material", String.Empty); - - reader.ReadInnerXml(); // RegionHandle + if (reader.Name == "PassTouches") + obj.PassTouches = reader.ReadElementContentAsBoolean("PassTouches", String.Empty); + else + obj.PassTouches = false; + + obj.RegionHandle = (ulong)reader.ReadElementContentAsLong("RegionHandle", String.Empty); obj.RemoteScriptAccessPIN = reader.ReadElementContentAsInt("ScriptAccessPin", String.Empty); - Vector3 groupPosition = ReadVector(reader, "GroupPosition"); Vector3 offsetPosition = ReadVector(reader, "OffsetPosition"); obj.Rotation = ReadQuaternion(reader, "RotationOffset"); obj.Velocity = ReadVector(reader, "Velocity"); - Vector3 rotationalVelocity = ReadVector(reader, "RotationalVelocity"); + if (reader.Name == "RotationalVelocity") + ReadVector(reader, "RotationalVelocity"); obj.AngularVelocity = ReadVector(reader, "AngularVelocity"); obj.Acceleration = ReadVector(reader, "Acceleration"); obj.Description = reader.ReadElementString("Description"); @@ -609,19 +669,20 @@ namespace OpenMetaverse.Assets { public UUID ID; public string Name; - public string OwnerIdentity; - public string CreatorIdentity; - public string GroupIdentity; + public UUID OwnerID; + public UUID CreatorID; + public UUID GroupID; + public UUID LastOwnerID; + public UUID PermsGranterID; public UUID AssetID; - public string ContentType; + public AssetType Type; + public InventoryType InvType; public string Description; public uint PermsBase; public uint PermsOwner; public uint PermsGroup; public uint PermsEveryone; public uint PermsNextOwner; - public int SalePrice; - public int SaleType; public int Flags; public DateTime CreationDate; @@ -630,19 +691,20 @@ namespace OpenMetaverse.Assets OSDMap map = new OSDMap(); map["id"] = OSD.FromUUID(ID); map["name"] = OSD.FromString(Name); - map["owner_identity"] = OSD.FromString(OwnerIdentity); - map["creator_identity"] = OSD.FromString(CreatorIdentity); - map["group_identity"] = OSD.FromString(GroupIdentity); + map["owner_id"] = OSD.FromUUID(OwnerID); + map["creator_id"] = OSD.FromUUID(CreatorID); + map["group_id"] = OSD.FromUUID(GroupID); + map["last_owner_id"] = OSD.FromUUID(LastOwnerID); + map["perms_granter_id"] = OSD.FromUUID(PermsGranterID); map["asset_id"] = OSD.FromUUID(AssetID); - map["content_type"] = OSD.FromString(ContentType); + map["asset_type"] = OSD.FromInteger((int)Type); + map["inv_type"] = OSD.FromInteger((int)InvType); map["description"] = OSD.FromString(Description); map["perms_base"] = OSD.FromInteger(PermsBase); map["perms_owner"] = OSD.FromInteger(PermsOwner); map["perms_group"] = OSD.FromInteger(PermsGroup); map["perms_everyone"] = OSD.FromInteger(PermsEveryone); map["perms_next_owner"] = OSD.FromInteger(PermsNextOwner); - map["sale_price"] = OSD.FromInteger(SalePrice); - map["sale_type"] = OSD.FromInteger(SaleType); map["flags"] = OSD.FromInteger(Flags); map["creation_date"] = OSD.FromDate(CreationDate); return map; @@ -652,19 +714,20 @@ namespace OpenMetaverse.Assets { ID = map["id"].AsUUID(); Name = map["name"].AsString(); - OwnerIdentity = map["owner_identity"].AsString(); - CreatorIdentity = map["creator_identity"].AsString(); - GroupIdentity = map["group_identity"].AsString(); + OwnerID = map["owner_id"].AsUUID(); + CreatorID = map["creator_id"].AsUUID(); + GroupID = map["group_id"].AsUUID(); + LastOwnerID = map["last_owner_id"].AsUUID(); + PermsGranterID = map["perms_granter_id"].AsUUID(); AssetID = map["asset_id"].AsUUID(); - ContentType = map["content_type"].AsString(); + Type = (AssetType)map["asset_type"].AsInteger(); + InvType = (InventoryType)map["inv_type"].AsInteger(); Description = map["description"].AsString(); PermsBase = (uint)map["perms_base"].AsInteger(); PermsOwner = (uint)map["perms_owner"].AsInteger(); PermsGroup = (uint)map["perms_group"].AsInteger(); PermsEveryone = (uint)map["perms_everyone"].AsInteger(); PermsNextOwner = (uint)map["perms_next_owner"].AsInteger(); - SalePrice = map["sale_price"].AsInteger(); - SaleType = map["sale_type"].AsInteger(); Flags = map["flags"].AsInteger(); CreationDate = map["creation_date"].AsDate(); } @@ -748,6 +811,7 @@ namespace OpenMetaverse.Assets public int State; public int PCode; public int Material; + public bool PassTouches; public UUID SoundID; public float SoundGain; public float SoundRadius; @@ -819,6 +883,7 @@ namespace OpenMetaverse.Assets map["state"] = OSD.FromInteger(State); map["prim_code"] = OSD.FromInteger(PCode); map["material"] = OSD.FromInteger(Material); + map["pass_touches"] = OSD.FromBoolean(PassTouches); map["sound_id"] = OSD.FromUUID(SoundID); map["sound_gain"] = OSD.FromReal(SoundGain); map["sound_radius"] = OSD.FromReal(SoundRadius); @@ -897,6 +962,7 @@ namespace OpenMetaverse.Assets State = map["state"].AsInteger(); PCode = map["prim_code"].AsInteger(); Material = map["material"].AsInteger(); + PassTouches = map["pass_touches"].AsBoolean(); SoundID = map["sound_id"].AsUUID(); SoundGain = (float)map["sound_gain"].AsReal(); SoundRadius = (float)map["sound_radius"].AsReal(); diff --git a/OpenMetaverse/Messages/LindenMessages.cs b/OpenMetaverse/Messages/LindenMessages.cs index 27296e21..4c807ef7 100644 --- a/OpenMetaverse/Messages/LindenMessages.cs +++ b/OpenMetaverse/Messages/LindenMessages.cs @@ -1100,13 +1100,16 @@ namespace OpenMetaverse.Messages.Linden #region Inventory Messages - public class NewFileAgentInventoryMessage + public class NewFileAgentInventoryMessage : IMessage { public UUID FolderID; public AssetType AssetType; public InventoryType InventoryType; public string Name; public string Description; + public PermissionMask EveryoneMask; + public PermissionMask GroupMask; + public PermissionMask NextOwnerMask; /// /// Serialize the object @@ -1120,6 +1123,9 @@ namespace OpenMetaverse.Messages.Linden map["inventory_type"] = OSD.FromString(Utils.InventoryTypeToString(InventoryType)); map["name"] = OSD.FromString(Name); map["description"] = OSD.FromString(Description); + map["everyone_mask"] = OSD.FromInteger((int)EveryoneMask); + map["group_mask"] = OSD.FromInteger((int)GroupMask); + map["next_owner_mask"] = OSD.FromInteger((int)NextOwnerMask); return map; } @@ -1135,9 +1141,158 @@ namespace OpenMetaverse.Messages.Linden InventoryType = Utils.StringToInventoryType(map["inventory_type"].AsString()); Name = map["name"].AsString(); Description = map["description"].AsString(); + EveryoneMask = (PermissionMask)map["everyone_mask"].AsInteger(); + GroupMask = (PermissionMask)map["group_mask"].AsInteger(); + NextOwnerMask = (PermissionMask)map["next_owner_mask"].AsInteger(); } } + public class NewFileAgentInventoryReplyMessage : IMessage + { + public string State; + public Uri Uploader; + + public NewFileAgentInventoryReplyMessage() + { + State = "upload"; + } + + public OSDMap Serialize() + { + OSDMap map = new OSDMap(); + map["state"] = OSD.FromString(State); + map["uploader"] = OSD.FromUri(Uploader); + + return map; + } + + public void Deserialize(OSDMap map) + { + State = map["state"].AsString(); + Uploader = map["uploader"].AsUri(); + } + } + + public class NewFileAgentInventoryVariablePriceMessage : IMessage + { + public UUID FolderID; + public AssetType AssetType; + public InventoryType InventoryType; + public string Name; + public string Description; + public PermissionMask EveryoneMask; + public PermissionMask GroupMask; + public PermissionMask NextOwnerMask; + // TODO: asset_resources? + + /// + /// Serialize the object + /// + /// An containing the objects data + public OSDMap Serialize() + { + OSDMap map = new OSDMap(); + map["folder_id"] = OSD.FromUUID(FolderID); + map["asset_type"] = OSD.FromString(Utils.AssetTypeToString(AssetType)); + map["inventory_type"] = OSD.FromString(Utils.InventoryTypeToString(InventoryType)); + map["name"] = OSD.FromString(Name); + map["description"] = OSD.FromString(Description); + map["everyone_mask"] = OSD.FromInteger((int)EveryoneMask); + map["group_mask"] = OSD.FromInteger((int)GroupMask); + map["next_owner_mask"] = OSD.FromInteger((int)NextOwnerMask); + + return map; + } + + /// + /// Deserialize the message + /// + /// An containing the data + public void Deserialize(OSDMap map) + { + FolderID = map["folder_id"].AsUUID(); + AssetType = Utils.StringToAssetType(map["asset_type"].AsString()); + InventoryType = Utils.StringToInventoryType(map["inventory_type"].AsString()); + Name = map["name"].AsString(); + Description = map["description"].AsString(); + EveryoneMask = (PermissionMask)map["everyone_mask"].AsInteger(); + GroupMask = (PermissionMask)map["group_mask"].AsInteger(); + NextOwnerMask = (PermissionMask)map["next_owner_mask"].AsInteger(); + } + } + + public class NewFileAgentInventoryVariablePriceReplyMessage : IMessage + { + public int ResourceCost; + public string State; + public int UploadPrice; + public Uri Rsvp; + + public NewFileAgentInventoryVariablePriceReplyMessage() + { + State = "confirm_upload"; + } + + public OSDMap Serialize() + { + OSDMap map = new OSDMap(); + map["resource_cost"] = OSD.FromInteger(ResourceCost); + map["state"] = OSD.FromString(State); + map["upload_price"] = OSD.FromInteger(UploadPrice); + map["rsvp"] = OSD.FromUri(Rsvp); + + return map; + } + + public void Deserialize(OSDMap map) + { + ResourceCost = map["resource_cost"].AsInteger(); + State = map["state"].AsString(); + UploadPrice = map["upload_price"].AsInteger(); + Rsvp = map["rsvp"].AsUri(); + } + } + + public class NewFileAgentInventoryUploadReplyMessage : IMessage + { + public UUID NewInventoryItem; + public UUID NewAsset; + public string State; + public PermissionMask NewBaseMask; + public PermissionMask NewEveryoneMask; + public PermissionMask NewOwnerMask; + public PermissionMask NewNextOwnerMask; + + public NewFileAgentInventoryUploadReplyMessage() + { + State = "complete"; + } + + public OSDMap Serialize() + { + OSDMap map = new OSDMap(); + map["new_inventory_item"] = OSD.FromUUID(NewInventoryItem); + map["new_asset"] = OSD.FromUUID(NewAsset); + map["state"] = OSD.FromString(State); + map["new_base_mask"] = OSD.FromInteger((int)NewBaseMask); + map["new_everyone_mask"] = OSD.FromInteger((int)NewEveryoneMask); + map["new_owner_mask"] = OSD.FromInteger((int)NewOwnerMask); + map["new_next_owner_mask"] = OSD.FromInteger((int)NewNextOwnerMask); + + return map; + } + + public void Deserialize(OSDMap map) + { + NewInventoryItem = map["new_inventory_item"].AsUUID(); + NewAsset = map["new_asset"].AsUUID(); + State = map["state"].AsString(); + NewBaseMask = (PermissionMask)map["new_base_mask"].AsInteger(); + NewEveryoneMask = (PermissionMask)map["new_everyone_mask"].AsInteger(); + NewOwnerMask = (PermissionMask)map["new_owner_mask"].AsInteger(); + NewNextOwnerMask = (PermissionMask)map["new_next_owner_mask"].AsInteger(); + } + } public class WebFetchInventoryDescendentsMessage : IMessage { @@ -1165,6 +1320,7 @@ namespace OpenMetaverse.Messages.Linden #endregion } + #endregion #region Agent Messages @@ -3685,6 +3841,298 @@ namespace OpenMetaverse.Messages.Linden #endregion + #region Object Messages + + public class UploadObjectAssetMessage : IMessage + { + public class Object + { + public class Face + { + public Bumpiness Bump; + public Color4 Color; + public bool Fullbright; + public float Glow; + public UUID ImageID; + public float ImageRot; + public int MediaFlags; + public float OffsetS; + public float OffsetT; + public float ScaleS; + public float ScaleT; + + public OSDMap Serialize() + { + OSDMap map = new OSDMap(); + map["bump"] = OSD.FromInteger((int)Bump); + map["colors"] = OSD.FromColor4(Color); + map["fullbright"] = OSD.FromBoolean(Fullbright); + map["glow"] = OSD.FromReal(Glow); + map["imageid"] = OSD.FromUUID(ImageID); + map["imagerot"] = OSD.FromReal(ImageRot); + map["media_flags"] = OSD.FromInteger(MediaFlags); + map["offsets"] = OSD.FromReal(OffsetS); + map["offsett"] = OSD.FromReal(OffsetT); + map["scales"] = OSD.FromReal(ScaleS); + map["scalet"] = OSD.FromReal(ScaleT); + + return map; + } + + public void Deserialize(OSDMap map) + { + Bump = (Bumpiness)map["bump"].AsInteger(); + Color = map["colors"].AsColor4(); + Fullbright = map["fullbright"].AsBoolean(); + Glow = (float)map["glow"].AsReal(); + ImageID = map["imageid"].AsUUID(); + ImageRot = (float)map["imagerot"].AsReal(); + MediaFlags = map["media_flags"].AsInteger(); + OffsetS = (float)map["offsets"].AsReal(); + OffsetT = (float)map["offsett"].AsReal(); + ScaleS = (float)map["scales"].AsReal(); + ScaleT = (float)map["scalet"].AsReal(); + } + } + + public class ExtraParam + { + public ExtraParamType Type; + public byte[] ExtraParamData; + + public OSDMap Serialize() + { + OSDMap map = new OSDMap(); + map["extra_parameter"] = OSD.FromInteger((int)Type); + map["param_data"] = OSD.FromBinary(ExtraParamData); + + return map; + } + + public void Deserialize(OSDMap map) + { + Type = (ExtraParamType)map["extra_parameter"].AsInteger(); + ExtraParamData = map["param_data"].AsBinary(); + } + } + + public Face[] Faces; + public ExtraParam[] ExtraParams; + public UUID GroupID; + public Material Material; + public string Name; + public Vector3 Position; + public Quaternion Rotation; + public Vector3 Scale; + public float PathBegin; + public int PathCurve; + public float PathEnd; + public float RadiusOffset; + public float Revolutions; + public float ScaleX; + public float ScaleY; + public float ShearX; + public float ShearY; + public float Skew; + public float TaperX; + public float TaperY; + public float Twist; + public float TwistBegin; + public float ProfileBegin; + public int ProfileCurve; + public float ProfileEnd; + public float ProfileHollow; + public UUID SculptID; + public SculptType SculptType; + + public OSDMap Serialize() + { + OSDMap map = new OSDMap(); + + map["group-id"] = OSD.FromUUID(GroupID); + map["material"] = OSD.FromInteger((int)Material); + map["name"] = OSD.FromString(Name); + map["pos"] = OSD.FromVector3(Position); + map["rotation"] = OSD.FromQuaternion(Rotation); + map["scale"] = OSD.FromVector3(Scale); + + // Extra params + OSDArray extraParams = new OSDArray(); + if (ExtraParams != null) + { + for (int i = 0; i < ExtraParams.Length; i++) + extraParams.Add(ExtraParams[i].Serialize()); + } + map["extra_parameters"] = extraParams; + + // Faces + OSDArray faces = new OSDArray(); + if (Faces != null) + { + for (int i = 0; i < Faces.Length; i++) + faces.Add(Faces[i].Serialize()); + } + map["facelist"] = faces; + + // Shape + OSDMap shape = new OSDMap(); + OSDMap path = new OSDMap(); + path["begin"] = OSD.FromReal(PathBegin); + path["curve"] = OSD.FromInteger(PathCurve); + path["end"] = OSD.FromReal(PathEnd); + path["radius_offset"] = OSD.FromReal(RadiusOffset); + path["revolutions"] = OSD.FromReal(Revolutions); + path["scale_x"] = OSD.FromReal(ScaleX); + path["scale_y"] = OSD.FromReal(ScaleY); + path["shear_x"] = OSD.FromReal(ShearX); + path["shear_y"] = OSD.FromReal(ShearY); + path["skew"] = OSD.FromReal(Skew); + path["taper_x"] = OSD.FromReal(TaperX); + path["taper_y"] = OSD.FromReal(TaperY); + path["twist"] = OSD.FromReal(Twist); + path["twist_begin"] = OSD.FromReal(TwistBegin); + shape["path"] = path; + OSDMap profile = new OSDMap(); + profile["begin"] = OSD.FromReal(ProfileBegin); + profile["curve"] = OSD.FromInteger(ProfileCurve); + profile["end"] = OSD.FromReal(ProfileEnd); + profile["hollow"] = OSD.FromReal(ProfileHollow); + shape["profile"] = profile; + OSDMap sculpt = new OSDMap(); + sculpt["id"] = OSD.FromUUID(SculptID); + sculpt["type"] = OSD.FromInteger((int)SculptType); + shape["sculpt"] = sculpt; + map["shape"] = shape; + + return map; + } + + public void Deserialize(OSDMap map) + { + GroupID = map["group-id"].AsUUID(); + Material = (Material)map["material"].AsInteger(); + Name = map["name"].AsString(); + Position = map["pos"].AsVector3(); + Rotation = map["rotation"].AsQuaternion(); + Scale = map["scale"].AsVector3(); + + // Extra params + OSDArray extraParams = map["extra_parameters"] as OSDArray; + if (extraParams != null) + { + ExtraParams = new ExtraParam[extraParams.Count]; + for (int i = 0; i < extraParams.Count; i++) + { + ExtraParam extraParam = new ExtraParam(); + extraParam.Deserialize(extraParams[i] as OSDMap); + ExtraParams[i] = extraParam; + } + } + else + { + ExtraParams = new ExtraParam[0]; + } + + // Faces + OSDArray faces = map["facelist"] as OSDArray; + if (faces != null) + { + Faces = new Face[faces.Count]; + for (int i = 0; i < faces.Count; i++) + { + Face face = new Face(); + face.Deserialize(faces[i] as OSDMap); + Faces[i] = face; + } + } + else + { + Faces = new Face[0]; + } + + // Shape + OSDMap shape = map["shape"] as OSDMap; + OSDMap path = shape["path"] as OSDMap; + PathBegin = (float)path["begin"].AsReal(); + PathCurve = path["curve"].AsInteger(); + PathEnd = (float)path["end"].AsReal(); + RadiusOffset = (float)path["radius_offset"].AsReal(); + Revolutions = (float)path["revolutions"].AsReal(); + ScaleX = (float)path["scale_x"].AsReal(); + ScaleY = (float)path["scale_y"].AsReal(); + ShearX = (float)path["shear_x"].AsReal(); + ShearY = (float)path["shear_y"].AsReal(); + Skew = (float)path["skew"].AsReal(); + TaperX = (float)path["taper_x"].AsReal(); + TaperY = (float)path["taper_y"].AsReal(); + Twist = (float)path["twist"].AsReal(); + TwistBegin = (float)path["twist_begin"].AsReal(); + + OSDMap profile = shape["profile"] as OSDMap; + ProfileBegin = (float)profile["begin"].AsReal(); + ProfileCurve = profile["curve"].AsInteger(); + ProfileEnd = (float)profile["end"].AsReal(); + ProfileHollow = (float)profile["hollow"].AsReal(); + + OSDMap sculpt = shape["sculpt"] as OSDMap; + if (sculpt != null) + { + SculptID = sculpt["id"].AsUUID(); + SculptType = (SculptType)sculpt["type"].AsInteger(); + } + else + { + SculptID = UUID.Zero; + SculptType = 0; + } + } + } + + public Object[] Objects; + + public OSDMap Serialize() + { + OSDMap map = new OSDMap(); + OSDArray array = new OSDArray(); + + if (Objects != null) + { + for (int i = 0; i < Objects.Length; i++) + array.Add(Objects[i].Serialize()); + } + + map["objects"] = array; + return map; + } + + public void Deserialize(OSDMap map) + { + OSDArray array = map["objects"] as OSDArray; + + if (array != null) + { + Objects = new Object[array.Count]; + + for (int i = 0; i < array.Count; i++) + { + Object obj = new Object(); + OSDMap objMap = array[i] as OSDMap; + + if (objMap != null) + obj.Deserialize(objMap); + + Objects[i] = obj; + } + } + else + { + Objects = new Object[0]; + } + } + } + + #endregion Object Messages + #region Object Media Messages /// /// A message sent from the viewer to the simulator which diff --git a/OpenMetaverseTypes/Enums.cs b/OpenMetaverseTypes/Enums.cs index c91c3b05..51b85eef 100644 --- a/OpenMetaverseTypes/Enums.cs +++ b/OpenMetaverseTypes/Enums.cs @@ -124,8 +124,8 @@ namespace OpenMetaverse OutfitFolder = 47, /// Root folder for the folders of type OutfitFolder MyOutfitsFolder = 48, - /// - InboxFolder = 49, + /// Linden mesh format + Mesh = 49, } /// @@ -184,7 +184,10 @@ namespace OpenMetaverse /// Animation = 19, /// - Gesture = 20 + Gesture = 20, + + /// + Mesh = 22, } /// diff --git a/OpenMetaverseTypes/EnumsPrimitive.cs b/OpenMetaverseTypes/EnumsPrimitive.cs index 1bb56912..33076b18 100644 --- a/OpenMetaverseTypes/EnumsPrimitive.cs +++ b/OpenMetaverseTypes/EnumsPrimitive.cs @@ -265,6 +265,8 @@ namespace OpenMetaverse /// Cylinder = 4, /// + Mesh = 5, + /// Invert = 64, /// Mirror = 128 diff --git a/OpenMetaverseTypes/UtilsConversions.cs b/OpenMetaverseTypes/UtilsConversions.cs index ef4bda7b..9b720f78 100644 --- a/OpenMetaverseTypes/UtilsConversions.cs +++ b/OpenMetaverseTypes/UtilsConversions.cs @@ -37,54 +37,83 @@ namespace OpenMetaverse private static readonly string[] _AssetTypeNames = new string[] { - "texture", - "sound", - "callcard", - "landmark", - "script", - "clothing", - "object", - "notecard", - "category", - "root", - "lsltext", - "lslbyte", - "txtr_tga", - "bodypart", - "trash", - "snapshot", - "lstndfnd", - "snd_wav", - "img_tga", - "jpeg", - "animatn", - "gesture", - "simstate" + "texture", // 0 + "sound", // 1 + "callcard", // 2 + "landmark", // 3 + "script", // 4 + "clothing", // 5 + "object", // 6 + "notecard", // 7 + "category", // 8 + "root", // 9 + "lsltext", // 10 + "lslbyte", // 11 + "txtr_tga", // 12 + "bodypart", // 13 + "trash", // 14 + "snapshot", // 15 + "lstndfnd", // 16 + "snd_wav", // 17 + "img_tga", // 18 + "jpeg", // 19 + "animatn", // 20 + "gesture", // 21 + "simstate", // 22 + "favorite", // 23 + "link", // 24 + "linkfolder", // 25 + String.Empty, // 26 + String.Empty, // 27 + String.Empty, // 28 + String.Empty, // 29 + String.Empty, // 30 + String.Empty, // 31 + String.Empty, // 32 + String.Empty, // 33 + String.Empty, // 34 + String.Empty, // 35 + String.Empty, // 36 + String.Empty, // 37 + String.Empty, // 38 + String.Empty, // 39 + String.Empty, // 40 + String.Empty, // 41 + String.Empty, // 42 + String.Empty, // 43 + String.Empty, // 44 + String.Empty, // 45 + "curoutfit", // 46 + "outfit", // 47 + "myoutfits", // 48 + "mesh", // 49 }; private static readonly string[] _InventoryTypeNames = new string[] { - "texture", - "sound", - "callcard", - "landmark", - String.Empty, - String.Empty, - "object", - "notecard", - "category", - "root", - "script", - String.Empty, - String.Empty, - String.Empty, - String.Empty, - "snapshot", - String.Empty, - "attach", - "wearable", - "animation", - "gesture", + "texture", // 0 + "sound", // 1 + "callcard", // 2 + "landmark", // 3 + String.Empty, // 4 + String.Empty, // 5 + "object", // 6 + "notecard", // 7 + "category", // 8 + "root", // 9 + "script", // 10 + String.Empty, // 11 + String.Empty, // 12 + String.Empty, // 13 + String.Empty, // 14 + "snapshot", // 15 + String.Empty, // 16 + "attach", // 17 + "wearable", // 18 + "animation", // 19 + "gesture", // 20 + String.Empty, // 21 + "mesh" // 22 }; private static readonly string[] _SaleTypeNames = new string[] diff --git a/bin/log4net.dll b/bin/log4net.dll index ffc57e11..974b4939 100644 Binary files a/bin/log4net.dll and b/bin/log4net.dll differ