public override void Read(BinaryReader resourceReader, Resource resource) { resourceReader.BaseStream.Position = Offset; // Decompress SNAP block compression using var decompressedStream = BlockCompress.Decompress(resourceReader, Size); using var reader = new BinaryReader(decompressedStream); // Get DATA block to know how to read SNAP data var data = resource.DataBlock.AsKeyValueCollection(); var numParticles = data.GetIntegerProperty("num_particles"); var attributes = data.GetArray("attributes"); var stringList = data.GetArray <string>("string_list"); var attributeData = new Dictionary <string, IEnumerable>(); foreach (var attribute in attributes) { var attributeName = attribute.GetProperty <string>("name"); var attributeType = attribute.GetProperty <string>("type"); var attributeArray = attributeType switch { "skinning" => ReadSkinningData(reader, numParticles, stringList), "string" => ReadStringArray(reader, numParticles, stringList), "bone" => ReadStringArray(reader, numParticles, stringList), _ => ReadArrayOfType(reader, numParticles, attributeType), }; attributeData.Add(attributeName, attributeArray); } NumParticles = (uint)numParticles; AttributeData = attributeData; }
public override void Read(BinaryReader reader, Resource resource) { reader.BaseStream.Position = Offset; var outStream = new MemoryStream(); var outWrite = new BinaryWriter(outStream); var outRead = new BinaryReader(outStream); // Why why why why why why why var magic = reader.ReadUInt32(); if (magic == MAGIC2) { ReadVersion2(reader, outWrite, outRead); return; } if (magic == MAGIC3) { RawBinaryReader = reader; ReadVersion3(reader, outWrite, outRead); RawBinaryReader = null; return; } if (magic != MAGIC) { throw new UnexpectedMagicException("Invalid KV3 signature", magic, nameof(magic)); } Encoding = new Guid(reader.ReadBytes(16)); Format = new Guid(reader.ReadBytes(16)); // Valve's implementation lives in LoadKV3Binary() // KV3_ENCODING_BINARY_BLOCK_COMPRESSED calls CBlockCompress::FastDecompress() // and then it proceeds to call LoadKV3BinaryUncompressed, which should be the same routine for KV3_ENCODING_BINARY_UNCOMPRESSED // Old binary with debug symbols for ref: https://users.alliedmods.net/~asherkin/public/bins/dota_symbols/bin/osx64/libmeshsystem.dylib if (Encoding.CompareTo(KV3_ENCODING_BINARY_BLOCK_COMPRESSED) == 0) { BlockCompress.FastDecompress(reader, outWrite, outRead); } else if (Encoding.CompareTo(KV3_ENCODING_BINARY_BLOCK_LZ4) == 0) { DecompressLZ4(reader, outWrite); } else if (Encoding.CompareTo(KV3_ENCODING_BINARY_UNCOMPRESSED) == 0) { reader.BaseStream.CopyTo(outStream); outStream.Position = 0; } else { throw new UnexpectedMagicException("Unrecognised KV3 Encoding", Encoding.ToString(), nameof(Encoding)); } var stringCount = outRead.ReadUInt32(); stringArray = new string[stringCount]; for (var i = 0; i < stringCount; i++) { stringArray[i] = outRead.ReadNullTermString(System.Text.Encoding.UTF8); } Data = ParseBinaryKV3(outRead, null, true); }