public void ExportListFile() { WowRootHandler wowRoot = CASC.Root as WowRootHandler; using (StreamWriter sw = new StreamWriter("listfile_export.txt")) { foreach (var file in CASCFile.Files.OrderBy(f => f.Value.FullName, StringComparer.OrdinalIgnoreCase)) { if (CASC.FileExists(file.Key) && (wowRoot == null || !wowRoot.IsUnknownFile(file.Key))) { sw.WriteLine(file.Value.FullName); } } //var wr = CASC.Root as WowRootHandler; //SortedDictionary<int, string> fids = new SortedDictionary<int, string>(); //foreach (var file in CASCFile.FileNames) //{ // var id = wr.GetFileDataIdByName(file.Value); // if (id > 0) // { // fids[id] = file.Value; // } //} //foreach (var file in fids) //{ // sw.WriteLine("{0} {1}", file.Key, file.Value); //} } }
public void ExportFolders() { WowRootHandler wowRoot = CASC.Root as WowRootHandler; using (StreamWriter sw = new StreamWriter("dirs.txt")) { HashSet <string> dirData = new HashSet <string>(StringComparer.OrdinalIgnoreCase); foreach (var file in CASCFile.Files.OrderBy(f => f.Value.FullName, StringComparer.OrdinalIgnoreCase)) { if (CASC.FileExists(file.Key) && (wowRoot == null || !wowRoot.IsUnknownFile(file.Key))) { ulong fileHash = file.Key; int dirSepIndex = file.Value.FullName.LastIndexOf('\\'); if (dirSepIndex >= 0) { string dir = file.Value.FullName.Substring(0, dirSepIndex); dirData.Add(dir); } } } foreach (var dir in dirData) { sw.WriteLine(dir); } } }
private CASCHandlerLite(CASCConfig config, LocaleFlags locale, BackgroundWorkerEx worker) : base(config, worker) { if (config.GameType != CASCGameType.WoW) throw new Exception("Unsupported game " + config.BuildUID); Logger.WriteLine("CASCHandlerLite: loading encoding data..."); EncodingHandler EncodingHandler; using (var _ = new PerfCounter("new EncodingHandler()")) { using (var fs = OpenEncodingFile(this)) EncodingHandler = new EncodingHandler(fs, worker); } Logger.WriteLine("CASCHandlerLite: loaded {0} encoding data", EncodingHandler.Count); Logger.WriteLine("CASCHandlerLite: loading root data..."); RootHandlerBase RootHandler; using (var _ = new PerfCounter("new RootHandler()")) { using (var fs = OpenRootFile(EncodingHandler, this)) RootHandler = new WowRootHandler(fs, worker); } Logger.WriteLine("CASCHandlerLite: loaded {0} root data", RootHandler.Count); RootHandler.SetFlags(locale, ContentFlags.None, false); RootEntry rootEntry; foreach (var entry in RootHandler.GetAllEntries()) { rootEntry = entry.Value; if ((rootEntry.Block.LocaleFlags == locale || (rootEntry.Block.LocaleFlags & locale) != LocaleFlags.None) && (rootEntry.Block.ContentFlags & ContentFlags.LowViolence) == ContentFlags.None) { var enc = EncodingHandler.GetEntry(rootEntry.MD5); if (enc != null) { if (!HashToKey.ContainsKey(entry.Key)) { HashToKey.Add(entry.Key, enc.Key); FileDataIdToHash.Add(rootEntry.FileDataId, entry.Key); } } } } RootHandler.Clear(); EncodingHandler.Clear(); RootHandler = null; EncodingHandler = null; GC.Collect(); Logger.WriteLine("CASCHandlerLite: loaded {0} files", HashToKey.Count); }
public override bool FileExists(int fileDataId) { WowRootHandler rh = Root as WowRootHandler; if (rh == null) { return(false); } return(FileExists(rh.GetHashByFileDataId(fileDataId))); }
public bool FileExists(int fileDataId) { WowRootHandler rh = Root as WowRootHandler; if (rh != null) { var hash = rh.GetHashByFileDataId(fileDataId); return(FileExists(hash)); } return(false); }
public override Stream OpenFile(int fileDataId) { WowRootHandler rh = Root as WowRootHandler; if (rh != null) { return(OpenFile(rh.GetHashByFileDataId(fileDataId))); } if (CASCConfig.ThrowOnFileNotFound) { throw new FileNotFoundException("FileData: " + fileDataId.ToString()); } return(null); }
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(); }); }
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 <int, string> idToName = new Dictionary <int, 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++) { idToName[row.Value.GetField <int>(i)] = "unknown\\sound\\" + name + (many ? "_" + (i - 2).ToString("D2") : "") + (type == 28 ? ".mp3" : ".ogg"); } } } } if (_casc.FileExists("DBFilesClient\\SoundKit.db2") && _casc.FileExists("DBFilesClient\\SoundKitEntry.db2")) { using (Stream skStream = _casc.OpenFile("DBFilesClient\\SoundKit.db2")) using (Stream skeStream = _casc.OpenFile("DBFilesClient\\SoundKitEntry.db2")) { DB5Reader sk = new DB5Reader(skStream); DB5Reader ske = new DB5Reader(skeStream); Dictionary <int, List <int> > lookup = new Dictionary <int, List <int> >(); foreach (var row in ske) { int soundKitId = row.Value.GetField <int>(3); if (!lookup.ContainsKey(soundKitId)) { lookup[soundKitId] = new List <int>(); } lookup[soundKitId].Add(row.Value.GetField <int>(0)); } foreach (var row in sk) { string name = row.Value.GetField <string>(0).Replace(':', '_'); int type = row.Value.GetField <byte>(12); List <int> ske_entries; if (!lookup.TryGetValue(row.Key, out ske_entries)) { continue; } bool many = ske_entries.Count > 1; int i = 0; foreach (var fid in ske_entries) { idToName[fid] = "unknown\\sound\\" + name + (many ? "_" + (i + 1).ToString("D2") : "") + (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); int numTotal = files.Count(); int numDone = 0; WowRootHandler wowRoot = _casc.Root as WowRootHandler; foreach (var unknownEntry in files) { CASCFile unknownFile = unknownEntry as CASCFile; string name; if (idToName.TryGetValue(wowRoot.GetFileDataIdByHash(unknownFile.Hash), out name)) { unknownFile.FullName = name; } 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 = 0x138; string m2name = br.ReadCString(); unknownFile.FullName = "unknown\\" + m2name + ".m2"; } } } progress.Report((int)(++numDone / (float)numTotal * 100.0f)); } _casc.Root.Dump(); }); }
private CASCHandlerLite(CASCConfig config, LocaleFlags locale, BackgroundWorkerEx worker) : base(config, worker) { if (config.GameType != CASCGameType.WoW) { throw new Exception("Unsupported game " + config.BuildUID); } Logger.WriteLine("CASCHandlerLite: loading encoding data..."); EncodingHandler EncodingHandler; using (var _ = new PerfCounter("new EncodingHandler()")) { using (var fs = OpenEncodingFile(this)) EncodingHandler = new EncodingHandler(fs, worker); } Logger.WriteLine("CASCHandlerLite: loaded {0} encoding data", EncodingHandler.Count); Logger.WriteLine("CASCHandlerLite: loading root data..."); WowRootHandler RootHandler; using (var _ = new PerfCounter("new RootHandler()")) { using (var fs = OpenRootFile(EncodingHandler, this)) RootHandler = new WowRootHandler(fs, worker); } Logger.WriteLine("CASCHandlerLite: loaded {0} root data", RootHandler.Count); RootHandler.SetFlags(locale, ContentFlags.None, false); CDNIndexData = new Dictionary <MD5Hash, IndexEntry>(comparer); if (LocalIndex != null) { LocalIndexData = new Dictionary <MD5Hash, IndexEntry>(comparer); } RootEntry rootEntry; foreach (var entry in RootHandler.GetAllEntries()) { rootEntry = entry.Value; if ((rootEntry.LocaleFlags == locale || (rootEntry.LocaleFlags & locale) != LocaleFlags.None) && (rootEntry.ContentFlags & ContentFlags.LowViolence) == ContentFlags.None) { if (EncodingHandler.GetEntry(rootEntry.MD5, out EncodingEntry enc)) { if (!HashToKey.ContainsKey(entry.Key)) { HashToKey.Add(entry.Key, enc.Key); FileDataIdToHash.Add(RootHandler.GetFileDataIdByHash(entry.Key), entry.Key); if (LocalIndex != null) { IndexEntry iLocal = LocalIndex.GetIndexInfo(enc.Key); if (iLocal != null && !LocalIndexData.ContainsKey(enc.Key)) { LocalIndexData.Add(enc.Key, iLocal); } } IndexEntry iCDN = CDNIndex.GetIndexInfo(enc.Key); if (iCDN != null && !CDNIndexData.ContainsKey(enc.Key)) { CDNIndexData.Add(enc.Key, iCDN); } } } } } CDNIndex.Clear(); //CDNIndex = null; LocalIndex?.Clear(); LocalIndex = null; RootHandler.Clear(); RootHandler = null; EncodingHandler.Clear(); EncodingHandler = null; GC.Collect(); Logger.WriteLine("CASCHandlerLite: loaded {0} files", HashToKey.Count); }
private CASCHandlerLite(CASCConfig config, LocaleFlags locale, BackgroundWorkerEx worker) : base(config, worker) { if (config.GameType != CASCGameType.WoW) { throw new Exception("Unsupported game " + config.BuildUID); } Logger.WriteLine("CASCHandlerLite: loading encoding data..."); EncodingHandler EncodingHandler; using (var _ = new PerfCounter("new EncodingHandler()")) { using (var fs = OpenEncodingFile(this)) EncodingHandler = new EncodingHandler(fs, worker); } Logger.WriteLine("CASCHandlerLite: loaded {0} encoding data", EncodingHandler.Count); Logger.WriteLine("CASCHandlerLite: loading root data..."); RootHandlerBase RootHandler; using (var _ = new PerfCounter("new RootHandler()")) { using (var fs = OpenRootFile(EncodingHandler, this)) RootHandler = new WowRootHandler(fs, worker); } Logger.WriteLine("CASCHandlerLite: loaded {0} root data", RootHandler.Count); RootHandler.SetFlags(locale, ContentFlags.None, false); RootEntry rootEntry; foreach (var entry in RootHandler.GetAllEntries()) { rootEntry = entry.Value; if ((rootEntry.Block.LocaleFlags == locale || (rootEntry.Block.LocaleFlags & locale) != LocaleFlags.None) && (rootEntry.Block.ContentFlags & ContentFlags.LowViolence) == ContentFlags.None) { var enc = EncodingHandler.GetEntry(rootEntry.MD5); if (enc != null) { if (!HashToKey.ContainsKey(entry.Key)) { HashToKey.Add(entry.Key, enc.Key); FileDataIdToHash.Add(rootEntry.FileDataId, entry.Key); } } } } RootHandler.Clear(); EncodingHandler.Clear(); RootHandler = null; EncodingHandler = null; GC.Collect(); Logger.WriteLine("CASCHandlerLite: loaded {0} files", HashToKey.Count); }
private CASCHandlerLite(CASCConfig config, LocaleFlags locale, BackgroundWorkerEx worker) : base(config, worker) { if (config.GameType != CASCGameType.WoW) throw new Exception("Unsupported game " + config.BuildUID); Logger.WriteLine("CASCHandlerLite: loading encoding data..."); EncodingHandler EncodingHandler; using (var _ = new PerfCounter("new EncodingHandler()")) { using (var fs = OpenEncodingFile(this)) EncodingHandler = new EncodingHandler(fs, worker); } Logger.WriteLine("CASCHandlerLite: loaded {0} encoding data", EncodingHandler.Count); Logger.WriteLine("CASCHandlerLite: loading root data..."); WowRootHandler RootHandler; using (var _ = new PerfCounter("new RootHandler()")) { using (var fs = OpenRootFile(EncodingHandler, this)) RootHandler = new WowRootHandler(fs, worker); } Logger.WriteLine("CASCHandlerLite: loaded {0} root data", RootHandler.Count); RootHandler.SetFlags(locale, ContentFlags.None, false); CDNIndexData = new Dictionary<MD5Hash, IndexEntry>(comparer); if (LocalIndex != null) LocalIndexData = new Dictionary<MD5Hash, IndexEntry>(comparer); RootEntry rootEntry; foreach (var entry in RootHandler.GetAllEntries()) { rootEntry = entry.Value; if ((rootEntry.LocaleFlags == locale || (rootEntry.LocaleFlags & locale) != LocaleFlags.None) && (rootEntry.ContentFlags & ContentFlags.LowViolence) == ContentFlags.None) { EncodingEntry enc; if (EncodingHandler.GetEntry(rootEntry.MD5, out enc)) { if (!HashToKey.ContainsKey(entry.Key)) { HashToKey.Add(entry.Key, enc.Key); FileDataIdToHash.Add(RootHandler.GetFileDataIdByHash(entry.Key), entry.Key); if (LocalIndex != null) { IndexEntry iLocal = LocalIndex.GetIndexInfo(enc.Key); if (iLocal != null && !LocalIndexData.ContainsKey(enc.Key)) LocalIndexData.Add(enc.Key, iLocal); } IndexEntry iCDN = CDNIndex.GetIndexInfo(enc.Key); if (iCDN != null && !CDNIndexData.ContainsKey(enc.Key)) CDNIndexData.Add(enc.Key, iCDN); } } } } CDNIndex.Clear(); //CDNIndex = null; LocalIndex?.Clear(); LocalIndex = null; RootHandler.Clear(); RootHandler = null; EncodingHandler.Clear(); EncodingHandler = null; GC.Collect(); Logger.WriteLine("CASCHandlerLite: loaded {0} files", HashToKey.Count); }
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 <int, List <string> > idToName = new Dictionary <int, List <string> >(); if (_casc.Config.GameType == CASCGameType.WoW && AnalyzeSoundFiles) { if (_casc.FileExists("DBFilesClient\\SoundEntries.db2")) { using (Stream stream = _casc.OpenFile("DBFilesClient\\SoundEntries.db2")) { WDB2Reader se = new WDB2Reader(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++) { int id = row.Value.GetField <int>(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(1237434 /*"DBFilesClient\\SoundKit.db2"*/) && _casc.FileExists(1237435 /*"DBFilesClient\\SoundKitEntry.db2"*/) && _casc.FileExists(1665033 /*"DBFilesClient\\SoundKitName.db2"*/)) { using (Stream skStream = _casc.OpenFile(1237434)) using (Stream skeStream = _casc.OpenFile(1237435)) using (Stream sknStream = _casc.OpenFile(1665033)) { Func <ulong, bool> keyCheckFunc = x => KeyService.GetKey(x) != null; WDC3Reader sk = new WDC3Reader(skStream, keyCheckFunc); WDC3Reader ske = new WDC3Reader(skeStream, keyCheckFunc); WDC3Reader skn = new WDC3Reader(sknStream, keyCheckFunc); Dictionary <int, List <int> > lookup = new Dictionary <int, List <int> >(); foreach (var row in ske) { int soundKitId = row.Value.GetField <int>(0); if (!lookup.ContainsKey(soundKitId)) { lookup[soundKitId] = new List <int>(); } lookup[soundKitId].Add(row.Value.GetField <int>(1)); } foreach (var row in sk) { WDC3Row sknRow = skn.GetRow(row.Key); if (sknRow != null) { string name = sknRow.GetField <string>(0).Replace(':', '_').Replace("\"", ""); int type = row.Value.GetField <byte>(6); if (!lookup.TryGetValue(row.Key, out List <int> 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>(); } if (AddFileDataIdToSoundFiles) { idToName[fid].Add("unknown\\sound\\" + name + (many ? "_" + (i + 1).ToString("D2") : "") + "_" + fid + (type == 28 ? ".mp3" : ".ogg")); } else { idToName[fid].Add("unknown\\sound\\" + name + (many ? "_" + (i + 1).ToString("D2") : "") + (type == 28 ? ".mp3" : ".ogg")); } i++; } } } } } } CASCFolder unknownFolder = _root.GetEntry("unknown") as CASCFolder; if (unknownFolder == null) { return; } foreach (var kv in idToName) { foreach (var fn in kv.Value) { Logger.WriteLine($"{kv.Key};{fn}"); } } 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(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"; Logger.WriteLine($"{wowRoot.GetFileDataIdByHash(unknownFile.Hash)};{unknownFile.FullName}"); //m2file.Position = 0; //while (m2file.Position != m2file.Length) //{ // int chunkType = br.ReadInt32(); // int chunkSize = br.ReadInt32(); // if (chunkType == 0x44494641) // AFID // { // int count = chunkSize / 8; // for (int i = 0; i < count; i++) // { // ushort animId = br.ReadUInt16(); // ushort subAnimId = br.ReadUInt16(); // int FileDataId = br.ReadInt32(); // if (FileDataId != 0) // Logger.WriteLine($"{FileDataId};{wowRoot.GetFileDataIdByHash(unknownFile.Hash)}\\{name}\\{name}{animId:D4}-{subAnimId:D2}.anim"); // } // break; // } // else // { // m2file.Position += chunkSize; // } //} } } } progress.Report((int)(++numDone / (float)numTotal * 100)); } _casc.Root.Dump(); }); }