Ejemplo n.º 1
0
 public virtual void CopyInFromBinary(
     IOutfitInternal item,
     MutagenFrame frame,
     RecordTypeConverter?recordTypeConverter = null)
 {
     UtilityTranslation.MajorRecordParse <IOutfitInternal>(
         record: item,
         frame: frame,
         recordTypeConverter: recordTypeConverter,
         fillStructs: OutfitBinaryCreateTranslation.FillBinaryStructs,
         fillTyped: OutfitBinaryCreateTranslation.FillBinaryRecordTypes);
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Iterates a MajorRecordFrame's subrecords and locates the first occurance of the desired type
        /// </summary>
        /// <param name="majorFrame">Frame to read from</param>
        /// <param name="type">Type to search for</param>
        /// <param name="offset">Offset within the Major Record's contents to start searching</param>
        /// <param name="frame">SubrecordFrame if found</param>
        /// <param name="loc">Location of the subrecord, relative to the parent record's RecordType data</param>
        /// <returns>True if matching subrecord is found</returns>
        public static bool TryLocateSubrecordFrame(this MajorRecordFrame majorFrame, RecordType type, int offset, out SubrecordFrame frame, out int loc)
        {
            var find = UtilityTranslation.FindFirstSubrecord(majorFrame.Content.Slice(offset - majorFrame.HeaderLength), majorFrame.Meta, type, navigateToContent: false);

            if (find == null)
            {
                frame = default;
                loc   = default;
                return(false);
            }
            frame = new SubrecordFrame(majorFrame.Meta, majorFrame.Content.Slice(find.Value + offset - majorFrame.HeaderLength));
            loc   = find.Value + offset;
            return(true);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Iterates a MajorRecordFrame's contents and locates the first occurance of the desired type
        /// </summary>
        /// <param name="majorFrame">Frame to read from</param>
        /// <param name="type">Type to search for</param>
        /// <param name="header">SubrecordHeader if found</param>
        /// <param name="loc">Location of the subrecord, relative to the parent record's RecordType data</param>
        /// <returns>True if matching subrecord is found</returns>
        public static bool TryLocateSubrecord(this MajorRecordFrame majorFrame, RecordType type, out SubrecordHeader header, out int loc)
        {
            var find = UtilityTranslation.FindFirstSubrecord(majorFrame.Content, majorFrame.Meta, type, navigateToContent: false);

            if (find == null)
            {
                header = default;
                loc    = default;
                return(false);
            }
            header = new SubrecordHeader(majorFrame.Meta, majorFrame.Content.Slice(find.Value));
            loc    = find.Value + majorFrame.HeaderLength;
            return(true);
        }
Ejemplo n.º 4
0
 public virtual void CopyInFromBinary(
     IVirtualMachineAdapter item,
     MutagenFrame frame,
     RecordTypeConverter?recordTypeConverter = null)
 {
     frame = frame.SpawnWithFinalPosition(HeaderTranslation.ParseSubrecord(
                                              frame.Reader,
                                              recordTypeConverter.ConvertToCustom(RecordTypes.VMAD)));
     UtilityTranslation.SubrecordParse(
         record: item,
         frame: frame,
         recordTypeConverter: recordTypeConverter,
         fillStructs: VirtualMachineAdapterBinaryCreateTranslation.FillBinaryStructs);
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Retrieves the character representing a Global's data type from a MajorRecordFrame
        /// </summary>
        /// <param name="frame">Frame to retrieve from</param>
        /// <returns>Character representing data type</returns>
        /// <exception cref="ArgumentException">If FNAM not present or malformed</exception>
        public static char GetGlobalChar(MajorRecordFrame frame)
        {
            var subrecordSpan = frame.Content;
            var fnamLocation  = UtilityTranslation.FindFirstSubrecord(subrecordSpan, frame.Header.Meta, FNAM);

            if (fnamLocation == null)
            {
                throw new ArgumentException($"Could not find FNAM.");
            }
            var fnamMeta = frame.Header.Meta.SubrecordFrame(subrecordSpan.Slice(fnamLocation.Value));

            if (fnamMeta.Content.Length != 1)
            {
                throw new ArgumentException($"FNAM had non 1 length: {fnamMeta.Content.Length}");
            }
            return((char)fnamMeta.Content[0]);
        }
Ejemplo n.º 6
0
            public static void WriteSubBlocksParallel(
                ICellSubBlockGetter subBlock,
                MasterReferenceReader masters,
                int targetIndex,
                GameConstants gameConstants,
                Stream[] streamDepositArray)
            {
                var cells = subBlock.Cells;

                Stream[] streams         = new Stream[(cells?.Count ?? 0) + 1];
                byte[]   groupBytes      = new byte[gameConstants.GroupConstants.HeaderLength];
                var      groupByteStream = new MemoryStream(groupBytes);

                BinaryPrimitives.WriteInt32LittleEndian(groupBytes.AsSpan(), RecordTypes.GRUP.TypeInt);
                using (var stream = new MutagenWriter(
                           groupByteStream,
                           meta: new WritingBundle(gameConstants)
                {
                    MasterReferences = masters
                },
                           dispose: false))
                {
                    stream.Position += 8;
                    CellSubBlockBinaryWriteTranslation.WriteEmbedded(subBlock, stream);
                }
                streams[0] = groupByteStream;
                if (cells != null)
                {
                    Parallel.ForEach(cells, (cell, state, counter) =>
                    {
                        MemoryTributary trib = new MemoryTributary();
                        cell.WriteToBinary(new MutagenWriter(
                                               trib,
                                               new WritingBundle(gameConstants)
                        {
                            MasterReferences = masters
                        },
                                               dispose: false));
                        streams[(int)counter + 1] = trib;
                    });
                }
                UtilityTranslation.CompileSetGroupLength(streams, groupBytes);
                streamDepositArray[targetIndex] = new CompositeReadStream(streams, resetPositions: true);
            }
Ejemplo n.º 7
0
            public static void WriteGroupParallel <T>(
                IGroupGetter <T> group,
                MasterReferenceReader masters,
                int targetIndex,
                GameConstants gameConstants,
                Stream[] streamDepositArray)
                where T : class, ISkyrimMajorRecordGetter, IBinaryItem
            {
                if (group.RecordCache.Count == 0)
                {
                    return;
                }
                var cuts = group.Cut(CutCount).ToArray();

                Stream[] subStreams = new Stream[cuts.Length + 1];
                byte[]   groupBytes = new byte[gameConstants.GroupConstants.HeaderLength];
                BinaryPrimitives.WriteInt32LittleEndian(groupBytes.AsSpan(), RecordTypes.GRUP.TypeInt);
                var groupByteStream = new MemoryStream(groupBytes);

                using (var stream = new MutagenWriter(groupByteStream, gameConstants, dispose: false))
                {
                    stream.Position += 8;
                    GroupBinaryWriteTranslation.WriteEmbedded <T>(group, stream);
                }
                subStreams[0] = groupByteStream;
                Parallel.ForEach(cuts, (cutItems, state, counter) =>
                {
                    MemoryTributary trib = new MemoryTributary();
                    var bundle           = new WritingBundle(gameConstants)
                    {
                        MasterReferences = masters
                    };
                    using (var stream = new MutagenWriter(trib, bundle, dispose: false))
                    {
                        foreach (var item in cutItems)
                        {
                            item.WriteToBinary(stream);
                        }
                    }
                    subStreams[(int)counter + 1] = trib;
                });
                UtilityTranslation.CompileSetGroupLength(subStreams, groupBytes);
                streamDepositArray[targetIndex] = new CompositeReadStream(subStreams, resetPositions: true);
            }
Ejemplo n.º 8
0
        private void ProcessRegions(
            MajorRecordFrame majorFrame,
            long fileOffset)
        {
            var rdat = UtilityTranslation.FindFirstSubrecord(majorFrame.Content, majorFrame.Meta, RecordTypes.RDAT, navigateToContent: false);

            if (rdat == null)
            {
                return;
            }

            // Order RDATs by index
            SortedList <uint, RangeInt64> rdats = new SortedList <uint, RangeInt64>();
            List <uint> raw = new List <uint>();

            while (rdat != null)
            {
                var rdatHeader = majorFrame.Meta.SubrecordFrame(majorFrame.Content.Slice(rdat.Value));
                var index      = BinaryPrimitives.ReadUInt32LittleEndian(rdatHeader.Content);
                var nextRdat   = UtilityTranslation.FindFirstSubrecord(
                    majorFrame.Content,
                    majorFrame.Meta,
                    RecordTypes.RDAT,
                    navigateToContent: false,
                    offset: rdat.Value + rdatHeader.TotalLength);
                rdats[index] =
                    new RangeInt64(
                        fileOffset + majorFrame.HeaderLength + rdat.Value,
                        nextRdat == null ? fileOffset + majorFrame.TotalLength - 1 : nextRdat.Value - 1 + fileOffset + majorFrame.HeaderLength);
                raw.Add(index);
                rdat = nextRdat;
            }
            if (raw.SequenceEqual(rdats.Keys))
            {
                return;
            }
            foreach (var item in rdats.Reverse())
            {
                this._Instructions.SetMove(
                    loc: fileOffset + majorFrame.TotalLength,
                    section: item.Value);
            }
        }
Ejemplo n.º 9
0
        public bool IsOfRecordType <T>(FormID formID)
            where T : IMajorRecordCommonGetter
        {
            if (formID == FormID.Null)
            {
                return(false);
            }
            lock (_cachedLocs)
            {
                if (!_cachedLocs.TryGetValue(typeof(T), out var cache))
                {
                    using var stream = _streamCreator();
                    var locs = RecordLocator.GetFileLocations(
                        stream,
                        new RecordInterest(
                            interestingTypes: UtilityTranslation.GetRecordType <T>()));
                    cache = locs.FormIDs.ToHashSet();

                    _cachedLocs.Add(typeof(T), cache);
                }
                return(cache.Contains(formID));
            }
        }
Ejemplo n.º 10
0
 public void EnumerateSubrecords_Empty()
 {
     byte[] b = new byte[0];
     Assert.Empty(UtilityTranslation.EnumerateSubrecords(new ReadOnlyMemorySlice <byte>(b), GameConstants.Oblivion));
 }
Ejemplo n.º 11
0
 public void FindFirstSubrecord_Duplicate()
 {
     Assert.Equal(FirstTypicalLocation, UtilityTranslation.FindFirstSubrecord(GetTypical(), GameConstants.Oblivion, FirstTypicalType));
 }
Ejemplo n.º 12
0
        public void FindFirstSubrecord_Empty()
        {
            var b = new byte[0];

            Assert.Null(UtilityTranslation.FindFirstSubrecord(b, GameConstants.Oblivion, SecondTypicalType));
        }
Ejemplo n.º 13
0
            public static void WriteWorldspacesParallel(
                IGroupGetter <IWorldspaceGetter> group,
                MasterReferenceReader masters,
                int targetIndex,
                Stream[] streamDepositArray)
            {
                var cache = group.RecordCache;

                if (cache == null || cache.Count == 0)
                {
                    return;
                }
                Stream[] streams = new Stream[cache.Count + 1];
                var      bundle  = new WritingBundle(GameConstants.Oblivion)
                {
                    MasterReferences = masters
                };

                byte[] groupBytes = new byte[GameConstants.Oblivion.GroupConstants.HeaderLength];
                BinaryPrimitives.WriteInt32LittleEndian(groupBytes.AsSpan(), RecordTypes.GRUP.TypeInt);
                var groupByteStream = new MemoryStream(groupBytes);

                using (var stream = new MutagenWriter(groupByteStream, GameConstants.Oblivion, dispose: false))
                {
                    stream.Position += 8;
                    GroupBinaryWriteTranslation.WriteEmbedded <IWorldspaceGetter>(group, stream);
                }
                streams[0] = groupByteStream;
                Parallel.ForEach(group, (worldspace, worldspaceState, worldspaceCounter) =>
                {
                    var worldTrib = new MemoryTributary();
                    using (var writer = new MutagenWriter(worldTrib, bundle, dispose: false))
                    {
                        using (HeaderExport.Header(
                                   writer: writer,
                                   record: RecordTypes.WRLD,
                                   type: ObjectType.Record))
                        {
                            WorldspaceBinaryWriteTranslation.WriteEmbedded(
                                item: worldspace,
                                writer: writer);
                            WorldspaceBinaryWriteTranslation.WriteRecordTypes(
                                item: worldspace,
                                writer: writer,
                                recordTypeConverter: null);
                        }
                    }
                    var road     = worldspace.Road;
                    var topCell  = worldspace.TopCell;
                    var subCells = worldspace.SubCells;
                    if (subCells?.Count == 0 &&
                        road == null &&
                        topCell == null)
                    {
                        streams[worldspaceCounter + 1] = worldTrib;
                        return;
                    }

                    Stream[] subStreams = new Stream[(subCells?.Count ?? 0) + 1];

                    var worldGroupTrib   = new MemoryTributary();
                    var worldGroupWriter = new MutagenWriter(worldGroupTrib, bundle, dispose: false);
                    worldGroupWriter.Write(RecordTypes.GRUP.TypeInt);
                    worldGroupWriter.Write(UtilityTranslation.Zeros.Slice(0, GameConstants.Oblivion.GroupConstants.LengthLength));
                    FormKeyBinaryTranslation.Instance.Write(
                        worldGroupWriter,
                        worldspace.FormKey);
                    worldGroupWriter.Write((int)GroupTypeEnum.WorldChildren);
                    worldGroupWriter.Write(worldspace.SubCellsTimestamp);
                    road?.WriteToBinary(worldGroupWriter);
                    topCell?.WriteToBinary(worldGroupWriter);
                    subStreams[0] = worldGroupTrib;

                    if (subCells != null)
                    {
                        Parallel.ForEach(subCells, (block, blockState, blockCounter) =>
                        {
                            WriteBlocksParallel(
                                block,
                                masters,
                                (int)blockCounter + 1,
                                subStreams);
                        });
                    }

                    worldGroupWriter.Position = 4;
                    worldGroupWriter.Write((uint)(subStreams.NotNull().Select(s => s.Length).Sum()));
                    streams[worldspaceCounter + 1] = new CompositeReadStream(worldTrib.AsEnumerable().And(subStreams), resetPositions: true);
                });
                UtilityTranslation.CompileSetGroupLength(streams, groupBytes);
                streamDepositArray[targetIndex] = new CompositeReadStream(streams, resetPositions: true);
            }
Ejemplo n.º 14
0
        private void ProcessPackages(
            MajorRecordFrame majorFrame,
            long fileOffset)
        {
            // Reorder Idle subrecords

            // Reorder data values
            var xnamPos = UtilityTranslation.FindFirstSubrecord(majorFrame.Content, majorFrame.Meta, RecordTypes.XNAM);

            if (xnamPos == null)
            {
                throw new ArgumentException();
            }

            if (!majorFrame.TryLocateSubrecordFrame(RecordTypes.PKCU, out var pkcuRec))
            {
                throw new ArgumentException();
            }
            var count = pkcuRec.Content.Int32();

            if (count == 0)
            {
                return;
            }

            var        anamPos = UtilityTranslation.FindFirstSubrecord(majorFrame.Content, majorFrame.Meta, RecordTypes.ANAM);
            RecordType pldt    = new RecordType("PLDT");
            RecordType ptda    = new RecordType("PTDA");
            RecordType pdto    = new RecordType("PDTO");
            RecordType tpic    = new RecordType("TPIC");
            RecordType unam    = new RecordType("UNAM");
            RecordType bnam    = new RecordType("BNAM");
            RecordType pnam    = new RecordType("PNAM");

            // Reorder data values to be in index ordering
            if (anamPos.HasValue && anamPos.Value < xnamPos.Value)
            {
                var startLoc   = anamPos.Value;
                var dataValues = new List <(sbyte Index, ReadOnlyMemorySlice <byte> Data)>();
                var curLoc     = startLoc;
                while (anamPos.HasValue && anamPos.Value < xnamPos.Value)
                {
                    var anamRecord = majorFrame.Meta.SubrecordFrame(majorFrame.Content.Slice(anamPos.Value));
                    var recs       = UtilityTranslation.FindNextSubrecords(
                        majorFrame.Content.Slice(anamPos.Value + anamRecord.TotalLength),
                        majorFrame.Meta,
                        out var _,
                        RecordTypes.ANAM,
                        RecordTypes.CNAM,
                        pldt,
                        ptda,
                        pdto,
                        tpic);
                    int finalLoc;
                    if (recs[0] == null)
                    {
                        finalLoc = recs.NotNull().Max();
                    }
                    else if (recs[0] == 0)
                    {
                        dataValues.Add(
                            (-1, majorFrame.Content.Slice(anamPos.Value, anamRecord.TotalLength)));
                        curLoc  = anamPos.Value + anamRecord.TotalLength;
                        anamPos = anamPos.Value + anamRecord.TotalLength;
                        continue;
                    }
                    else
                    {
                        finalLoc = recs
                                   .NotNull()
                                   .Where(i => i < recs[0] !.Value)
                                   .Max();
                    }
                    var finalRec  = majorFrame.Meta.Subrecord(majorFrame.Content.Slice(anamPos.Value + anamRecord.TotalLength + finalLoc));
                    var dataSlice = majorFrame.Content.Slice(anamPos.Value, anamRecord.TotalLength + finalLoc + finalRec.TotalLength);
                    if (BinaryStringUtility.ProcessWholeToZString(anamRecord.Content) == "Bool" &&
                        recs[1] != null)
                    {
                        // Ensure bool value is 1 or 0
                        var cnam = majorFrame.Meta.SubrecordFrame(majorFrame.Content.Slice(anamPos.Value + anamRecord.TotalLength + recs[1].Value));
                        if (cnam.Content.Length != 1)
                        {
                            throw new ArgumentException();
                        }
                        if (cnam.Content[0] > 1)
                        {
                            var bytes     = dataSlice.ToArray();
                            int boolIndex = anamRecord.TotalLength + recs[1].Value + cnam.HeaderLength;
                            bytes[boolIndex] = (byte)(bytes[boolIndex] > 0 ? 1 : 0);
                            dataSlice        = bytes;
                        }
                    }
                    dataValues.Add((-1, dataSlice));

                    curLoc  = anamPos.Value + anamRecord.TotalLength + finalLoc + finalRec.TotalLength;
                    anamPos = anamPos.Value + anamRecord.TotalLength + recs[0];
                }

                var unamLocs = UtilityTranslation.ParseRepeatingSubrecord(
                    majorFrame.Content.Slice(curLoc),
                    majorFrame.Meta,
                    unam,
                    out var _);
                if (unamLocs == null ||
                    unamLocs.Length != dataValues.Count ||
                    unamLocs.Length != count)
                {
                    throw new ArgumentException();
                }

                for (sbyte i = 0; i < unamLocs.Length; i++)
                {
                    var unamRec = majorFrame.Meta.SubrecordFrame(majorFrame.Content.Slice(curLoc + unamLocs[i]));
                    dataValues[i] = (
                        (sbyte)unamRec.Content[0],
                        dataValues[i].Data);
                }

                var subLoc = startLoc;
                foreach (var item in dataValues.OrderBy(i => i.Index))
                {
                    _Instructions.SetSubstitution(
                        fileOffset + majorFrame.HeaderLength + subLoc,
                        item.Data.ToArray());
                    subLoc += item.Data.Length;
                }
                foreach (var item in dataValues.OrderBy(i => i.Index))
                {
                    byte[] bytes = new byte[] { 0x55, 0x4E, 0x41, 0x4D, 0x01, 0x00, 0x00 };
                    bytes[6] = (byte)item.Index;
                    _Instructions.SetSubstitution(
                        fileOffset + majorFrame.HeaderLength + subLoc,
                        bytes.ToArray());
                    subLoc += bytes.Length;
                }
            }

            // Reorder inputs
            var unamPos = UtilityTranslation.FindFirstSubrecord(majorFrame.Content.Slice(xnamPos.Value), majorFrame.Meta, unam);

            if (!unamPos.HasValue)
            {
                return;
            }
            unamPos += xnamPos.Value;
            var writeLoc    = fileOffset + majorFrame.HeaderLength + unamPos.Value;
            var inputValues = new List <(sbyte Index, ReadOnlyMemorySlice <byte> Data)>();

            while (unamPos.HasValue)
            {
                var unamRecord = majorFrame.Meta.SubrecordFrame(majorFrame.Content.Slice(unamPos.Value));
                var recs       = UtilityTranslation.FindNextSubrecords(
                    majorFrame.Content.Slice(unamPos.Value + unamRecord.TotalLength),
                    majorFrame.Meta,
                    out var _,
                    unam,
                    bnam,
                    pnam);
                int finalLoc;
                if (recs[0] == null)
                {
                    finalLoc = recs.NotNull().Max();
                }
                else if (recs[0] == 0)
                {
                    inputValues.Add(
                        ((sbyte)unamRecord.Content[0], majorFrame.Content.Slice(unamPos.Value, unamRecord.TotalLength)));
                    unamPos = unamPos.Value + unamRecord.TotalLength;
                    continue;
                }
                else
                {
                    finalLoc = recs
                               .NotNull()
                               .Where(i => i < recs[0] !.Value)
                               .Max();
                }
                var finalRec = majorFrame.Meta.Subrecord(majorFrame.Content.Slice(unamPos.Value + unamRecord.TotalLength + finalLoc));
                inputValues.Add(
                    ((sbyte)unamRecord.Content[0], majorFrame.Content.Slice(unamPos.Value, unamRecord.TotalLength + finalLoc + finalRec.TotalLength)));

                unamPos = unamPos.Value + unamRecord.TotalLength + recs[0];
            }
            foreach (var item in inputValues.OrderBy(i => i.Index))
            {
                _Instructions.SetSubstitution(
                    writeLoc,
                    item.Data.ToArray());
                writeLoc += item.Data.Length;
            }
        }
Ejemplo n.º 15
0
        private void ProcessQuests(
            MajorRecordFrame majorFrame,
            long fileOffset)
        {
            if (majorFrame.TryLocateSubrecordFrame(RecordTypes.ANAM, out var anamRec, out var anamIndex))
            {
                var next    = anamRec.AsUInt32();
                var targets = new RecordType[]
                {
                    RecordTypes.ALST,
                    RecordTypes.ALLS
                };
                var locs = UtilityTranslation.FindAllOfSubrecords(
                    majorFrame.Content,
                    majorFrame.Meta,
                    targets.ToGetter(),
                    navigateToContent: true);
                uint actualNext = 0;
                if (locs.Length > 0)
                {
                    actualNext = locs
                                 .Select(l =>
                    {
                        return(BinaryPrimitives.ReadUInt32LittleEndian(majorFrame.Content.Slice(l)));
                    })
                                 .Max();
                    actualNext++;
                }
                if (actualNext != next)
                {
                    byte[] sub = new byte[4];
                    BinaryPrimitives.WriteUInt32LittleEndian(sub, actualNext);
                    _Instructions.SetSubstitution(
                        fileOffset + anamIndex + anamRec.HeaderLength,
                        sub);
                }
            }

            var sizeChange = FixMissingCounters(
                majorFrame,
                fileOffset,
                new RecordType("COCT"),
                new RecordType("CNTO"));

            ProcessLengths(
                majorFrame,
                sizeChange,
                fileOffset);

            FixVMADFormIDs(
                majorFrame,
                fileOffset,
                out var vmadPos,
                out var objectFormat,
                out var processedLen);
            if (vmadPos != null)
            {
                var vmadFrame = Meta.SubrecordFrame(majorFrame.Content.Slice(vmadPos.Value));
                var stream    = new MutagenMemoryReadStream(vmadFrame.Content, Bundle)
                {
                    Position = processedLen - vmadFrame.HeaderLength
                };
                if (stream.Complete)
                {
                    return;
                }
                // skip unknown
                stream.Position += 1;
                var fragCount = stream.ReadUInt16();
                // skip name
                var len = stream.ReadUInt16();
                stream.Position += len;
                for (int i = 0; i < fragCount; i++)
                {
                    stream.Position += 9;
                    // skip name
                    len              = stream.ReadUInt16();
                    stream.Position += len;
                    // skip name
                    len              = stream.ReadUInt16();
                    stream.Position += len;
                }
                var aliasCount = stream.ReadUInt16();
                for (int i = 0; i < aliasCount; i++)
                {
                    FixObjectPropertyIDs(stream, fileOffset, objectFormat);
                    // skip version
                    stream.Position += 2;
                    objectFormat     = stream.ReadUInt16();
                    var numScripts = stream.ReadUInt16();
                    for (int j = 0; j < numScripts; j++)
                    {
                        FixVMADScriptIDs(stream, fileOffset, objectFormat);
                    }
                }
            }
        }
Ejemplo n.º 16
0
 void BipedObjectNamesCustomParse(OverlayStream stream, int finalPos, int offset)
 {
     _bipedObjectNamesLoc = (ushort)(stream.Position - offset);
     UtilityTranslation.SkipPastAll(stream, _package.MetaData.Constants, RecordTypes.NAME);
 }