Ejemplo n.º 1
0
        public bool Pack(AssetsFileReader reader, AssetsFileWriter writer, AssetBundleCompressionType compType, bool blockDirAtEnd = true)
        {
            reader.Position = 0;
            writer.Position = 0;
            if (Read(reader, false))
            {
                AssetBundleHeader06 newHeader = new AssetBundleHeader06()
                {
                    signature         = bundleHeader6.signature,
                    fileVersion       = bundleHeader6.fileVersion,
                    minPlayerVersion  = bundleHeader6.minPlayerVersion,
                    fileEngineVersion = bundleHeader6.fileEngineVersion,
                    totalFileSize     = 0,
                    compressedSize    = 0,
                    decompressedSize  = 0,
                    flags             = (uint)(0x43 | (blockDirAtEnd ? 0x80 : 0x00))
                };

                AssetBundleBlockAndDirectoryList06 newBlockAndDirList = new AssetBundleBlockAndDirectoryList06()
                {
                    checksumLow    = 0,
                    checksumHigh   = 0,
                    blockCount     = 0,
                    blockInf       = null,
                    directoryCount = bundleInf6.directoryCount,
                    dirInf         = bundleInf6.dirInf
                };

                //write header now and overwrite it later
                long startPos = writer.Position;

                newHeader.Write(writer);
                if (newHeader.fileVersion >= 7)
                {
                    writer.Align16();
                }

                int headerSize = (int)(writer.Position - startPos);

                long totalCompressedSize = 0;
                List <AssetBundleBlockInfo06> newBlocks = new List <AssetBundleBlockInfo06>();
                List <Stream> newStreams = new List <Stream>(); //used if blockDirAtEnd == false

                long fileDataOffset = bundleHeader6.GetFileDataOffset();
                int  fileDataLength = (int)(bundleHeader6.totalFileSize - fileDataOffset);

                SegmentStream bundleDataStream = new SegmentStream(reader.BaseStream, fileDataOffset, fileDataLength);

                switch (compType)
                {
                case AssetBundleCompressionType.LZMA:
                {
                    Stream writeStream;
                    if (blockDirAtEnd)
                    {
                        writeStream = writer.BaseStream;
                    }
                    else
                    {
                        writeStream = GetTempFileStream();
                    }

                    long writeStreamStart = writeStream.Position;
                    SevenZipHelper.Compress(bundleDataStream, writeStream);
                    uint writeStreamLength = (uint)(writeStream.Position - writeStreamStart);

                    AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06()
                    {
                        compressedSize   = writeStreamLength,
                        decompressedSize = (uint)fileDataLength,
                        flags            = 0x41
                    };

                    totalCompressedSize += blockInfo.compressedSize;
                    newBlocks.Add(blockInfo);

                    if (!blockDirAtEnd)
                    {
                        newStreams.Add(writeStream);
                    }

                    break;
                }

                case AssetBundleCompressionType.LZ4:
                {
                    //compress into 0x20000 blocks
                    BinaryReader bundleDataReader  = new BinaryReader(bundleDataStream);
                    byte[]       uncompressedBlock = bundleDataReader.ReadBytes(0x20000);
                    while (uncompressedBlock.Length != 0)
                    {
                        Stream writeStream;
                        if (blockDirAtEnd)
                        {
                            writeStream = writer.BaseStream;
                        }
                        else
                        {
                            writeStream = GetTempFileStream();
                        }

                        byte[] compressedBlock = LZ4Codec.Encode32HC(uncompressedBlock, 0, uncompressedBlock.Length);

                        if (compressedBlock.Length > uncompressedBlock.Length)
                        {
                            writeStream.Write(uncompressedBlock, 0, uncompressedBlock.Length);

                            AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06()
                            {
                                compressedSize   = (uint)uncompressedBlock.Length,
                                decompressedSize = (uint)uncompressedBlock.Length,
                                flags            = 0x0
                            };

                            totalCompressedSize += blockInfo.compressedSize;

                            newBlocks.Add(blockInfo);
                        }
                        else
                        {
                            writeStream.Write(compressedBlock, 0, compressedBlock.Length);

                            AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06()
                            {
                                compressedSize   = (uint)compressedBlock.Length,
                                decompressedSize = (uint)uncompressedBlock.Length,
                                flags            = 0x3
                            };

                            totalCompressedSize += blockInfo.compressedSize;

                            newBlocks.Add(blockInfo);
                        }

                        if (!blockDirAtEnd)
                        {
                            newStreams.Add(writeStream);
                        }

                        uncompressedBlock = bundleDataReader.ReadBytes(0x20000);
                    }
                    break;
                }

                case AssetBundleCompressionType.NONE:
                {
                    AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06()
                    {
                        compressedSize   = (uint)fileDataLength,
                        decompressedSize = (uint)fileDataLength,
                        flags            = 0x00
                    };

                    totalCompressedSize += blockInfo.compressedSize;

                    newBlocks.Add(blockInfo);

                    if (blockDirAtEnd)
                    {
                        bundleDataStream.CopyToCompat(writer.BaseStream);
                    }
                    else
                    {
                        newStreams.Add(bundleDataStream);
                    }

                    break;
                }
                }

                newBlockAndDirList.blockInf = newBlocks.ToArray();

                byte[] bundleInfoBytes;
                using (MemoryStream memStream = new MemoryStream())
                {
                    AssetsFileWriter infoWriter = new AssetsFileWriter(memStream);
                    newBlockAndDirList.Write(infoWriter);
                    bundleInfoBytes = memStream.ToArray();
                }

                //listing is usually lz4 even if the data blocks are lzma
                byte[] bundleInfoBytesCom = LZ4Codec.Encode32HC(bundleInfoBytes, 0, bundleInfoBytes.Length);

                long totalFileSize = headerSize + bundleInfoBytesCom.Length + totalCompressedSize;
                newHeader.totalFileSize    = totalFileSize;
                newHeader.decompressedSize = (uint)bundleInfoBytes.Length;
                newHeader.compressedSize   = (uint)bundleInfoBytesCom.Length;

                if (!blockDirAtEnd)
                {
                    writer.Write(bundleInfoBytesCom);
                    foreach (Stream newStream in newStreams)
                    {
                        newStream.Position = 0;
                        newStream.CopyToCompat(writer.BaseStream);
                        newStream.Close();
                    }
                }
                else
                {
                    writer.Write(bundleInfoBytesCom);
                }

                writer.Position = 0;
                newHeader.Write(writer);
                if (newHeader.fileVersion >= 7)
                {
                    writer.Align16();
                }

                return(true);
            }
            return(false);
        }