Advertisement
_DarkLex_

Untitled

Jun 1st, 2021 (edited)
839
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.98 KB | None | 0 0
  1.     [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
  2.     public class NbtPropertyAttribute : Attribute
  3.     {
  4.         public string Name { get; }
  5.         public bool HideDefault { get; }
  6.  
  7.         public NbtPropertyAttribute(string name = null, bool hideDefault = true)
  8.         {
  9.             Name = name;
  10.             HideDefault = hideDefault;
  11.         }
  12.     }
  13.  
  14.     public static class NbtSerializer
  15.     {
  16.         public static NbtCompound SerializeObject(object value)
  17.         {
  18.             return (NbtCompound)SerializeChild(null, value);
  19.         }
  20.  
  21.         public static T DeserializeObject<T>(NbtCompound tag)
  22.         {
  23.             return (T)DeserializeChild(typeof(T), tag);
  24.         }
  25.  
  26.         public static void FillObject<T>(T value, NbtCompound tag)
  27.         {
  28.             FillObject(value, value.GetType(), tag);
  29.         }
  30.  
  31.         private static NbtTag SerializeChild(string name, object value)
  32.         {
  33.             if (value is NbtTag normalValue)
  34.             {
  35.                 if (name != null) normalValue.Name = name;
  36.                 return normalValue;
  37.             }
  38.  
  39.             var tag = CreateBaseTag(name, value);
  40.             if (tag != null) return tag;
  41.  
  42.             if (value is IList list)
  43.             {
  44.                 return GetNbtList(name, list);
  45.             }
  46.             else if (value is IDictionary dictionary)
  47.             {
  48.                 return GetNbtCompaund(name, dictionary);
  49.             }
  50.  
  51.             var type = value.GetType();
  52.  
  53.             var properties = type.GetProperties();
  54.             var fields = type.GetFields();
  55.  
  56.             if (properties.Length == 0 && fields.Length == 0) return null;
  57.  
  58.             var nbt = new NbtCompound();
  59.             if (name != null) nbt.Name = name;
  60.  
  61.             foreach (var property in properties)
  62.             {
  63.                 var child = SerializeMember(property, property.GetValue(value));
  64.                 if (child != null) nbt.Add(child);
  65.             }
  66.  
  67.             foreach (var filed in fields)
  68.             {
  69.                 var child = SerializeMember(filed, filed.GetValue(value));
  70.                 if (child != null) nbt.Add(child);
  71.             }
  72.  
  73.             if (nbt.Count == 0) return null;
  74.  
  75.             return nbt;
  76.         }
  77.  
  78.         private static NbtTag SerializeMember(MemberInfo memberInfo, object value)
  79.         {
  80.             var attribute = GetAttribute(memberInfo);
  81.             if (attribute == null) return null;
  82.  
  83.             if (attribute.HideDefault && value.Equals(GetDefaultValue(value))) return null;
  84.  
  85.             string childName = attribute.Name ?? memberInfo.Name;
  86.             return SerializeChild(childName, value);
  87.         }
  88.  
  89.         public static object GetDefaultValue(object value)
  90.         {
  91.             return value switch
  92.             {
  93.                 byte or sbyte or
  94.                 short or short or
  95.                 int or uint or
  96.                 long or ulong or
  97.                 decimal or double or float => 0,
  98.                 bool => false,
  99.                 _ => null
  100.             };
  101.         }
  102.  
  103.         private static object DeserializeChild(Type type, NbtTag tag)
  104.         {
  105.             if (type.IsAssignableTo(typeof(NbtTag)))
  106.             {
  107.                 tag.Name = null;
  108.                 return tag;
  109.             }
  110.  
  111.             var value = GetValueFromTag(tag, type);
  112.             if (value != null) return value;
  113.  
  114.             if (type.IsAssignableTo(typeof(IList)))
  115.             {
  116.                 return GetList(type, (NbtList)tag);
  117.             }
  118.             else if (type.IsAssignableTo(typeof(IDictionary)))
  119.             {
  120.                 return GetDictionary(type, (NbtCompound)tag);
  121.             }
  122.  
  123.             value = Activator.CreateInstance(type);
  124.  
  125.             DeserializeBase(value, type, tag);
  126.  
  127.             return value;
  128.         }
  129.  
  130.         private static void DeserializeBase(object value, Type type, NbtTag tag)
  131.         {
  132.             var compound = (NbtCompound)tag;
  133.  
  134.             var properties = type.GetProperties();
  135.             var fields = type.GetFields();
  136.  
  137.             if (compound.Count == 0) return;
  138.  
  139.             foreach (var property in properties)
  140.             {
  141.                 if (!TryGetMemberTag(property, property.PropertyType, compound, out NbtTag child)) continue;
  142.  
  143.                 if (property.SetMethod == null)
  144.                 {
  145.                     FillObject(property.GetValue(value), property.PropertyType, child);
  146.                     continue;
  147.                 }
  148.  
  149.                 property.SetValue(value, DeserializeChild(property.PropertyType, child));
  150.             }
  151.  
  152.             foreach (var filed in fields)
  153.             {
  154.                 if (!TryGetMemberTag(filed, filed.FieldType, compound, out NbtTag child)) continue;
  155.                 filed.SetValue(value, DeserializeChild(filed.FieldType, child));
  156.             }
  157.         }
  158.  
  159.         private static bool TryGetMemberTag(MemberInfo memberInfo, Type memberType, NbtCompound compound, out NbtTag tag)
  160.         {
  161.             tag = null;
  162.  
  163.             var attribute = GetAttribute(memberInfo);
  164.             if (attribute == null) return false;
  165.  
  166.             string childName = attribute.Name ?? memberInfo.Name;
  167.             return compound.TryGet(childName, out tag);
  168.         }
  169.  
  170.         private static void FillObject(object value, Type type, NbtTag tag)
  171.         {
  172.             var baseTypeValue = GetValueFromTag(tag, type);
  173.             if (baseTypeValue != null) return;
  174.  
  175.             if (value is IList list)
  176.             {
  177.                 list.Clear();
  178.                 FillList(list, list.GetType(), (NbtList) tag);
  179.                 return;
  180.             }
  181.             else if (value is IDictionary dictionary)
  182.             {
  183.                 dictionary.Clear();
  184.                 FillDictionary(dictionary, dictionary.GetType(), (NbtCompound) tag);
  185.                 return;
  186.             }
  187.  
  188.             value = Activator.CreateInstance(type);
  189.  
  190.             DeserializeBase(value, type, tag);
  191.         }
  192.  
  193.         private static NbtPropertyAttribute GetAttribute(MemberInfo memberInfo)
  194.         {
  195.             return memberInfo.GetCustomAttribute<NbtPropertyAttribute>();
  196.         }
  197.  
  198.         private static NbtTag? CreateBaseTag(string name, object value)
  199.         {
  200.             return value switch
  201.             {
  202.                 byte _value => new NbtByte(name, _value),
  203.                 sbyte _value => new NbtByte(name, (byte)_value),
  204.                 short _value => new NbtShort(name, _value),
  205.                 ushort _value => new NbtShort(name, (short)_value),
  206.                 int _value => new NbtInt(name, _value),
  207.                 uint _value => new NbtInt(name, (int)_value),
  208.                 long _value => new NbtLong(name, _value),
  209.                 ulong _value => new NbtLong(name, (long)_value),
  210.                 double _value => new NbtDouble(name, _value),
  211.                 float _value => new NbtFloat(name, _value),
  212.                 string _value => new NbtString(name, _value),
  213.                 byte[] _value => new NbtByteArray(name, _value),
  214.                 int[] _value => new NbtIntArray(name, _value),
  215.                 _ => null
  216.             };
  217.         }
  218.  
  219.         private static object? GetValueFromTag(NbtTag tag, Type type)
  220.         {
  221.             return (tag) switch
  222.             {
  223.                 NbtByte _value => type == typeof(byte) ? _value.Value : (sbyte)_value.Value,
  224.                 NbtShort _value => type == typeof(short) ? _value.Value : (ushort)_value.Value,
  225.                 NbtInt _value => type == typeof(int) ? _value.Value : (uint)_value.Value,
  226.                 NbtLong _value => type == typeof(long) ? _value.Value : (ulong)_value.Value,
  227.                 NbtDouble _value => _value.Value,
  228.                 NbtFloat _value => _value.Value,
  229.                 NbtString _value => _value.Value,
  230.                 NbtByteArray _value => _value.Value,
  231.                 NbtIntArray _value => _value.Value,
  232.                 _ => null
  233.             };
  234.         }
  235.  
  236.         private static NbtList GetNbtList(string name, IList list)
  237.         {
  238.             if (list.Count == 0) return null;
  239.  
  240.             var nbt = new NbtList();
  241.             if (name != null) nbt.Name = name;
  242.  
  243.             foreach (var value in list)
  244.             {
  245.                 nbt.Add(SerializeChild(null, value));
  246.             }
  247.  
  248.             return nbt;
  249.         }
  250.  
  251.         private static IList GetList(Type type, NbtList tag)
  252.         {
  253.             var list = (IList)Activator.CreateInstance(type);
  254.  
  255.             FillList(list, type, tag);
  256.             return list;
  257.         }
  258.  
  259.         private static void FillList(IList list, Type type, NbtList tag)
  260.         {
  261.             if (tag.Count == 0) return;
  262.  
  263.             var listType = type.GetGenericArguments().First();
  264.  
  265.             foreach (var child in tag)
  266.             {
  267.                 list.Add(DeserializeChild(listType, child));
  268.             }
  269.         }
  270.  
  271.         private static NbtCompound GetNbtCompaund(string name, IDictionary dictionary)
  272.         {
  273.             if (dictionary.Count == 0) return null;
  274.             if (dictionary.GetType().GetGenericArguments().First() != typeof(string)) return null;
  275.  
  276.             var keys = dictionary.Keys.GetEnumerator();
  277.             var values = dictionary.Values.GetEnumerator();
  278.  
  279.             var nbt = new NbtCompound();
  280.             if (name != null) nbt.Name = name;
  281.  
  282.             while (keys.MoveNext() && values.MoveNext())
  283.             {
  284.                 var childName = (string)keys.Current;
  285.                 nbt.Add(SerializeChild(childName, values.Current));
  286.             }
  287.  
  288.             return nbt;
  289.         }
  290.  
  291.         private static IDictionary GetDictionary(Type type, NbtCompound tag)
  292.         {
  293.             var dictionary = (IDictionary)Activator.CreateInstance(type);
  294.  
  295.             FillDictionary(dictionary, type, tag);
  296.             return dictionary;
  297.         }
  298.  
  299.         private static void FillDictionary(IDictionary dictionary, Type type, NbtCompound tag)
  300.         {
  301.             var dictionaryType = type.GetGenericArguments().Last();
  302.  
  303.             foreach (var child in tag)
  304.             {
  305.                 dictionary.Add(child.Name, DeserializeChild(dictionaryType, child));
  306.             }
  307.         }
  308.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement