Пример #1
0
        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;
        }
Пример #2
0
        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);
        }