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 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); }
public void FindFirstSubrecords_Single() { var ret = PluginUtilityTranslation.FindFirstSubrecords(GetTypical(), GameConstants.Oblivion, SecondTypicalType); Assert.Single(ret); Assert.Equal(SecondTypicalLocation, ret[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 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); }
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]); }
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]); }
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); }
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); }
public virtual void CopyInFromBinary( IMagicEffectSpawnHazardArchetypeInternal item, MutagenFrame frame, TypedParseParams?translationParams = null) { PluginUtilityTranslation.SubrecordParse( record: item, frame: frame, translationParams: translationParams, fillStructs: MagicEffectSpawnHazardArchetypeBinaryCreateTranslation.FillBinaryStructs); }
public virtual void CopyInFromBinary( IMagicEffectLightArchetypeInternal item, MutagenFrame frame, RecordTypeConverter?recordTypeConverter = null) { PluginUtilityTranslation.SubrecordParse( record: item, frame: frame, recordTypeConverter: recordTypeConverter, fillStructs: MagicEffectLightArchetypeBinaryCreateTranslation.FillBinaryStructs); }
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); }
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); }
/// <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); }
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); }
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); }
/// <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); }
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); }
/// <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); }
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); }
/// <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)); }
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)); } }
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); }
public void FindFirstSubrecord_Empty() { var b = new byte[0]; Assert.Null(PluginUtilityTranslation.FindFirstSubrecord(b, GameConstants.Oblivion, SecondTypicalType)); }
public void FindFirstSubrecord_Duplicate() { Assert.Equal(FirstTypicalLocation, PluginUtilityTranslation.FindFirstSubrecord(GetTypical(), GameConstants.Oblivion, FirstTypicalType)); }
public void EnumerateSubrecords_Empty() { byte[] b = new byte[0]; Assert.Empty(PluginUtilityTranslation.EnumerateSubrecords(new ReadOnlyMemorySlice <byte>(b), GameConstants.Oblivion)); }
void BipedObjectNamesCustomParse(OverlayStream stream, int finalPos, int offset) { _bipedObjectNamesLoc = (ushort)(stream.Position - offset); PluginUtilityTranslation.SkipPastAll(stream, _package.MetaData.Constants, RecordTypes.NAME); }