/// <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; }
/// <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); } }