예제 #1
0
        /// <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;
        }
예제 #2
0
        /// <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;
        }