/// <summary> /// Disassembles entire car parts block using <see cref="BinaryReader"/> provided /// into <see cref="DBModelPart"/> collections. /// </summary> /// <param name="br"><see cref="BinaryReader"/> to read data with.</param> /// <param name="size">Size of the block.</param> private void Decode(BinaryReader br, int size) { long position = br.BaseStream.Position; var offsets = this.FindOffsets(br, size); // We need to read part0 as well br.BaseStream.Position = offsets[0] + 0x24; int maxattrib = br.ReadInt32(); br.BaseStream.Position = offsets[0] + 0x2C; int maxmodels = br.ReadInt32(); br.BaseStream.Position = offsets[0] + 0x34; int maxstruct = br.ReadInt32(); br.BaseStream.Position = offsets[0] + 0x3C; int maxcparts = br.ReadInt32(); // Get all custom attributes var cpmap = this.ReadCustomCP(br, offsets[7]); // Initialize stream over string block br.BaseStream.Position = offsets[1]; var strlen = br.ReadInt32(); var strarr = br.ReadBytes(strlen); using var StrStream = new MemoryStream(strarr); using var StrReader = new BinaryReader(StrStream); // Read all attribute offsets br.BaseStream.Position = offsets[2]; var offset_dict = this.ReadOffsets(br); // Read all car part attributes br.BaseStream.Position = offsets[3]; var attrib_list = this.ReadAttribs(br, StrReader, maxattrib, cpmap); // Read all models br.BaseStream.Position = offsets[5]; var models_list = this.ReadModels(br, maxmodels); // Read all car part structs br.BaseStream.Position = offsets[4]; var tablen = br.ReadInt32(); var tabarr = br.ReadBytes(tablen); using var TabStream = new MemoryStream(tabarr); using var TabReader = new BinaryReader(TabStream); // Read all temporary parts br.BaseStream.Position = offsets[6]; var temp_cparts = this.ReadTempParts(br, maxcparts); // Increase capacity based on model count this.Capacity = models_list.Length; // Generate Model Collections for (int a1 = 0; a1 < models_list.Length; ++a1) { if (String.IsNullOrEmpty(models_list[a1])) { continue; } DBModelPart collection; try { collection = new DBModelPart(models_list[a1], this); } catch { continue; } // in case exists var tempparts = temp_cparts.FindAll(_ => _.Index == a1); foreach (var temppart in tempparts) { offset_dict.TryGetValue(temppart.AttribOffset, out var cpoff); var realpart = new Parts.CarParts.RealCarPart(collection, cpoff?.AttribOffsets.Count ?? 0); foreach (var attroff in cpoff?.AttribOffsets ?? Enumerable.Empty <ushort>()) { if (attroff >= attrib_list.Length) { continue; } var addon = (CPAttribute)attrib_list[attroff].PlainCopy(); if (addon is ModelTableAttribute tableattr) { tableattr.ReadStruct(TabReader, StrReader); } realpart.Attributes.Add(addon); } collection.ModelCarParts.Add(realpart); } try { this.Add(collection); } catch { } // skip if exists } br.BaseStream.Position = position + size; }
/// <summary> /// Disassembles entire car parts block using <see cref="BinaryReader"/> provided /// into <see cref="DBModelPart"/> collections. /// </summary> /// <param name="br"><see cref="BinaryReader"/> to read data with.</param> /// <param name="size">Size of the car parts block.</param> private void Decode(BinaryReader br, int size) { long position = br.BaseStream.Position; var offsets = this.FindOffsets(br, size); // We need to read part0 as well br.BaseStream.Position = offsets[0] + 0x14; int maxcparts = br.ReadInt32(); br.BaseStream.Position = offsets[0] + 0x1C; int maxattrib = br.ReadInt32(); // Get all custom attributes var cpmap = this.ReadCustomCP(br, offsets[4]); // Initialize stream over string block br.BaseStream.Position = offsets[1]; var length = br.ReadInt32(); var strarr = br.ReadBytes(length); using var StrStream = new MemoryStream(strarr); using var StrReader = new BinaryReader(StrStream); // Read all car part attributes br.BaseStream.Position = offsets[2]; var attrib_list = this.ReadAttribs(br, StrReader, maxattrib, cpmap); // Read all temporary parts br.BaseStream.Position = offsets[3]; var temp_cparts = this.ReadTempParts(br, StrReader, maxcparts); // Generate Model Collections int index = -1; foreach (var group in temp_cparts.GroupBy(_ => _.CarNameHash)) { ++index; var collection = new DBModelPart(group.Key.BinString(LookupReturn.EMPTY), this); foreach (var temppart in group) { var realpart = new Parts.CarParts.RealCarPart(collection, temppart.AttribEnd - temppart.AttribStart) { PartLabel = temppart.PartNameHash.BinString(LookupReturn.EMPTY), BrandLabel = temppart.BrandNameHash.BinString(LookupReturn.EMPTY), DebugName = temppart.DebugName, CarPartGroupID = temppart.CarPartGroupID, UpgradeGroupID = temppart.UpgradeGroupID, UpgradeStyle = temppart.UpgradeStyle, GeometryLodA = temppart.LodAHash.BinString(LookupReturn.EMPTY), GeometryLodB = temppart.LodBHash.BinString(LookupReturn.EMPTY), GeometryLodC = temppart.LodCHash.BinString(LookupReturn.EMPTY), GeometryLodD = temppart.LodDHash.BinString(LookupReturn.EMPTY), }; for (int a1 = temppart.AttribStart; a1 < temppart.AttribEnd; ++a1) { if (temppart.AttribOffset + a1 >= attrib_list.Length) { continue; } var addon = (CPAttribute)attrib_list[temppart.AttribOffset + a1].PlainCopy(); realpart.Attributes.Add(addon); } collection.ModelCarParts.Add(realpart); } try { this.Add(collection); } catch { } // skip if exists } br.BaseStream.Position = position + size; }