wabbajack/Wabbajack.Compression.BSA/TES3Archive/Builder.cs

78 lines
2.3 KiB
C#
Raw Permalink Normal View History

using System.IO;
using System.Text;
2021-09-27 12:42:46 +00:00
using System.Threading;
using System.Threading.Tasks;
2020-03-25 22:30:43 +00:00
using Wabbajack.Common;
2021-09-27 12:42:46 +00:00
using Wabbajack.Compression.BSA.Interfaces;
using Wabbajack.DTOs.BSA.ArchiveStates;
using Wabbajack.DTOs.BSA.FileStates;
2021-10-23 16:51:17 +00:00
namespace Wabbajack.Compression.BSA.TES3Archive;
public class Builder : IBuilder
{
2021-10-23 16:51:17 +00:00
private readonly (TES3File state, Stream data)[] _files;
private readonly TES3State _state;
2021-10-23 16:51:17 +00:00
public Builder(TES3State state)
{
_state = state;
_files = new (TES3File state, Stream data)[_state.FileCount];
}
2022-10-07 22:14:01 +00:00
public ValueTask AddFile(AFile state, Stream src, CancellationToken token)
2021-10-23 16:51:17 +00:00
{
var tesState = (TES3File) state;
_files[state.Index] = (tesState, src);
2022-10-07 22:14:01 +00:00
return ValueTask.CompletedTask;
2021-10-23 16:51:17 +00:00
}
2021-10-23 16:51:17 +00:00
public async ValueTask Build(Stream file, CancellationToken token)
{
await using var bw = new BinaryWriter(file, Encoding.Default, true);
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
bw.Write(_state.VersionNumber);
bw.Write(_state.HashOffset);
bw.Write(_state.FileCount);
2021-10-23 16:51:17 +00:00
foreach (var (state, _) in _files)
{
bw.Write(state.Size);
bw.Write(state.Offset);
}
2021-10-23 16:51:17 +00:00
foreach (var (state, _) in _files) bw.Write(state.NameOffset);
2021-10-23 16:51:17 +00:00
var orgPos = bw.BaseStream.Position;
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
foreach (var (state, _) in _files)
{
if (bw.BaseStream.Position != orgPos + state.NameOffset)
throw new BSAException("Offsets don't match when writing TES3 BSA");
bw.Write(Encoding.ASCII.GetBytes((string) state.Path));
bw.Write((byte) 0);
}
2021-10-23 16:51:17 +00:00
bw.BaseStream.Position = _state.HashOffset + 12;
foreach (var (state, _) in _files)
{
bw.Write(state.Hash1);
bw.Write(state.Hash2);
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
if (bw.BaseStream.Position != _state.DataOffset)
throw new InvalidDataException("Data offset doesn't match when writing TES3 BSA");
2021-10-23 16:51:17 +00:00
foreach (var (state, data) in _files)
{
bw.BaseStream.Position = _state.DataOffset + state.Offset;
await data.CopyToWithStatusAsync(data.Length, bw.BaseStream, token);
await data.DisposeAsync();
}
}
2022-10-07 22:57:12 +00:00
public ValueTask DisposeAsync()
{
2022-10-07 22:57:12 +00:00
return ValueTask.CompletedTask;
}
2021-09-27 12:42:46 +00:00
}