static void WADTest() { using (WADFile wad = new WADFile("Zed.wad.client")) { wad.RemoveEntry(wad.Entries[0]); wad.Write("Zed.wad.client"); } /*using (WADFile wad = new WADFile("Jinx.wad.client")) * { * Dictionary<ulong, byte[]> entries = new Dictionary<ulong, byte[]>(); * foreach(WADEntry entry in wad.Entries) * { * entries.Add(entry.XXHash, entry.GetContent(true)); * } * Parallel.ForEach(entries, (entry) => * { * File.WriteAllBytes("lol//" + entry.Key.ToString(), entry.Value); * }); * }*/ //string extractionFolder = "D:/Chewy/Desktop/WADTEST"; //Directory.CreateDirectory(extractionFolder); /*using (WADFile wad = new WADFile(@"C:\Riot Games\League of Legends\RADS\projects\league_client\managedfiles\0.0.0.93\Plugins\rcp-fe-viewport\assets.wad")) * { * wad.AddEntry(123456789, File.ReadAllBytes(@"C:\Riot Games\League of Legends\RADS\projects\league_client\managedfiles\0.0.0.93\Plugins\rcp-fe-viewport\description.json"), true); * wad.AddEntry(12345678, File.ReadAllBytes(@"C:\Riot Games\League of Legends\RADS\projects\league_client\managedfiles\0.0.0.93\Plugins\rcp-fe-viewport\description.json"), true); * wad.AddEntry(0, "wow"); * wad.Entries[0].FileRedirection = "It's like right now"; * wad.Write(@"C:\Riot Games\League of Legends\RADS\projects\league_client\managedfiles\0.0.0.93\Plugins\rcp-fe-viewport\assetsOHWOW.wad"); * }*/ }
private void PackWadFolders(string wadLocation) { //Loop through each WAD folder foreach (string wadFolder in Directory.EnumerateDirectories(wadLocation)) { char separator = Pathing.GetPathSeparator(wadFolder); string wadName = wadFolder.Split(separator).Last(); using (WADFile wad = new WADFile(3, 0)) { //Add each file to the WAD foreach (string wadFolderFile in Directory.EnumerateFiles(wadFolder, "*", SearchOption.AllDirectories)) { string path = wadFolderFile.Replace(wadFolder + separator, "").Replace('\\', '/'); ulong hash = XXHash.XXH64(Encoding.ASCII.GetBytes(path.ToLower())); string extension = Path.GetExtension(wadFolderFile); wad.AddEntry(hash, File.ReadAllBytes(wadFolderFile), extension != ".wpk" && extension != ".bnk" ? true : false); } //After WAD creation is finished we can write the WAD to the ZIP ZipArchiveEntry archiveEntry = this.Content.CreateEntry(string.Format(@"WAD\{0}", wadName)); wad.Write(archiveEntry.Open()); } } }
public static WADFile Merge(WADFile wadBase, WADFile wadMerge, out bool returnedMerge) { returnedMerge = false; //If the Modded WAD mods all entries of the original WAD then it will be returned to prevent memory halting and increase speed bool containsBaseEntries = true; foreach (WADEntry baseEntry in wadBase.Entries) { if (!wadMerge.Entries.Any(x => x.XXHash == baseEntry.XXHash)) { containsBaseEntries = false; break; } } if (containsBaseEntries) { returnedMerge = containsBaseEntries; return(wadMerge); } else { return(Merge(wadBase, wadMerge)); } }
public static WADFile Merge(WADFile wadBase, WADFile wadMerge) { //First add new files and then modify changed ones foreach (WADEntry entry in wadMerge.Entries) { WADEntry baseEntry = wadBase.Entries.FirstOrDefault(x => x.XXHash == entry.XXHash); if (baseEntry == null) { if (entry.Type == EntryType.Uncompressed) { wadBase.AddEntry(entry.XXHash, entry.GetContent(false), false); } else if (entry.Type == EntryType.ZStandardCompressed || entry.Type == EntryType.Compressed) { wadBase.AddEntryCompressed(entry.XXHash, entry.GetContent(false), entry.UncompressedSize, entry.Type); } } else if (!entry.SHA.SequenceEqual(baseEntry.SHA)) { if (entry.Type == EntryType.Uncompressed) { wadBase.Entries.Single(x => x.XXHash == entry.XXHash).EditData(entry.GetContent(false)); } else if (entry.Type == EntryType.ZStandardCompressed || entry.Type == EntryType.Compressed) { wadBase.Entries.Single(x => x.XXHash == entry.XXHash).EditData(entry.GetContent(false), entry.UncompressedSize); } } } return(wadBase); }
public LeagueFileIndex(string leagueFolder) { string wadRootPath = Path.Combine(leagueFolder, @"DATA\FINAL"); this.Version = new Version(FileVersionInfo.GetVersionInfo(Path.Combine(leagueFolder, "League of Legends.exe")).FileVersion); foreach (string wadFile in Directory.GetFiles(wadRootPath, "*", SearchOption.AllDirectories).Where(x => x.Contains(".wad"))) { using (WADFile wad = new WADFile(wadFile)) { List <ulong> fileHashes = new List <ulong>(); foreach (WADEntry entry in wad.Entries) { fileHashes.Add(entry.XXHash); string gameWadPath = wadFile.Replace(leagueFolder + Pathing.GetPathSeparator(leagueFolder), ""); if (this._gameIndex.ContainsKey(entry.XXHash)) { this._gameIndex[entry.XXHash].Add(gameWadPath); } else { this._gameIndex.Add(entry.XXHash, new List <string>() { gameWadPath }); } } } } Write(); }
public bool cleanUp() { this.activeWad?.Dispose(); StringDictionary = new Dictionary <ulong, string>(); mapEntries = new Dictionary <string, WADEntry>(); wadPath = ""; activeWad = new WADFile(); active = true; return(true); }
public static List <WadResult> GenerateWADStrings(WADFile wad, List <WadResult> wadResults) { List <string> strings = new List <string>(); foreach (WADEntry entry in wad.Entries.Where(x => x.Type != EntryType.FileRedirection)) { byte[] entryContent = entry.GetContent(true); LeagueFileType fileType = Utilities.GetLeagueFileExtensionType(entryContent); if (fileType == LeagueFileType.BIN) { BINFile bin = null; try { bin = new BINFile(new MemoryStream(entryContent)); strings.AddRange(ProcessBINLinkedFiles(bin.LinkedFiles)); strings.AddRange(ProcessBINFile(bin)); } catch (Exception excp) { throw new Exception(TAG + "解析wad文件失败,创建BIN文件失败...|" + excp.Message); } } } Dictionary <ulong, string> stringDictionary = new Dictionary <ulong, string>(); strings = strings.Distinct().ToList(); using (XXHash64 xxHash = XXHash64.Create()) { foreach (string fetchedString in strings) { if (!string.IsNullOrEmpty(fetchedString)) { // 计算路径的哈希值 byte[] b = Encoding.ASCII.GetBytes(fetchedString.ToLower()); byte[] hashVal = xxHash.ComputeHash(b); ulong hash = BitConverter.ToUInt64(hashVal, 0); string hex = BitConverter.ToString(hashVal, 0); if (!stringDictionary.ContainsKey(hash)) { stringDictionary.Add(hash, fetchedString); WadResult wadResult = new WadResult(); wadResult.hash = hash; wadResult.hex = hex; wadResult.name = fetchedString; //wadResult.type = Utilities.GetLeagueFileExtensionType(b); wadResults.Add(wadResult); } } } } GC.Collect(); return(wadResults); }
public static Dictionary <ulong, string> Generate(WADFile wad) { Dictionary <ulong, string> hashtable = new Dictionary <ulong, string>(); List <string> strings = new List <string>(); foreach (WADEntry entry in wad.Entries.Where(x => x.Type != EntryType.FileRedirection)) { byte[] entryContent = entry.GetContent(true); LeagueFileType fileType = LeagueUtilities.GetExtension(entryContent); if (fileType == LeagueFileType.BIN) { BINFile bin = null; try { bin = new BINFile(new MemoryStream(entryContent)); } catch (Exception) { } if (bin != null) { strings.AddRange(ProcessBINLinkedFiles(bin.LinkedFiles)); strings.AddRange(ProcessBINFile(bin)); } } else if (IsLegacyDirList(entry.XXHash)) { strings.AddRange(ProcessLegacyDirList(entry)); } } using (XXHash64 xxHash = XXHash64.Create()) { foreach (string fetchedString in strings.Distinct()) { if (!string.IsNullOrEmpty(fetchedString)) { ulong hash = BitConverter.ToUInt64(xxHash.ComputeHash(Encoding.ASCII.GetBytes(fetchedString.ToLower())), 0); if (!hashtable.ContainsKey(hash)) { hashtable.Add(hash, fetchedString); } } } } return(hashtable); }
public string convert(List <IFormFile> file) { if (null == file || file.Count != 1) { throw new ArgumentException("目前只支持解析单个wad文件"); } WADFile wad = new WADFile(file[0].OpenReadStream()); List <WadResult> wadResults = new List <WadResult>(); wadResults = WADHashGenerator.GenerateWADStrings(wad, wadResults); wad.Dispose(); GC.Collect(); return(ApiUtil.success(wadResults)); }
public static void GenerateWADStrings(WADFile wad, Dictionary <ulong, string> stringDictionary) { List <string> strings = new List <string>(); foreach (WADEntry entry in wad.Entries.Where(x => x.Type != EntryType.FileRedirection)) { byte[] entryContent = entry.GetContent(true); LeagueFileType fileType = Utilities.GetLeagueFileExtensionType(entryContent); if (fileType == LeagueFileType.BIN) { BINFile bin = null; try { bin = new BINFile(new MemoryStream(entryContent)); } catch (Exception excp) { Console.WriteLine(excp.Message); } if (bin != null) { strings.AddRange(ProcessBINLinkedFiles(bin.LinkedFiles)); strings = strings.Distinct().ToList(); strings.AddRange(ProcessBINFile(bin)); } } } using (XXHash64 xxHash = XXHash64.Create()) { for (int i = 0; i < strings.Count; i++) { string fetchedString = strings[i]; if (!string.IsNullOrEmpty(fetchedString)) { ulong hash = BitConverter.ToUInt64(xxHash.ComputeHash(Encoding.ASCII.GetBytes(fetchedString.ToLower())), 0); if (!stringDictionary.ContainsKey(hash)) { stringDictionary.Add(hash, fetchedString); } } } } }
private void ExtractFile(string path) { try { var info = new FileInfo(path); var Wad = new WADFile(path); var stringDictionary = new Dictionary <ulong, string>(); WADHashGenerator.GenerateWADStrings(Wad, stringDictionary); var worker = ExtractWADEntries(info.Directory.FullName + "/" + System.IO.Path.GetFileNameWithoutExtension(path), Wad.Entries, stringDictionary); worker.RunWorkerCompleted += Worker_RunWorkerCompleted; } catch (Exception excp) { return; } }
public LeagueFileIndex(string leagueFolder) { string wadRootPath = Path.Combine(leagueFolder, @"DATA\FINAL"); this.Version = new Version(FileVersionInfo.GetVersionInfo(Path.Combine(leagueFolder, "League of Legends.exe")).FileVersion); foreach (string wadFile in Directory.GetFiles(wadRootPath, "*.wad.client", SearchOption.AllDirectories)) { try { using (WADFile wad = new WADFile(wadFile)) { List <ulong> fileHashes = new List <ulong>(); foreach (WADEntry entry in wad.Entries) { fileHashes.Add(entry.XXHash); string gameWadPath = wadFile.Replace(leagueFolder + Pathing.GetPathSeparator(leagueFolder), ""); if (this._gameIndex.ContainsKey(entry.XXHash)) { this._gameIndex[entry.XXHash].Add(gameWadPath); } else { this._gameIndex.Add(entry.XXHash, new List <string>() { gameWadPath }); } } } } catch (InvalidFileSignatureException) { // Silent error, this can happen because the Riot patcher is broken Log.Error("Found a orrupted/invalid game WAD file: " + wadFile); } catch (Exception exception) { throw new Exception("Failed to index WAD file: " + wadFile, exception); } } Write(); }
public void UninstallMod(ModFile mod) { Log.Information("Uninstalling Mod: " + mod.GetID()); List <ulong> modFiles = new List <ulong>(this.Index.ModEntryMap[mod.GetID()]); Dictionary <string, WADFile> wadFiles = new Dictionary <string, WADFile>(); this.Index.StartEdit(); //In this loop we remove the installed WAD entries foreach (ulong modFile in modFiles) { List <string> modFileWadFiles = this.Index.Mod[modFile]; //Initialize WAD files for entry deletion foreach (string modFileWadFile in modFileWadFiles) { if (!wadFiles.ContainsKey(modFileWadFile)) { wadFiles.Add(modFileWadFile, new WADFile(string.Format(@"{0}\{1}", OVERLAY_FOLDER, modFileWadFile))); } WADFile wad = wadFiles[modFileWadFile]; wad.RemoveEntry(modFile); } this.Index.RemoveModFile(modFile, mod.GetID()); } //Now we need to either delete empty WAD files or fill the ones from which we removed the entries with original files //if the modified ones are the same as original then we need to delete those too foreach (KeyValuePair <string, WADFile> wadFile in wadFiles) { //If the WAD isn't being used by any other mod or is empty we can delete it if (!this.Index.WadModMap[wadFile.Key].Any(x => x != mod.GetID()) || wadFile.Value.Entries.Count == 0) { wadFile.Value.Dispose(); File.Delete(string.Format(@"{0}\{1}", OVERLAY_FOLDER, wadFile.Key)); } //If it's used by some other mods we need to merge it into the original WAD else { string gameWadPath = string.Format(@"{0}\{1}", this.LeagueFolder, wadFile.Key); string overlayWadPath = string.Format(@"{0}\{1}", OVERLAY_FOLDER, wadFile.Key); WADFile originalWad = new WADFile(gameWadPath); using (WADFile mergedWad = WADMerger.Merge(originalWad, wadFile.Value)) { mergedWad.Write(overlayWadPath + ".temp"); } wadFile.Value.Dispose(); File.Delete(overlayWadPath); File.Move(overlayWadPath + ".temp", overlayWadPath); } } this.Database.ChangeModState(mod.GetID(), false); this.Index.RemoveMod(mod.GetID()); this.Index.EndEdit(); }
private void WriteModWADFiles(ModFile mod) { Action <KeyValuePair <string, WADFile> > writeWadFileDelegate = new Action <KeyValuePair <string, WADFile> >(WriteWadFile); if (Config.Get <bool>("ParallelWadInstallation")) { ParallelOptions parallelOptions = new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }; Parallel.ForEach(mod.WadFiles, parallelOptions, (modWadFile) => { writeWadFileDelegate.Invoke(modWadFile); }); } else { foreach (KeyValuePair <string, WADFile> modWadFile in mod.WadFiles) { writeWadFileDelegate.Invoke(modWadFile); } } void WriteWadFile(KeyValuePair <string, WADFile> modWadFile) { string wadPath = this.Index.FindWADPath(modWadFile.Key); string overlayModWadPath = string.Format(@"{0}\{1}", OVERLAY_FOLDER, wadPath); string gameModWadPath = string.Format(@"{0}\{1}", this.LeagueFolder, wadPath); //Check if the WAD already exists, if it does, we need to merge the 2 WADs //if it doesnt, then we need to copy it from the game directory if (!File.Exists(overlayModWadPath)) { Directory.CreateDirectory(Path.GetDirectoryName(overlayModWadPath)); WADFile baseWad = new WADFile(gameModWadPath); bool returnedModdedWad = false; using (WADFile mergedWad = WADMerger.Merge(baseWad, modWadFile.Value, out returnedModdedWad)) { mergedWad.Write(overlayModWadPath); } if (returnedModdedWad) { baseWad.Dispose(); } else { modWadFile.Value.Dispose(); } } else { File.Move(overlayModWadPath, overlayModWadPath + ".temp"); using (WADFile mergedWad = WADMerger.Merge(new WADFile(overlayModWadPath + ".temp"), modWadFile.Value)) { mergedWad.Write(overlayModWadPath); } //Delete temp wad file File.Delete(overlayModWadPath + ".temp"); modWadFile.Value.Dispose(); } } }