mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
issue-4 - Can index nested archives
This commit is contained in:
parent
e1d9cd335d
commit
4b036221b9
@ -251,7 +251,7 @@ namespace Compression.BSA
|
||||
private int _offset;
|
||||
private FolderRecord _folder;
|
||||
private string _name;
|
||||
private uint _originalSize;
|
||||
private uint? _originalSize;
|
||||
|
||||
public FileRecord(BSAReader bsa, FolderRecord folderRecord, BinaryReader src)
|
||||
{
|
||||
@ -296,11 +296,36 @@ namespace Compression.BSA
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Compressed) return (int)_originalSize;
|
||||
if (Compressed)
|
||||
{
|
||||
if (_originalSize == null)
|
||||
LoadOriginalSize();
|
||||
return (int)_originalSize;
|
||||
}
|
||||
return _size;
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadOriginalSize()
|
||||
{
|
||||
using (var in_file = File.OpenRead(_bsa._fileName))
|
||||
using (var rdr = new BinaryReader(in_file))
|
||||
{
|
||||
rdr.BaseStream.Position = _offset;
|
||||
string _name;
|
||||
int file_size = _size;
|
||||
if (_bsa.HasNameBlobs)
|
||||
{
|
||||
var name_size = rdr.ReadByte();
|
||||
file_size -= name_size + 1;
|
||||
rdr.BaseStream.Position = _offset + 1 + name_size;
|
||||
}
|
||||
|
||||
_originalSize = rdr.ReadUInt32();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public ulong Hash {
|
||||
get
|
||||
{
|
||||
|
@ -194,7 +194,11 @@ namespace Wabbajack.Common
|
||||
public class IndexedArchiveCache
|
||||
{
|
||||
public string Hash;
|
||||
public int Version;
|
||||
public List<IndexedEntry> Entries;
|
||||
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public Dictionary<string, IndexedArchiveCache> InnerArchives;
|
||||
}
|
||||
|
||||
public class IndexedArchive : IndexedArchiveCache
|
||||
|
@ -86,6 +86,10 @@
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Compression.BSA\Compression.BSA.csproj">
|
||||
<Project>{ff5d892f-8ff4-44fc-8f7f-cd58f307ad1b}</Project>
|
||||
<Name>Compression.BSA</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SevenZipExtractor\SevenZipExtractor.csproj">
|
||||
<Project>{8aa97f58-5044-4bba-b8d9-a74b6947a660}</Project>
|
||||
<Name>SevenZipExtractor</Name>
|
||||
|
@ -100,17 +100,27 @@ namespace Wabbajack
|
||||
.PMap(file => LoadArchive(file));
|
||||
}
|
||||
|
||||
|
||||
private const int ARCHIVE_CONTENTS_VERSION = 1;
|
||||
private IndexedArchive LoadArchive(string file)
|
||||
{
|
||||
TOP:
|
||||
string metaname = file + ".archive_contents";
|
||||
|
||||
if (metaname.FileExists() && new FileInfo(metaname).LastWriteTime >= new FileInfo(file).LastWriteTime)
|
||||
{
|
||||
Status("Loading Archive Index for {0}", Path.GetFileName(file));
|
||||
var info = metaname.FromJSON<IndexedArchive>();
|
||||
if (info.Version != ARCHIVE_CONTENTS_VERSION)
|
||||
{
|
||||
File.Delete(metaname);
|
||||
goto TOP;
|
||||
}
|
||||
|
||||
info.Name = Path.GetFileName(file);
|
||||
info.AbsolutePath = file;
|
||||
|
||||
|
||||
var ini_name = file + ".meta";
|
||||
if (ini_name.FileExists())
|
||||
{
|
||||
@ -121,16 +131,44 @@ namespace Wabbajack
|
||||
return info;
|
||||
}
|
||||
|
||||
IndexArchive(file).ToJSON(metaname);
|
||||
goto TOP;
|
||||
}
|
||||
|
||||
private bool IsArchiveFile(string name)
|
||||
{
|
||||
var ext = Path.GetExtension(name);
|
||||
if (ext == ".bsa" || Consts.SupportedArchives.Contains(ext))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private IndexedArchiveCache IndexArchive(string file)
|
||||
{
|
||||
Status("Indexing {0}", Path.GetFileName(file));
|
||||
var streams = new Dictionary<string, (SHA256Managed, long)>();
|
||||
FileExtractor.Extract(file, entry => {
|
||||
var inner_archives = new Dictionary<string, string>();
|
||||
FileExtractor.Extract(file, entry =>
|
||||
{
|
||||
Stream inner;
|
||||
if (IsArchiveFile(entry.Name))
|
||||
{
|
||||
var name = Path.GetTempFileName() + Path.GetExtension(entry.Name);
|
||||
inner_archives.Add(entry.Name, name);
|
||||
inner = File.OpenWrite(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
inner = Stream.Null;
|
||||
}
|
||||
var sha = new SHA256Managed();
|
||||
var os = new CryptoStream(Stream.Null, sha, CryptoStreamMode.Write);
|
||||
var os = new CryptoStream(inner, sha, CryptoStreamMode.Write);
|
||||
streams.Add(entry.Name, (sha, (long)entry.Size));
|
||||
return os;
|
||||
});
|
||||
|
||||
var indexed = new IndexedArchiveCache();
|
||||
indexed.Version = ARCHIVE_CONTENTS_VERSION;
|
||||
indexed.Hash = file.FileSHA256();
|
||||
indexed.Entries = streams.Select(entry =>
|
||||
{
|
||||
@ -144,8 +182,18 @@ namespace Wabbajack
|
||||
|
||||
streams.Do(e => e.Value.Item1.Dispose());
|
||||
|
||||
indexed.ToJSON(metaname);
|
||||
return LoadArchive(file);
|
||||
if (inner_archives.Count > 0)
|
||||
{
|
||||
var result = inner_archives.Select(archive =>
|
||||
{
|
||||
return (archive.Key, IndexArchive(archive.Value));
|
||||
}).ToDictionary(e => e.Key, e => e.Item2);
|
||||
indexed.InnerArchives = result;
|
||||
|
||||
inner_archives.Do(e => File.Delete(e.Value));
|
||||
}
|
||||
|
||||
return indexed;
|
||||
}
|
||||
|
||||
public void Compile()
|
||||
|
Loading…
Reference in New Issue
Block a user