static internal TypeInformation ParseTypeFields(Mono.Cecil.TypeDefinition type, bool onlyFieldWithGhostField = true)
        {
            bool isBuffer      = CecilExtensions.IsBufferElementData(type);
            bool isCommandData = CecilExtensions.IsICommandData(type);
            var  root          = new TypeInformation(type);

            if (isBuffer)
            {
                root.AttributeMask &= ~(TypeAttribute.AttributeFlags.InterpolatedAndExtrapolated);
            }

            if (!type.HasFields)
            {
                return(root);
            }
            foreach (var field in type.Fields)
            {
                if (!field.IsPublic || field.IsStatic)
                {
                    continue;
                }

                var ghostField = CecilExtensions.GetGhostFieldAttribute(type, field);
                if (!onlyFieldWithGhostField && isCommandData &&
                    field.HasAttributeOnMemberOImplementedInterfaces <DontSerializeForCommand>())
                {
                    continue;
                }
                if (!onlyFieldWithGhostField || (ghostField != null && ghostField.SendData))
                {
                    root.Add(ParseTypeField(field, field.FieldType, ghostField, TypeAttribute.Empty(), root.AttributeMask));
                }
            }
            foreach (var prop in type.Properties)
            {
                if (prop.GetMethod == null || !prop.GetMethod.IsPublic || prop.GetMethod.IsStatic)
                {
                    continue;
                }
                if (prop.SetMethod == null || !prop.SetMethod.IsPublic || prop.SetMethod.IsStatic)
                {
                    continue;
                }

                var ghostField = CecilExtensions.GetGhostFieldAttribute(type, prop);
                if (!onlyFieldWithGhostField && isCommandData &&
                    prop.HasAttributeOnMemberOImplementedInterfaces <DontSerializeForCommand>())
                {
                    continue;
                }

                if (!onlyFieldWithGhostField || (ghostField != null && ghostField.SendData))
                {
                    root.Add(ParseTypeField(prop, prop.PropertyType, ghostField, TypeAttribute.Empty(), root.AttributeMask));
                }
            }


            return(root);
        }
        TypeInformation ParseTypeFields(Mono.Cecil.TypeDefinition type, bool onlyFieldWithGhostField = true)
        {
            var root = new TypeInformation(type);

            if (!type.HasFields)
            {
                return(root);
            }

            foreach (var field in type.Fields)
            {
                if (!field.IsPublic || field.IsStatic)
                {
                    continue;
                }

                if (!onlyFieldWithGhostField || CecilExtensions.HasGhostFieldAttribute(type, field))
                {
                    if (!CecilExtensions.HasGhostFieldAttribute(type, field) || CecilExtensions.GetGhostFieldAttribute(type, field).SendData)
                    {
                        root.Add(ParseTypeField(type, field, TypeAttribute.Empty()));
                    }
                }
            }
            return(root);
        }
        static internal TypeInformation ParseVariantTypeFields(Mono.Cecil.TypeDefinition variantType, Mono.Cecil.TypeReference typeReference)
        {
            var type = typeReference.Resolve();

            var root = new TypeInformation(type);

            if (!variantType.HasFields)
            {
                return(root);
            }

            foreach (var field in variantType.Fields)
            {
                if (!field.IsPublic || field.IsStatic)
                {
                    continue;
                }

                if (type.Fields.FirstOrDefault(f => f.Name == field.Name) == null)
                {
                    UnityEngine.Debug.LogError($"Variant {variantType.Name}. field {field.Name} not present in original type {type.Name}");
                    continue;
                }

                //Avoid use ghost fields modifiers for the variant type. passing null prevent that
                var ghostField = CecilExtensions.GetGhostFieldAttribute(null, field);
                if (ghostField != null && ghostField.SendData)
                {
                    root.Add(ParseTypeField(field, field.FieldType, ghostField, TypeAttribute.Empty(), root.AttributeMask));
                }
            }
            foreach (var prop in type.Properties)
            {
                if (prop.GetMethod == null || !prop.GetMethod.IsPublic || prop.GetMethod.IsStatic)
                {
                    continue;
                }
                if (prop.SetMethod == null || !prop.SetMethod.IsPublic || prop.SetMethod.IsStatic)
                {
                    continue;
                }

                if (type.Properties.FirstOrDefault(f => f.Name == prop.Name) == null)
                {
                    UnityEngine.Debug.LogError($"Variant {variantType.Name}. field {prop.Name} not present in original type {type.Name}");
                    continue;
                }

                var ghostField = CecilExtensions.GetGhostFieldAttribute(type, prop);
                if (ghostField != null && ghostField.SendData)
                {
                    root.Add(ParseTypeField(prop, prop.PropertyType, ghostField, TypeAttribute.Empty(), root.AttributeMask));
                }
            }
            return(root);
        }
        public TypeInformation(Mono.Cecil.TypeReference parentType, Mono.Cecil.FieldDefinition fieldInfo, TypeAttribute inheritedAttribute,
                               string parent = null)
        {
            FieldInfo = fieldInfo;
            Type      = fieldInfo.FieldType;
            Fields    = new List <TypeInformation>();
            Attribute = inheritedAttribute;

            ParseAttribute(CecilExtensions.GetGhostFieldAttribute(parentType, fieldInfo));
            Parent = string.IsNullOrEmpty(parent) ? "" : parent;
        }