public override long WriteReplacer(AssetsFileWriter writer)
        {
            writer.Write((short)2); //replacer type
            writer.Write((byte)1);  //file type (0 bundle, 1 assets)
            writer.Write((byte)1);  //idk, always 1
            writer.Write(0);        //always 0 even when fileid is something else
            writer.Write(GetPathID());
            writer.Write(GetClassID());
            writer.Write(GetMonoScriptID());

            writer.Write(preloadList.Count);
            for (int i = 0; i < preloadList.Count; i++)
            {
                writer.Write(preloadList[i].fileID);
                writer.Write(preloadList[i].pathID);
            }

            //flag1, unknown
            writer.Write((byte)0);
            //flag2
            if (propertiesHash.data != null)
            {
                writer.Write((byte)1);
                writer.Write(propertiesHash.data);
            }
            else
            {
                writer.Write((byte)0);
            }
            //flag3
            if (scriptIdHash.data != null)
            {
                writer.Write((byte)1);
                writer.Write(scriptIdHash.data);
            }
            else
            {
                writer.Write((byte)0);
            }
            //flag4
            if (file != null)
            {
                writer.Write((byte)1);
                file.Write(writer);
            }
            else
            {
                writer.Write((byte)0);
            }

            writer.Write(GetSize());
            Write(writer);

            return(writer.Position);
        }
示例#2
0
        public void Write(AssetsFileWriter writer, int optimizeStringTable = 1, int compress = 1)
        {
            long filePos = writer.BaseStream.Position;

            //lol don't do this if compress is 0
            if ((compress & 0x80) == 0)
            {
                throw new NotImplementedException("Compression flag 0x80 must be used");
            }

            //compress 1 for lz4 and 2 for lzma
            //this is backwards from assets files

            //build string table
            StringBuilder             strTableBuilder = new StringBuilder();
            Dictionary <string, uint> strTableMap;

            if (optimizeStringTable != 0)
            {
                strTableMap = new Dictionary <string, uint>();
            }
            else
            {
                strTableMap = null;
            }

            foreach (ClassDatabaseFile cldb in files)
            {
                for (int i = 0; i < cldb.classes.Count; i++)
                {
                    ClassDatabaseType type = cldb.classes[i];

                    AddStringTableEntry(cldb, strTableBuilder, strTableMap, ref type.name);

                    if (header.fileVersion == 4 && (cldb.header.flags & 1) != 0)
                    {
                        AddStringTableEntry(cldb, strTableBuilder, strTableMap, ref type.assemblyFileName);
                    }

                    List <ClassDatabaseTypeField> fields = type.fields;
                    for (int j = 0; j < fields.Count; j++)
                    {
                        ClassDatabaseTypeField field = fields[j];
                        AddStringTableEntry(cldb, strTableBuilder, strTableMap, ref field.fieldName);
                        AddStringTableEntry(cldb, strTableBuilder, strTableMap, ref field.typeName);
                        fields[j] = field;
                    }
                }
            }

            header.fileCount = (uint)files.Count;
            header.Write(writer);

            using (MemoryStream cldbMs = new MemoryStream())
                using (AssetsFileWriter cldbWriter = new AssetsFileWriter(cldbMs))
                {
                    //annoyingly, files and header.files are two different lists...
                    for (int i = 0; i < files.Count; i++)
                    {
                        ClassDatabaseFile cldb = files[i];
                        long cldbStartFilePos  = cldbWriter.BaseStream.Position;

                        //does not support 0x80 self compression rn
                        cldb.Write(cldbWriter, 0, 0, false);
                        long cldbEndFilePos = cldbWriter.BaseStream.Position;

                        string cldbName = header.files[i].name;
                        header.files[i] = new ClassDatabaseFileRef()
                        {
                            offset = (uint)cldbStartFilePos,
                            length = (uint)(cldbEndFilePos - cldbStartFilePos),
                            name   = cldbName
                        };
                    }

                    header.fileBlockSize = (uint)cldbMs.Length;

                    cldbMs.Position = 0;
                    if ((compress & 0x20) == 0)     //compressed
                    {
                        if ((compress & 0x1f) == 1) //lz4
                        {
                            byte[] compressedBlock = LZ4Codec.Encode32HC(cldbMs.ToArray(), 0, (int)cldbMs.Length);
                            writer.Write(compressedBlock);
                        }
                        else if ((compress & 0x1f) == 2) //lzma
                        {
                            byte[] compressedBlock = SevenZipHelper.Compress(cldbMs.ToArray());
                            writer.Write(compressedBlock);
                        }
                        else
                        {
                            throw new ArgumentException("File marked as compressed but no valid compression option set!");
                        }
                    }
                    else //write normally
                    {
                        cldbMs.CopyToCompat(writer.BaseStream);
                    }
                }

            header.stringTableOffset = (uint)writer.Position;

            byte[] stringTableBytes = Encoding.ASCII.GetBytes(strTableBuilder.ToString());

            header.stringTableLenUncompressed = (uint)stringTableBytes.Length;

            if ((compress & 0x40) == 0)     //string table is compressed
            {
                if ((compress & 0x1f) == 1) //lz4
                {
                    stringTableBytes = LZ4Codec.Encode32HC(stringTableBytes, 0, stringTableBytes.Length);
                }
                else if ((compress & 0x1f) == 2) //lzma
                {
                    stringTableBytes = SevenZipHelper.Compress(stringTableBytes);
                }
                else
                {
                    throw new ArgumentException("File marked as compressed but no valid compression option set!");
                }
            }

            header.stringTableLenCompressed = (uint)stringTableBytes.Length;

            writer.Write(stringTableBytes);

            writer.Position        = filePos;
            header.compressionType = (byte)compress;
            header.Write(writer);
        }