/// <summary>
        /// Creates and adds a <see cref="Tags.TagFieldInfo"/> to the <see cref="Tags.TagFieldInfo"/> <see cref="List{T}"/>.
        /// </summary>
        /// <param name="field">The <see cref="FieldInfo"/> to create the <see cref="Tags.TagFieldInfo"/> from.</param>
        /// <param name="attribute">The <see cref="TagFieldAttribute"/> for the <see cref="Tags.TagFieldInfo"/>.</param>
        /// <param name="targetVersion">The target <see cref="CacheVersion"/> the <see cref="Tags.TagFieldInfo"/> belongs to.</param>
        /// <param name="offset">The offset (in bytes) of the field. Gets updated to reflect the new offset following field.</param>
        private void CreateTagFieldInfo(FieldInfo field, TagFieldAttribute attribute, CacheVersion targetVersion, ref uint offset)
        {
            var fieldSize = TagFieldInfo.GetFieldSize(field.FieldType, attribute, targetVersion);

            if (fieldSize == 0 && !attribute.Flags.HasFlag(TagFieldFlags.Runtime))
            {
                throw new InvalidOperationException();
            }

            var tagFieldInfo = new TagFieldInfo(field, attribute, offset, fieldSize);

            TagFieldInfos.Add(tagFieldInfo);
            offset += fieldSize;
        }
Example #2
0
        /// <summary>
        /// Gets the size of a tag-field.
        /// </summary>
        /// <param name="type">The <see cref="Type"/> of the field.</param>
        /// <param name="attr">The <see cref="TagFieldAttribute"/> of the field.</param>
        /// <param name="targetVersion">The <see cref="CacheVersion"/> to target.</param>
        /// <returns></returns>
        public static uint GetFieldSize(Type type, TagFieldAttribute attr, CacheVersion targetVersion)
        {
            switch (Type.GetTypeCode(type))
            {
            case TypeCode.Boolean:
            case TypeCode.SByte:
            case TypeCode.Byte:
                return(0x01);

            case TypeCode.Char:
            case TypeCode.Int16:
            case TypeCode.UInt16:
                return(0x02);

            case TypeCode.Single:
            case TypeCode.Int32:
            case TypeCode.UInt32:
            case TypeCode.Object when attr != null && attr.Flags.HasFlag(TagFieldFlags.Pointer):
            case TypeCode.Object when type == typeof(Tag):
            case TypeCode.Object when type == typeof(CacheAddress):
            case TypeCode.Object when type == typeof(CachedTagInstance) && attr.Flags.HasFlag(TagFieldFlags.Short):
            //case TypeCode.Object when type == typeof(RgbColor):
            case TypeCode.Object when type == typeof(ArgbColor):
            case TypeCode.Object when type == typeof(Point2d):
            case TypeCode.Object when type == typeof(StringId):
            case TypeCode.Object when type == typeof(Angle):
            case TypeCode.Object when type == typeof(VertexShaderReference):
            case TypeCode.Object when type == typeof(PixelShaderReference):
                return(0x04);

            case TypeCode.Double:
            case TypeCode.Int64:
            case TypeCode.UInt64:
            case TypeCode.Object when type == typeof(CachedTagInstance) && targetVersion != CacheVersion.Unknown && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo2Xbox, CacheVersion.Halo2Vista):
            case TypeCode.Object when type == typeof(byte[]) && targetVersion != CacheVersion.Unknown && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo2Xbox, CacheVersion.Halo2Vista):
            case TypeCode.Object when type == typeof(Rectangle2d):
            case TypeCode.Object when type == typeof(RealEulerAngles2d):
            case TypeCode.Object when type == typeof(RealPoint2d):
            case TypeCode.Object when type == typeof(RealVector2d):
            case TypeCode.Object when type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List <>) && targetVersion != CacheVersion.Unknown && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo2Xbox, CacheVersion.Halo2Vista):
            case TypeCode.Object when type.IsGenericType && type.GetGenericTypeDefinition() == typeof(TagBlock <>) && targetVersion != CacheVersion.Unknown && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo2Xbox, CacheVersion.Halo2Vista):
                return(0x08);

            case TypeCode.Object when type == typeof(RealRgbColor):
            case TypeCode.Object when type == typeof(RealEulerAngles3d):
            case TypeCode.Object when type == typeof(RealPoint3d):
            case TypeCode.Object when type == typeof(RealVector3d):
            case TypeCode.Object when type == typeof(RealPlane2d):
            case TypeCode.Object when type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List <>) && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo3Retail, CacheVersion.Unknown):
            case TypeCode.Object when type.IsGenericType && type.GetGenericTypeDefinition() == typeof(TagBlock <>) && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo3Retail, CacheVersion.Unknown):
                return(0x0C);

            case TypeCode.Decimal:
            case TypeCode.Object when type == typeof(CachedTagInstance) && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo3Retail, CacheVersion.Unknown):
            case TypeCode.Object when type == typeof(RealArgbColor):
            case TypeCode.Object when type == typeof(RealQuaternion):
            case TypeCode.Object when type == typeof(RealPlane3d):
                return(0x10);

            case TypeCode.Object when type == typeof(byte[]) && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo3Retail, CacheVersion.Unknown):
                return(0x14);

            case TypeCode.Object when type == typeof(RealMatrix4x3):
                return(0x30);

            case TypeCode.Object when type == typeof(DatumIndex):
                return(sizeof(uint));

            case TypeCode.String:
            case TypeCode.Object when type.IsArray:
                return((uint)attr.Length);

            case TypeCode.Object when type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Bounds <>):
                return(TagFieldInfo.GetFieldSize(type.GenericTypeArguments[0], attr, targetVersion) * 2);

            case TypeCode.Object when type.IsEnum:
                return(TagFieldInfo.GetFieldSize(type.GetEnumUnderlyingType(), attr, targetVersion));

            // Assume the field is a structure
            default:
                return(TagStructure.GetTagStructureInfo(type, targetVersion).TotalSize);
            }
        }