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); }
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); }