Editor/HumanoidRetargeter/Embedded/ValveResourceFormat/Resource/ResourceTypes/KeyValuesOrNTRO.cs
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using HumanoidRetargeterVrf.Utils;
using System.IO;
using HumanoidRetargeterVrf.Serialization.KeyValues;
#nullable disable
namespace HumanoidRetargeterVrf.ResourceTypes
{
/// <summary>
/// Block that can contain either <see cref="KVObject"/> or <see cref="NTRO"/> data.
/// </summary>
public class KeyValuesOrNTRO : Block
{
private readonly string IntrospectionStructName;
private readonly BlockType KVBlockType;
/// <inheritdoc/>
public override BlockType Type => KVBlockType;
/// <summary>
/// Gets the parsed data as a <see cref="KVObject"/>.
/// </summary>
public KVObject Data { get; private set; }
private Block BackingData;
/// <summary>
/// Initializes a new instance of the <see cref="KeyValuesOrNTRO"/> class.
/// </summary>
public KeyValuesOrNTRO()
{
KVBlockType = BlockType.DATA;
}
/// <summary>
/// Initializes a new instance of the <see cref="KeyValuesOrNTRO"/> class with a specific block type and introspection struct name.
/// </summary>
/// <param name="type">The block type.</param>
/// <param name="introspectionStructName">The introspection struct name for <see cref="NTRO"/> parsing.</param>
public KeyValuesOrNTRO(BlockType type, string introspectionStructName)
{
KVBlockType = type;
IntrospectionStructName = introspectionStructName;
}
/// <inheritdoc/>
public override void Read(BinaryReader reader)
{
// It is possible to have MDAT block with NTRO in a file, but it will be KV3 anyway.
if (!Resource.ContainsBlockType(BlockType.NTRO) || KVBlockType == BlockType.MDAT)
{
var kv3 = new BinaryKV3(KVBlockType)
{
Offset = Offset,
Size = Size,
Resource = Resource,
};
kv3.Read(reader);
Data = kv3.Data;
BackingData = kv3;
}
else
{
var ntro = new NTRO
{
StructName = IntrospectionStructName,
Offset = Offset,
Size = Size,
Resource = Resource,
};
ntro.Read(reader);
Data = ntro.Output;
BackingData = ntro;
}
}
/// <inheritdoc/>
public override void Serialize(Stream stream)
{
if (BackingData is BinaryKV3 dataKv3)
{
dataKv3.Serialize(stream);
return;
}
throw new NotImplementedException("Serializing this block is not yet supported. If you need this, send us a pull request!");
}
/// <inheritdoc/>
/// <remarks>
/// Writes the data as KV3 text format, regardless of the backing data source.
/// </remarks>
public override void WriteText(IndentedTextWriter writer)
{
if (BackingData is BinaryKV3 dataKv3)
{
dataKv3.GetKV3File().WriteText(writer);
return;
}
BackingData.WriteText(writer);
}
}
}