Пример #1
0
        public ulong Read(AssetsFileReader reader, ulong filePos, int version)
        {
            classId   = reader.ReadInt32();
            baseClass = reader.ReadInt32();
            name      = new ClassDatabaseFileString();
            name.Read(reader, reader.Position);
            uint fieldCount = reader.ReadUInt32();

            fields = new List <ClassDatabaseTypeField>();
            for (int i = 0; i < fieldCount; i++)
            {
                ClassDatabaseTypeField cdtf = new ClassDatabaseTypeField();
                cdtf.Read(reader, filePos, version);
                fields.Add(cdtf);
            }
            return(reader.Position);
        }
        public bool FromClassDatabase(ClassDatabaseFile pFile, ClassDatabaseType pType, uint fieldIndex)
        {
            ClassDatabaseTypeField field = pType.fields[(int)fieldIndex];

            name      = field.fieldName.GetString(pFile);
            type      = field.typeName.GetString(pFile);
            valueType = AssetTypeValueField.GetValueTypeByTypeName(type);
            isArray   = field.isArray == 1 ? true : false;
            align     = (field.flags2 & 0x4000) != 0x00 ? true : false;
            hasValue  = (valueType == EnumValueTypes.ValueType_None) ? false : true;

            List <int> childrenIndexes = new List <int>();
            int        thisDepth       = pType.fields[(int)fieldIndex].depth;

            for (int i = (int)fieldIndex + 1; i < pType.fields.Count; i++)
            {
                if (pType.fields[i].depth == thisDepth + 1)
                {
                    childrenCount++;
                    childrenIndexes.Add(i);
                }
                if (pType.fields[i].depth <= thisDepth)
                {
                    break;
                }
            }
            children = new AssetTypeTemplateField[childrenCount];
            int child = 0;

            for (int i = (int)fieldIndex + 1; i < pType.fields.Count; i++)
            {
                if (pType.fields[i].depth == thisDepth + 1)
                {
                    children[child] = new AssetTypeTemplateField();
                    children[child].FromClassDatabase(pFile, pType, (uint)childrenIndexes[child]);
                    child++;
                }
                if (pType.fields[i].depth <= thisDepth)
                {
                    break;
                }
            }
            return(true);
        }
        public void Read(AssetsFileReader reader, int version, byte flags)
        {
            classId   = reader.ReadInt32();
            baseClass = reader.ReadInt32();
            name      = new ClassDatabaseFileString();
            name.Read(reader);
            if ((flags & 1) != 0)
            {
                assemblyFileName = new ClassDatabaseFileString();
                assemblyFileName.Read(reader);
            }
            uint fieldCount = reader.ReadUInt32();

            fields = new List <ClassDatabaseTypeField>();
            for (int i = 0; i < fieldCount; i++)
            {
                ClassDatabaseTypeField cdtf = new ClassDatabaseTypeField();
                cdtf.Read(reader, version);
                fields.Add(cdtf);
            }
        }
Пример #4
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);
        }
Пример #5
0
        public void Write(AssetsFileWriter writer, int optimizeStringTable = 1, int compress = 1, bool writeStringTable = true)
        {
            long filePos = writer.BaseStream.Position;

            byte[] newStrTable = stringTable;

            //"optimize string table (slow)" mode 2 not supported
            //ex: >AABB\0>localAABB\0 can be just >local>AABB\0
            if (optimizeStringTable == 1)
            {
                StringBuilder             strTableBuilder = new StringBuilder();
                Dictionary <string, uint> strTableMap     = new Dictionary <string, uint>();
                for (int i = 0; i < classes.Count; i++)
                {
                    ClassDatabaseType type = classes[i];

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

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

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

            header.Write(writer);
            writer.Write(classes.Count);
            for (int i = 0; i < classes.Count; i++)
            {
                classes[i].Write(writer, header.fileVersion, header.flags);
            }

            long stringTablePos = writer.Position;

            //set false only for tpk packing, don't set false anytime else!
            if (writeStringTable)
            {
                writer.Write(newStrTable);
            }

            long fileEndPos = writer.Position;

            long stringTableLen = writer.Position - stringTablePos;
            long fileSize       = writer.Position;

            header.stringTablePos   = (uint)stringTablePos;
            header.stringTableLen   = (uint)stringTableLen;
            header.uncompressedSize = (uint)fileSize;

            writer.Position = filePos;
            header.Write(writer);

            writer.Position = fileEndPos;
        }