Exemplo n.º 1
0
            public static void WriteBlocksParallel(
                ICellBlockGetter block,
                MasterReferenceReader masters,
                int targetIndex,
                Stream[] streamDepositArray)
            {
                var subBlocks = block.SubBlocks;

                Stream[] streams    = new Stream[(subBlocks?.Count ?? 0) + 1];
                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;
                    CellBlockBinaryWriteTranslation.WriteEmbedded(block, stream);
                }
                streams[0] = groupByteStream;
                if (subBlocks != null)
                {
                    Parallel.ForEach(subBlocks, (cellSubBlock, state, counter) =>
                    {
                        WriteSubBlocksParallel(
                            cellSubBlock,
                            masters,
                            (int)counter + 1,
                            streams);
                    });
                }
                PluginUtilityTranslation.CompileSetGroupLength(streams, groupBytes);
                streamDepositArray[targetIndex] = new CompositeReadStream(streams, resetPositions: true);
            }
Exemplo n.º 2
0
            public static void WriteSubBlocksParallel(
                IWorldspaceSubBlockGetter subBlock,
                MasterReferenceReader masters,
                int targetIndex,
                Stream[] streamDepositArray)
            {
                var items  = subBlock.Items;
                var bundle = new WritingBundle(GameConstants.Oblivion)
                {
                    MasterReferences = masters
                };

                Stream[] streams    = new Stream[(items?.Count ?? 0) + 1];
                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, bundle, dispose: false))
                {
                    stream.Position += 8;
                    WorldspaceSubBlockBinaryWriteTranslation.WriteEmbedded(subBlock, stream);
                }
                streams[0] = groupByteStream;
                if (items != null)
                {
                    Parallel.ForEach(items, (cell, state, counter) =>
                    {
                        MemoryTributary trib = new MemoryTributary();
                        cell.WriteToBinary(new MutagenWriter(trib, bundle, dispose: false));
                        streams[(int)counter + 1] = trib;
                    });
                }
                PluginUtilityTranslation.CompileSetGroupLength(streams, groupBytes);
                streamDepositArray[targetIndex] = new CompositeReadStream(streams, resetPositions: true);
            }
Exemplo n.º 3
0
        public void FindFirstSubrecords_Single()
        {
            var ret = PluginUtilityTranslation.FindFirstSubrecords(GetTypical(), GameConstants.Oblivion, SecondTypicalType);

            Assert.Single(ret);
            Assert.Equal(SecondTypicalLocation, ret[0]);
        }
Exemplo n.º 4
0
            public static void WriteCellsParallel(
                IListGroupGetter <ICellBlockGetter> group,
                MasterReferenceReader masters,
                int targetIndex,
                Stream[] streamDepositArray)
            {
                if (group.Records.Count == 0)
                {
                    return;
                }
                Stream[] streams    = new Stream[group.Records.Count + 1];
                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;
                    ListGroupBinaryWriteTranslation.WriteEmbedded <ICellBlockGetter>(group, stream);
                }
                streams[0] = groupByteStream;
                Parallel.ForEach(group.Records, (cellBlock, state, counter) =>
                {
                    WriteBlocksParallel(
                        cellBlock,
                        masters,
                        (int)counter + 1,
                        streams);
                });
                PluginUtilityTranslation.CompileSetGroupLength(streams, groupBytes);
                streamDepositArray[targetIndex] = new CompositeReadStream(streams, resetPositions: true);
            }
Exemplo n.º 5
0
        public static LensFlareBinaryOverlay LensFlareFactory(
            OverlayStream stream,
            BinaryOverlayFactoryPackage package,
            TypedParseParams?parseParams = null)
        {
            stream = PluginUtilityTranslation.DecompressStream(stream);
            var ret = new LensFlareBinaryOverlay(
                bytes: HeaderTranslation.ExtractRecordMemory(stream.RemainingMemory, package.MetaData.Constants),
                package: package);
            var finalPos = checked ((int)(stream.Position + stream.GetMajorRecord().TotalLength));
            int offset   = stream.Position + package.MetaData.Constants.MajorConstants.TypeAndLengthLength;

            ret._package.FormVersion = ret;
            stream.Position         += 0x10 + package.MetaData.Constants.MajorConstants.TypeAndLengthLength;
            ret.CustomFactoryEnd(
                stream: stream,
                finalPos: finalPos,
                offset: offset);
            ret.FillSubrecordTypes(
                majorReference: ret,
                stream: stream,
                finalPos: finalPos,
                offset: offset,
                parseParams: parseParams,
                fill: ret.FillRecordType);
            return(ret);
        }
Exemplo n.º 6
0
        public void FindFirstSubrecords_Typical()
        {
            var ret = PluginUtilityTranslation.FindFirstSubrecords(GetTypical(), GameConstants.Oblivion, SecondTypicalType, FirstTypicalType);

            Assert.Equal(2, ret.Length);
            Assert.Equal(SecondTypicalLocation, ret[0]);
            Assert.Equal(FirstTypicalLocation, ret[1]);
        }
Exemplo n.º 7
0
        public void FindFirstSubrecords_Empty()
        {
            var b   = new byte[0];
            var ret = PluginUtilityTranslation.FindFirstSubrecords(b, GameConstants.Oblivion, FirstTypicalType, SecondTypicalType);

            Assert.Equal(2, ret.Length);
            Assert.Null(ret[0]);
            Assert.Null(ret[1]);
        }
Exemplo n.º 8
0
 partial void FaceFxPhonemesRawParsingCustomParse(OverlayStream stream, int offset)
 {
     if (_faceFxPhonemesLoc == null)
     {
         _faceFxPhonemesLoc = (ushort)(stream.Position - offset);
     }
     PluginUtilityTranslation.SkipPastAll(stream, _package.MetaData.Constants, RecordTypes.PHTN);
     PluginUtilityTranslation.SkipPastAll(stream, _package.MetaData.Constants, RecordTypes.PHWT);
 }
Exemplo n.º 9
0
        public void EnumerateSubrecords_Typical()
        {
            var ret = PluginUtilityTranslation.EnumerateSubrecords(GetTypical(), GameConstants.Oblivion).ToArray();

            Assert.Equal(2, ret.Length);
            Assert.Equal(new RecordType("EDID"), ret[0].Key);
            Assert.Equal(FirstTypicalLocation, ret[0].Value);
            Assert.Equal(new RecordType("FNAM"), ret[1].Key);
            Assert.Equal(SecondTypicalLocation, ret[1].Value);
        }
Exemplo n.º 10
0
 public virtual void CopyInFromBinary(
     IMagicEffectSpawnHazardArchetypeInternal item,
     MutagenFrame frame,
     TypedParseParams?translationParams = null)
 {
     PluginUtilityTranslation.SubrecordParse(
         record: item,
         frame: frame,
         translationParams: translationParams,
         fillStructs: MagicEffectSpawnHazardArchetypeBinaryCreateTranslation.FillBinaryStructs);
 }
Exemplo n.º 11
0
 public virtual void CopyInFromBinary(
     IMagicEffectLightArchetypeInternal item,
     MutagenFrame frame,
     RecordTypeConverter?recordTypeConverter = null)
 {
     PluginUtilityTranslation.SubrecordParse(
         record: item,
         frame: frame,
         recordTypeConverter: recordTypeConverter,
         fillStructs: MagicEffectLightArchetypeBinaryCreateTranslation.FillBinaryStructs);
 }
Exemplo n.º 12
0
 public virtual void CopyInFromBinary(
     IRegionLand item,
     MutagenFrame frame,
     TypedParseParams?translationParams = null)
 {
     PluginUtilityTranslation.SubrecordParse(
         record: item,
         frame: frame,
         translationParams: translationParams,
         fillStructs: RegionLandBinaryCreateTranslation.FillBinaryStructs,
         fillTyped: RegionLandBinaryCreateTranslation.FillBinaryRecordTypes);
 }
Exemplo n.º 13
0
 public virtual void CopyInFromBinary(
     ILensFlareInternal item,
     MutagenFrame frame,
     TypedParseParams?translationParams = null)
 {
     PluginUtilityTranslation.MajorRecordParse <ILensFlareInternal>(
         record: item,
         frame: frame,
         translationParams: translationParams,
         fillStructs: LensFlareBinaryCreateTranslation.FillBinaryStructs,
         fillTyped: LensFlareBinaryCreateTranslation.FillBinaryRecordTypes);
 }
Exemplo n.º 14
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="pin">SubrecordPinFrame if found</param>
        /// <returns>True if matching subrecord is found</returns>
        public static bool TryLocateSubrecordPinFrame(this MajorRecordFrame majorFrame, RecordType type, int offset, out SubrecordPinFrame pin)
        {
            var find = PluginUtilityTranslation.FindFirstSubrecord(majorFrame.Content.Slice(offset - majorFrame.HeaderLength), majorFrame.Meta, type, navigateToContent: false);

            if (find == null)
            {
                pin = default;
                return(false);
            }
            pin = new SubrecordPinFrame(majorFrame.Meta, majorFrame.Content.Slice(find.Value + offset - majorFrame.HeaderLength), find.Value + offset);
            return(true);
        }
Exemplo n.º 15
0
 public virtual void CopyInFromBinary(
     IRegionLand item,
     MutagenFrame frame,
     RecordTypeConverter?recordTypeConverter = null)
 {
     PluginUtilityTranslation.SubrecordParse(
         record: item,
         frame: frame,
         recordTypeConverter: recordTypeConverter,
         fillStructs: RegionLandBinaryCreateTranslation.FillBinaryStructs,
         fillTyped: RegionLandBinaryCreateTranslation.FillBinaryRecordTypes);
 }
Exemplo n.º 16
0
 public virtual void CopyInFromBinary(
     IMaterialSwapInternal item,
     MutagenFrame frame,
     RecordTypeConverter?recordTypeConverter = null)
 {
     PluginUtilityTranslation.MajorRecordParse <IMaterialSwapInternal>(
         record: item,
         frame: frame,
         recordTypeConverter: recordTypeConverter,
         fillStructs: MaterialSwapBinaryCreateTranslation.FillBinaryStructs,
         fillTyped: MaterialSwapBinaryCreateTranslation.FillBinaryRecordTypes);
 }
Exemplo n.º 17
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="frame">SubrecordFrame if found</param>
        /// <returns>True if matching subrecord is found</returns>
        public static bool TryLocateSubrecordFrame(this MajorRecordFrame majorFrame, RecordType type, out SubrecordFrame frame)
        {
            var find = PluginUtilityTranslation.FindFirstSubrecord(majorFrame.Content, majorFrame.Meta, type, navigateToContent: false);

            if (find == null)
            {
                frame = default;
                return(false);
            }
            frame = new SubrecordFrame(majorFrame.Meta, majorFrame.Content.Slice(find.Value));
            return(true);
        }
Exemplo n.º 18
0
 public virtual void CopyInFromBinary(
     IVirtualMachineAdapter item,
     MutagenFrame frame,
     RecordTypeConverter?recordTypeConverter = null)
 {
     frame = frame.SpawnWithFinalPosition(HeaderTranslation.ParseSubrecord(
                                              frame.Reader,
                                              recordTypeConverter.ConvertToCustom(RecordTypes.VMAD)));
     PluginUtilityTranslation.SubrecordParse(
         record: item,
         frame: frame,
         recordTypeConverter: recordTypeConverter,
         fillStructs: VirtualMachineAdapterBinaryCreateTranslation.FillBinaryStructs);
 }
Exemplo n.º 19
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="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, int offset, out SubrecordHeader header, out int loc)
        {
            var find = PluginUtilityTranslation.FindFirstSubrecord(majorFrame.Content.Slice(offset - majorFrame.HeaderLength), majorFrame.Meta, type, navigateToContent: false);

            if (find == null)
            {
                header = default;
                loc    = default;
                return(false);
            }
            header = new SubrecordHeader(majorFrame.Meta, majorFrame.Content.Slice(find.Value + offset - majorFrame.HeaderLength));
            loc    = find.Value + offset;
            return(true);
        }
 public virtual void CopyInFromBinary(
     IVirtualMachineAdapter item,
     MutagenFrame frame,
     TypedParseParams?translationParams = null)
 {
     frame = frame.SpawnWithFinalPosition(HeaderTranslation.ParseSubrecord(
                                              frame.Reader,
                                              translationParams.ConvertToCustom(RecordTypes.VMAD),
                                              translationParams?.LengthOverride));
     PluginUtilityTranslation.SubrecordParse(
         record: item,
         frame: frame,
         translationParams: translationParams,
         fillStructs: VirtualMachineAdapterBinaryCreateTranslation.FillBinaryStructs);
 }
Exemplo n.º 21
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;
                });
                PluginUtilityTranslation.CompileSetGroupLength(subStreams, groupBytes);
                streamDepositArray[targetIndex] = new CompositeReadStream(subStreams, resetPositions: true);
            }
Exemplo n.º 22
0
        /// <summary>
        /// Takes a span aligned to a major record, and attempts to locate the game setting type.
        /// Will throw if the span is misaligned or doesn't start at a valid major record header.
        /// </summary>
        /// <param name="span">Data beginning at the start of a major record</param>
        /// <param name="meta">Game meta information to use in parsing</param>
        /// <returns>A response of the GameSettingType if found, or a reason if not.</returns>
        public static GetResponse <GameSettingType> GetGameSettingType(ReadOnlyMemorySlice <byte> span, GameConstants meta)
        {
            var majorMeta = meta.MajorRecordFrame(span);
            var edidLoc   = PluginUtilityTranslation.FindFirstSubrecord(majorMeta.Content, meta, Constants.EditorID);

            if (edidLoc == null)
            {
                return(GetResponse <GameSettingType> .Fail($"EDID was not located"));
            }
            var edidMeta = meta.SubrecordFrame(majorMeta.Content.Slice(edidLoc.Value));
            var edid     = BinaryStringUtility.ProcessWholeToZString(edidMeta.Content, MutagenEncodingProvider._1252);

            if (edid.Length == 0)
            {
                return(GetResponse <GameSettingType> .Fail("No EDID parsed."));
            }
            if (!TryGetGameSettingType(edid[0], out var settingType))
            {
                return(GetResponse <GameSettingType> .Fail($"Unknown game setting type: {edid[0]}"));
            }
            return(GetResponse <GameSettingType> .Succeed(settingType));
        }
Exemplo n.º 23
0
        public bool IsOfRecordType <T>(FormKey formKey)
            where T : IMajorRecordCommonGetter
        {
            if (formKey.IsNull)
            {
                return(false);
            }
            lock (_cachedLocs)
            {
                if (!_cachedLocs.TryGetValue(typeof(T), out var cache))
                {
                    using var stream = _streamCreator();
                    var locs = RecordLocator.GetFileLocations(
                        stream,
                        new RecordInterest(
                            interestingTypes: PluginUtilityTranslation.GetRecordType <T>()));
                    cache = locs.FormKeys.ToHashSet();

                    _cachedLocs.Add(typeof(T), cache);
                }
                return(cache.Contains(formKey));
            }
        }
Exemplo n.º 24
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(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);
                });
                PluginUtilityTranslation.CompileSetGroupLength(streams, groupBytes);
                streamDepositArray[targetIndex] = new CompositeReadStream(streams, resetPositions: true);
            }
Exemplo n.º 25
0
        public void FindFirstSubrecord_Empty()
        {
            var b = new byte[0];

            Assert.Null(PluginUtilityTranslation.FindFirstSubrecord(b, GameConstants.Oblivion, SecondTypicalType));
        }
Exemplo n.º 26
0
 public void FindFirstSubrecord_Duplicate()
 {
     Assert.Equal(FirstTypicalLocation, PluginUtilityTranslation.FindFirstSubrecord(GetTypical(), GameConstants.Oblivion, FirstTypicalType));
 }
Exemplo n.º 27
0
 public void EnumerateSubrecords_Empty()
 {
     byte[] b = new byte[0];
     Assert.Empty(PluginUtilityTranslation.EnumerateSubrecords(new ReadOnlyMemorySlice <byte>(b), GameConstants.Oblivion));
 }
Exemplo n.º 28
0
 void BipedObjectNamesCustomParse(OverlayStream stream, int finalPos, int offset)
 {
     _bipedObjectNamesLoc = (ushort)(stream.Position - offset);
     PluginUtilityTranslation.SkipPastAll(stream, _package.MetaData.Constants, RecordTypes.NAME);
 }