public async Task AnalyzeUnknownFiles(Action <int> progressCallback)
{
if (_casc == null)
{
return;
}
IProgress <int> progress = new Progress <int>(progressCallback);
await Task.Run(() =>
{
FileScanner scanner = new FileScanner(_casc, _root);
Dictionary <uint, List <string> > idToName = new Dictionary <uint, List <string> >();
if (_casc.Config.GameType == CASCGameType.WoW)
{
if (_casc.FileExists("DBFilesClient\\SoundEntries.db2"))
{
using (Stream stream = _casc.OpenFile("DBFilesClient\\SoundEntries.db2"))
{
DB2Reader se = new DB2Reader(stream);
foreach (var row in se)
{
string name = row.Value.GetField <string>(2);
int type = row.Value.GetField <int>(1);
bool many = row.Value.GetField <int>(4) > 0;
for (int i = 3; i < 23; i++)
{
uint id = row.Value.GetField <uint>(i);
if (!idToName.ContainsKey(id))
{
idToName[id] = new List <string>();
}
idToName[id].Add("unknown\\sound\\" + name + (many ? "_" + (i - 2).ToString("D2") : "") + (type == 28 ? ".mp3" : ".ogg"));
}
}
}
}
if (_casc.FileExists("DBFilesClient\\SoundKit.db2") && _casc.FileExists("DBFilesClient\\SoundKitEntry.db2") && _casc.FileExists("DBFilesClient\\SoundKitName.db2"))
{
using (Stream skStream = _casc.OpenFile("DBFilesClient\\SoundKit.db2"))
using (Stream skeStream = _casc.OpenFile("DBFilesClient\\SoundKitEntry.db2"))
using (Stream sknStream = _casc.OpenFile("DBFilesClient\\SoundKitName.db2"))
{
WDC1Reader sk = new WDC1Reader(skStream);
WDC1Reader ske = new WDC1Reader(skeStream);
WDC1Reader skn = new WDC1Reader(sknStream);
Dictionary <uint, List <uint> > lookup = new Dictionary <uint, List <uint> >();
foreach (var row in ske)
{
uint soundKitId = row.Value.GetField <uint>(0);
if (!lookup.ContainsKey(soundKitId))
{
lookup[soundKitId] = new List <uint>();
}
lookup[soundKitId].Add(row.Value.GetField <uint>(1));
}
foreach (var row in sk)
{
string name = skn.GetRow(row.Key).GetField <string>(0).Replace(':', '_');
int type = row.Value.GetField <byte>(6);
if (!lookup.TryGetValue(row.Key, out List <uint> ske_entries))
{
continue;
}
bool many = ske_entries.Count > 1;
int i = 0;
foreach (var fid in ske_entries)
{
if (!idToName.ContainsKey(fid))
{
idToName[fid] = new List <string>();
}
idToName[fid].Add("unknown\\sound\\" + name + (many ? "_" + (i + 1).ToString("D2") : "") + "_" + fid + (type == 28 ? ".mp3" : ".ogg"));
i++;
}
}
}
}
}
CASCFolder unknownFolder = _root.GetEntry("unknown") as CASCFolder;
if (unknownFolder == null)
{
return;
}
IEnumerable <CASCFile> files = CASCFolder.GetFiles(unknownFolder.Entries.Select(kv => kv.Value), null, true).ToList();
int numTotal = files.Count();
int numDone = 0;
WowRootHandler wowRoot = _casc.Root as WowRootHandler;
Jenkins96 Hasher = new Jenkins96();
char[] PathDelimiters = new char[] { '/', '\\' };
foreach (var unknownEntry in files)
{
CASCFile unknownFile = unknownEntry as CASCFile;
if (idToName.TryGetValue((uint)wowRoot.GetFileDataIdByHash(unknownFile.Hash), out List <string> name))
{
if (name.Count == 1)
{
unknownFile.FullName = name[0];
}
else
{
unknownFolder.Entries.Remove(unknownFile.Name);
foreach (var file in name)
{
Logger.WriteLine(file);
string[] parts = file.Split(PathDelimiters);
string entryName = parts[parts.Length - 1];
ulong filehash = unknownFile.Hash;
CASCFile entry = new CASCFile(filehash, file);
CASCFile.Files[filehash] = entry;
unknownFolder.Entries[entryName] = entry;
}
}
}
else
{
string ext = scanner.GetFileExtension(unknownFile);
unknownFile.FullName += ext;
if (ext == ".m2")
{
using (var m2file = _casc.OpenFile(unknownFile.Hash))
using (var br = new BinaryReader(m2file))
{
m2file.Position = 0x14;
int nameOffs = br.ReadInt32();
m2file.Position = nameOffs + 8; // + sizeof(MD21)
string m2name = br.ReadCString();
unknownFile.FullName = "unknown\\" + m2name + ".m2";
}
}
}
progress.Report((int)(++numDone / (float)numTotal * 100));
}
_casc.Root.Dump();
});
}