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); } }
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); }
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; }