Exemple #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);
            }
 public FormKey Parse(
     ReadOnlySpan<byte> span,
     MasterReferenceReader masterReferences)
 {
     var id = BinaryPrimitives.ReadUInt32LittleEndian(span);
     return FormKey.Factory(masterReferences, id);
 }
Exemple #3
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);
            }
Exemple #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);
            }
        public static MasterReferenceReader ConstructWriteMasters(IModGetter mod, BinaryWriteParameters param)
        {
            MasterReferenceReader ret     = new MasterReferenceReader(mod.ModKey);
            HashSet <ModKey>      modKeys = new HashSet <ModKey>();

            switch (param.MastersListSync)
            {
            case BinaryWriteParameters.MastersListSyncOption.NoCheck:
                modKeys.Add(mod.MasterReferences.Select(m => m.Master));
                break;

            case BinaryWriteParameters.MastersListSyncOption.Iterate:
                modKeys.Add(
                    // All FormKeys of links
                    mod.LinkFormKeys.Select(f => f.ModKey)
                    // All FormKeys of records themselves
                    .And(mod.EnumerateMajorRecords().Select(m => m.FormKey.ModKey)));
                break;

            default:
                throw new NotImplementedException();
            }
            modKeys.Remove(mod.ModKey);
            modKeys.Remove(ModKey.Null);
            ret.SetTo(modKeys.Select(m => new MasterReference()
            {
                Master = m
            }));
            return(ret);
        }
Exemple #6
0
 public static void WriteDialogTopicsParallel(
     IGroupGetter <IDialogTopicGetter> group,
     MasterReferenceReader masters,
     int targetIndex,
     Stream[] streamDepositArray)
 {
     WriteGroupParallel(group, masters, targetIndex, streamDepositArray);
 }
 public void Write <T>(
     MutagenWriter writer,
     IEDIDLink <T> item,
     MasterReferenceReader masterReferences)
     where T : class, IMajorRecordCommonGetter
 {
     this.Write(
         writer,
         item,
         masterReferences);
 }
Exemple #8
0
 public BinaryWriteParameters GetWriteParam(MasterReferenceReader masterRefs, StringsWriter stringsWriter)
 {
     return(new BinaryWriteParameters()
     {
         ModKey = BinaryWriteParameters.ModKeyOption.NoCheck,
         MastersListContent = BinaryWriteParameters.MastersListContentOption.NoCheck,
         RecordCount = BinaryWriteParameters.RecordCountOption.NoCheck,
         NextFormID = BinaryWriteParameters.NextFormIDOption.NoCheck,
         FormIDUniqueness = BinaryWriteParameters.FormIDUniquenessOption.NoCheck,
         MasterFlag = BinaryWriteParameters.MasterFlagOption.NoCheck,
         MastersListOrdering = masterRefs,
         StringsWriter = stringsWriter,
     });
 }
Exemple #9
0
 /// <summary>
 /// Constructor that opens a read stream to a path
 /// </summary>
 /// <param name="path">Path to read from</param>
 /// <param name="release">Game Release the stream is for</param>
 /// <param name="bufferSize">Size of internal buffer</param>
 /// <param name="offsetReference">Optional offset reference position to use</param>
 public MutagenBinaryReadStream(
     ModPath path,
     GameRelease release,
     int bufferSize       = 4096,
     long offsetReference = 0)
     : base(path, bufferSize)
 {
     this._path    = path;
     this.MetaData = new ParsingBundle(release, MasterReferenceReader.FromPath(path, release))
     {
         ModKey = path.ModKey
     };
     this.OffsetReference = offsetReference;
 }
Exemple #10
0
 /// <summary>
 /// Constructor that opens a read stream to a path
 /// </summary>
 /// <param name="path">Path to read from</param>
 /// <param name="release">Game Release the stream is for</param>
 /// <param name="bufferSize">Size of internal buffer</param>
 /// <param name="offsetReference">Optional offset reference position to use</param>
 /// <param name="fileSystem">FileSystem to read from</param>
 public MutagenBinaryReadStream(
     ModPath path,
     GameRelease release,
     int bufferSize         = 4096,
     long offsetReference   = 0,
     IFileSystem?fileSystem = null)
     : base(fileSystem.GetOrDefault().File.OpenRead(path), bufferSize)
 {
     this._path    = path;
     this.MetaData = new ParsingBundle(release, MasterReferenceReader.FromPath(path, release, fileSystem: fileSystem))
     {
         ModKey = path.ModKey
     };
     this.OffsetReference = offsetReference;
 }
        public FormKey Parse(
            ReadOnlySpan <byte> span,
            MasterReferenceReader masterReferences)
        {
            var id    = BinaryPrimitives.ReadUInt32LittleEndian(span);
            var modID = span[3];

            if (modID < masterReferences.Masters.Count)
            {
                return(new FormKey(
                           masterReferences.Masters[modID].Master,
                           id));
            }
            return(new FormKey(
                       masterReferences.CurrentMod,
                       id));
        }
Exemple #12
0
        /// <summary>
        /// Constructs a FormKey from a list of masters and the raw uint
        /// </summary>
        /// <param name="masterReferences">Master reference list to refer to</param>
        /// <param name="idWithModID">Mod index and Record ID to use</param>
        /// <returns>Converted FormID</returns>
        public static FormKey Factory(MasterReferenceReader masterReferences, uint idWithModID)
        {
            var modID = ModIndex.GetModIndexByteFromUInt(idWithModID);

            if (modID >= masterReferences.Masters.Count)
            {
                return(new FormKey(
                           masterReferences.CurrentMod,
                           idWithModID));
            }

            var master = masterReferences.Masters[modID];

            return(new FormKey(
                       master.Master,
                       idWithModID));
        }
Exemple #13
0
        public static void AddImplicitMasters(RunSynthesisMutagenPatcher settings, ExtendedList <LoadOrderListing> loadOrderListing)
        {
            HashSet <ModKey> referencedMasters = new HashSet <ModKey>();

            foreach (var item in loadOrderListing.OnlyEnabled())
            {
                MasterReferenceReader reader = MasterReferenceReader.FromPath(Path.Combine(settings.DataFolderPath, item.ModKey.FileName), settings.GameRelease);
                referencedMasters.Add(reader.Masters.Select(m => m.Master));
            }
            for (int i = 0; i < loadOrderListing.Count; i++)
            {
                var listing = loadOrderListing[i];
                if (!listing.Enabled && referencedMasters.Contains(listing.ModKey))
                {
                    loadOrderListing[i] = new LoadOrderListing(listing.ModKey, enabled: true);
                }
            }
        }
Exemple #14
0
        /// <summary>
        /// Constructor that wraps an existing stream
        /// </summary>
        /// <param name="stream">Stream to wrap and read from</param>
        /// <param name="modKey">ModKey</param>
        /// <param name="release">Game Release the stream is for</param>
        /// <param name="bufferSize">Size of internal buffer</param>
        /// <param name="dispose">Whether to dispose the source stream</param>
        /// <param name="offsetReference">Optional offset reference position to use</param>
        public MutagenBinaryReadStream(
            Stream stream,
            ModKey modKey,
            GameRelease release,
            int bufferSize       = 4096,
            bool dispose         = true,
            long offsetReference = 0)
            : base(stream, bufferSize, dispose)
        {
            var startPos = stream.Position;

            this.MetaData = new ParsingBundle(release, MasterReferenceReader.FromStream(stream, modKey, release))
            {
                ModKey = modKey
            };
            stream.Position      = startPos;
            this.OffsetReference = offsetReference;
        }
Exemple #15
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);
            }
Exemple #16
0
        public static void Align(
            ModPath inputPath,
            FilePath outputPath,
            GameRelease release,
            AlignmentRules alignmentRules,
            TempFolder?temp = null)
        {
            var interest = new RecordInterest(alignmentRules.Alignments.Keys)
            {
                EmptyMeansInterested = false
            };
            var parsingBundle = new ParsingBundle(GameConstants.Get(release), MasterReferenceReader.FromPath(inputPath, release));
            var fileLocs      = RecordLocator.GetFileLocations(inputPath.Path, release, interest);

            temp ??= new TempFolder();
            using (temp)
            {
                var alignedMajorRecordsFile = Path.Combine(temp.Dir.Path, "alignedRules");
                using (var inputStream = new MutagenBinaryReadStream(inputPath.Path, parsingBundle))
                {
                    using var writer = new MutagenWriter(new FileStream(alignedMajorRecordsFile, FileMode.Create), release);
                    AlignMajorRecordsByRules(inputStream, writer, alignmentRules, fileLocs);
                }

                var alignedGroupsFile = Path.Combine(temp.Dir.Path, "alignedGroups");
                using (var inputStream = new MutagenBinaryReadStream(alignedMajorRecordsFile, parsingBundle))
                {
                    using var writer = new MutagenWriter(new FileStream(alignedGroupsFile, FileMode.Create), release);
                    AlignGroupsByRules(inputStream, writer, alignmentRules, fileLocs);
                }

                fileLocs = RecordLocator.GetFileLocations(alignedGroupsFile, release, interest);
                var alignedCellsFile = Path.Combine(temp.Dir.Path, "alignedCells");
                using (var mutaReader = new BinaryReadStream(alignedGroupsFile))
                {
                    using var writer = new MutagenWriter(alignedCellsFile, release);
                    foreach (var grup in fileLocs.GrupLocations)
                    {
                        if (grup <= mutaReader.Position)
                        {
                            continue;
                        }
                        var noRecordLength = grup - mutaReader.Position;
                        mutaReader.WriteTo(writer.BaseStream, (int)noRecordLength);

                        // If complete overall, return
                        if (mutaReader.Complete)
                        {
                            break;
                        }

                        mutaReader.WriteTo(writer.BaseStream, 12);
                        var grupType = (GroupTypeEnum)mutaReader.ReadUInt32();
                        writer.Write((int)grupType);
                        switch (grupType)
                        {
                        case GroupTypeEnum.CellChildren:
                            AlignCellChildren(mutaReader, writer);
                            break;

                        default:
                            break;
                        }
                    }
                    mutaReader.WriteTo(writer.BaseStream, checked ((int)mutaReader.Remaining));
                }

                fileLocs = RecordLocator.GetFileLocations(alignedCellsFile, release, interest);
                using (var mutaReader = new MutagenBinaryReadStream(alignedCellsFile, parsingBundle))
                {
                    using var writer = new MutagenWriter(outputPath.Path, GameConstants.Get(release));
                    foreach (var grup in fileLocs.GrupLocations)
                    {
                        if (grup <= mutaReader.Position)
                        {
                            continue;
                        }
                        var noRecordLength = grup - mutaReader.Position;
                        mutaReader.WriteTo(writer.BaseStream, (int)noRecordLength);

                        // If complete overall, return
                        if (mutaReader.Complete)
                        {
                            break;
                        }

                        mutaReader.WriteTo(writer.BaseStream, 12);
                        var grupType = (GroupTypeEnum)mutaReader.ReadUInt32();
                        writer.Write((int)grupType);
                        switch (grupType)
                        {
                        case GroupTypeEnum.WorldChildren:
                            AlignWorldChildren(mutaReader, writer);
                            break;

                        default:
                            break;
                        }
                    }
                    mutaReader.WriteTo(writer.BaseStream, checked ((int)mutaReader.Remaining));
                }
            }
        }
Exemple #17
0
        public async Task Process(
            TempFolder tmpFolder,
            Subject <string> logging,
            ModPath sourcePath,
            string preprocessedPath,
            string outputPath)
        {
            this.Logging          = logging;
            this.TempFolder       = tmpFolder;
            this.SourcePath       = sourcePath;
            this.Masters          = MasterReferenceReader.FromPath(SourcePath, GameRelease);
            this.Bundle           = new ParsingBundle(GameRelease, Masters);
            this._NumMasters      = GetNumMasters();
            this._AlignedFileLocs = RecordLocator.GetFileLocations(new ModPath(ModKey, preprocessedPath), this.GameRelease);

            var preprocessedBytes = File.ReadAllBytes(preprocessedPath);

            IMutagenReadStream streamGetter() => new MutagenMemoryReadStream(preprocessedBytes, Bundle);

            using (var stream = streamGetter())
            {
                lock (_lengthTracker)
                {
                    foreach (var grup in this._AlignedFileLocs.GrupLocations.And(this._AlignedFileLocs.ListedRecords.Keys))
                    {
                        stream.Position           = grup + 4;
                        this._lengthTracker[grup] = stream.ReadUInt32();
                    }
                }

                await this.PreProcessorJobs(streamGetter);

                await Task.WhenAll(ExtraJobs(streamGetter));

                this.AddDynamicProcessorInstructions();
                Parallel.ForEach(this.DynamicProcessors.Keys
                                 .And(this.DynamicStreamProcessors.Keys)
                                 .And(RecordType.Null)
                                 .Distinct(),
                                 ParallelOptions,
                                 type => ProcessDynamicType(type, streamGetter));

                lock (_lengthTracker)
                {
                    foreach (var grup in this._lengthTracker)
                    {
                        stream.Position = grup.Key + 4;
                        if (grup.Value == stream.ReadUInt32())
                        {
                            continue;
                        }
                        this._Instructions.SetSubstitution(
                            loc: grup.Key + 4,
                            sub: BitConverter.GetBytes(grup.Value));
                    }
                }
            }

            var config = this._Instructions.GetConfig();

            using (var processor = new BinaryFileProcessor(
                       new FileStream(preprocessedPath, FileMode.Open, FileAccess.Read),
                       config))
            {
                try
                {
                    using var outStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write);
                    processor.CopyTo(outStream);
                }
                catch (Exception)
                {
                    if (File.Exists(outputPath))
                    {
                        File.Delete(outputPath);
                    }
                    throw;
                }
            }
        }
Exemple #18
0
 public IMasterReferenceReader FromPath(ModPath path)
 {
     return(MasterReferenceReader.FromPath(path, _gameReleaseContext.Release, fileSystem: _fileSystem));
 }
Exemple #19
0
        public Test BinaryPassthroughTest()
        {
            (TempFolder tmp, Test processedTest) = SetupProcessedFiles();

            var outputPath        = Path.Combine(tmp.Dir.Path, $"{this.Nickname}_NormalExport");
            var processedPath     = ProcessedPath(tmp);
            var orderedPath       = Path.Combine(tmp.Dir.Path, $"{this.Nickname}_Ordered");
            var binaryOverlayPath = Path.Combine(tmp.Dir.Path, $"{this.Nickname}_BinaryOverlay");
            var copyInPath        = Path.Combine(tmp.Dir.Path, $"{this.Nickname}_CopyIn");
            var strsProcessedPath = Path.Combine(tmp.Dir.Path, "Strings/Processed");

            var masterRefs = MasterReferenceReader.FromPath(new ModPath(ModKey, this.FilePath.Path), GameRelease);

            // Do normal
            if (Settings.TestNormal)
            {
                var  strsWriteDir = Path.Combine(tmp.Dir.Path, "Strings", $"{this.Nickname}_Normal");
                bool doStrings    = false;
                var  passthrough  = TestBattery.RunTest(
                    "Binary Normal Passthrough",
                    this.GameRelease,
                    this.Target,
                    parallel: Settings.Parallel,
                    toDo: async(o) =>
                {
                    o.OnNext(FilePath.ToString());
                    var mod   = await ImportBinary(this.FilePath.Path);
                    doStrings = mod.UsingLocalization;

                    foreach (var record in mod.EnumerateMajorRecords())
                    {
                        record.IsCompressed = false;
                    }

                    var writeParam = GetWriteParam(masterRefs, doStrings ? new StringsWriter(mod.ModKey, strsWriteDir) : null);
                    mod.WriteToBinary(outputPath, writeParam);
                    GC.Collect();

                    using var stream = new MutagenBinaryReadStream(processedPath, this.GameRelease);
                    writeParam.StringsWriter?.Dispose();

                    AssertFilesEqual(
                        stream,
                        outputPath,
                        amountToReport: 15);
                });
                processedTest.AddAsChild(passthrough);
                if (doStrings)
                {
                    foreach (var item in AssertStringsEqual(
                                 "Binary Normal",
                                 strsProcessedPath,
                                 strsWriteDir))
                    {
                        passthrough.AddAsChild(item);
                    }
                }
            }

            if (Settings.TestBinaryOverlay)
            {
                var  strsWriteDir = Path.Combine(tmp.Dir.Path, "Strings", $"{this.Nickname}_Overlay");
                bool doStrings    = false;
                var  passthrough  = TestBattery.RunTest(
                    "Binary Overlay Passthrough",
                    this.GameRelease,
                    this.Target,
                    parallel: Settings.Parallel,
                    toDo: async(o) =>
                {
                    o.OnNext(FilePath.ToString());
                    using (var wrapper = await ImportBinaryOverlay(this.FilePath.Path))
                    {
                        doStrings      = wrapper.UsingLocalization;
                        var writeParam = GetWriteParam(masterRefs, doStrings ? new StringsWriter(wrapper.ModKey, strsWriteDir) : null);
                        wrapper.WriteToBinary(binaryOverlayPath, writeParam);
                        writeParam.StringsWriter?.Dispose();
                    }

                    using var stream = new MutagenBinaryReadStream(processedPath, this.GameRelease);

                    PassthroughTest.AssertFilesEqual(
                        stream,
                        binaryOverlayPath,
                        amountToReport: 15);
                });
                processedTest.AddAsChild(passthrough);
                if (doStrings)
                {
                    foreach (var item in AssertStringsEqual(
                                 "Binary Overlay",
                                 strsProcessedPath,
                                 strsWriteDir))
                    {
                        passthrough.AddAsChild(item);
                    }
                }
            }

            if (Settings.TestCopyIn)
            {
                var  strsWriteDir = Path.Combine(tmp.Dir.Path, "Strings", $"{this.Nickname}_CopyIn");
                bool doStrings    = false;
                var  passthrough  = TestBattery.RunTest(
                    "Copy In Passthrough",
                    this.GameRelease,
                    this.Target,
                    parallel: Settings.Parallel,
                    toDo: async(o) =>
                {
                    o.OnNext(FilePath.ToString());
                    var copyIn     = await ImportCopyIn(this.FilePath.Path);
                    doStrings      = copyIn.UsingLocalization;
                    var writeParam = GetWriteParam(masterRefs, doStrings ? new StringsWriter(copyIn.ModKey, strsWriteDir) : null);
                    copyIn.WriteToBinary(copyInPath, writeParam);
                    writeParam.StringsWriter?.Dispose();

                    using var stream = new MutagenBinaryReadStream(processedPath, this.GameRelease);

                    PassthroughTest.AssertFilesEqual(
                        stream,
                        copyInPath,
                        amountToReport: 15);
                });
                processedTest.AddAsChild(passthrough);
                if (doStrings)
                {
                    foreach (var item in AssertStringsEqual(
                                 "Copy In",
                                 strsProcessedPath,
                                 strsWriteDir))
                    {
                        passthrough.AddAsChild(item);
                    }
                }
            }
            return(processedTest);
        }
Exemple #20
0
 public IMasterReferenceReader FromStream(Stream stream, ModKey modKey, bool disposeStream = true)
 {
     return(MasterReferenceReader.FromStream(stream, modKey, _gameReleaseContext.Release, disposeStream));
 }
Exemple #21
0
 public IMasterReferenceReader FromStream(IMutagenReadStream stream)
 {
     return(MasterReferenceReader.FromStream(stream));
 }
Exemple #22
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);
            }
Exemple #23
0
 public ParsingBundle(GameConstants constants, MasterReferenceReader masterReferences)
 {
     this.Constants        = constants;
     this.MasterReferences = masterReferences;
 }
Exemple #24
0
            public static OwnerTarget GetBinaryOwner(ReadOnlySpan <byte> span, RecordInfoCache cache, MasterReferenceReader masters)
            {
                FormID  form    = new FormID(BinaryPrimitives.ReadUInt32LittleEndian(span));
                FormKey formKey = FormKey.Factory(masters, form.Raw);

                if (cache.IsOfRecordType <Npc>(formKey))
                {
                    return(new NpcOwner()
                    {
                        Npc = new FormLink <INpcGetter>(FormKeyBinaryTranslation.Instance.Parse(span, masters)),
                        Global = new FormLink <IGlobalGetter>(FormKeyBinaryTranslation.Instance.Parse(span.Slice(4), masters))
                    });
                }
                else if (cache.IsOfRecordType <Faction>(formKey))
                {
                    return(new FactionOwner()
                    {
                        Faction = new FormLink <IFactionGetter>(FormKeyBinaryTranslation.Instance.Parse(span, masters)),
                        RequiredRank = BinaryPrimitives.ReadInt32LittleEndian(span.Slice(4))
                    });
                }
                else
                {
                    return(new NoOwner()
                    {
                        RawOwnerData = BinaryPrimitives.ReadUInt32LittleEndian(span),
                        RawVariableData = BinaryPrimitives.ReadUInt32LittleEndian(span.Slice(4))
                    });
                }
            }