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 void AddFile(string path, string entryPath, WadEntry entry) { char pathSeparator = Pathing.GetPathSeparator(path); string[] folders = path.Split(pathSeparator); //If folders length is 1 then we can add the file to this directory //if not, then we pass it down the hierarchy if (folders.Length == 1) { this.Items.Add(new WadFileViewModel(this._wadViewModel, this, entryPath, folders[0], entry)); } else { //If the folder exists we pass the file to it //if it doesn't then we create it before passing the file if (this.Items.FirstOrDefault(x => x.Name == folders[0]) is WadFolderViewModel folder) { folder.AddFile(path.Substring(path.IndexOf(pathSeparator) + 1), entryPath, entry); } else { string newFolderPath = string.Format("{0}/{1}", this.Path, folders[0]); WadFolderViewModel newFolder = new WadFolderViewModel(this._wadViewModel, this, newFolderPath); newFolder.AddFile(path.Substring(path.IndexOf(pathSeparator) + 1), entryPath, entry); this.Items.Add(newFolder); } } }
public ZipArchiveEntry GetEntry(string path) { char separator = Pathing.GetPathSeparator(path); ZipArchiveEntry entry = this.Content.GetEntry(path); if (entry == null) { entry = this.Content.GetEntry(path.Replace(separator, Pathing.GetInvertedPathSeparator(separator))); } return(entry); }
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 async void AddFolder(string folderLocation) { try { foreach (string fileLocation in Directory.EnumerateFiles(folderLocation, "*", SearchOption.AllDirectories)) { char pathSeparator = Pathing.GetPathSeparator(fileLocation); string path = fileLocation.Replace(PathIO.GetDirectoryName(folderLocation) + pathSeparator, "").Replace(pathSeparator, '/'); string entryPath = string.Format("{0}/{1}", this.Path, path); ulong hash = XXHash.XXH64(Encoding.ASCII.GetBytes(entryPath.ToLower())); WADEntry entry = new WADEntry(this._wadViewModel.WAD, hash, File.ReadAllBytes(fileLocation), true, PathIO.GetExtension(fileLocation)); AddFile(path, entryPath, entry); } } catch (Exception exception) { await DialogHelper.ShowMessageDialog(string.Format("{0}\n{1}", Localization.Get("WadFolderAddFolderError"), exception)); } }
private Dictionary <string, WADFile> GetWadFiles() { Dictionary <string, WADFile> modWadFiles = new Dictionary <string, WADFile>(); //Collect WAD files in WAD folder CollectWADFiles(); //Pack WAD folders files into WAD files CollectWADFolders(); //Collect files from the RAW folder CollectRAWFiles(); return(modWadFiles); void CollectWADFiles() { foreach (ZipArchiveEntry zipEntry in GetEntries(@"WAD[\\/][\w.]+.wad.client(?![\\/])")) { char ps = Pathing.GetPathSeparator(zipEntry.FullName); string wadPath = this._modManager.Index.FindWADPath(zipEntry.FullName.Split(ps)[1]); zipEntry.ExtractToFile("wadtemp", true); modWadFiles.Add(wadPath, new WADFile(new MemoryStream(File.ReadAllBytes("wadtemp")))); File.Delete("wadtemp"); //We need to check each entry to see if they're shared across any other WAD files //if they are, we need to also modify those WADs foreach (WADEntry entry in modWadFiles[wadPath].Entries) { //Check if the entry is present in the game files or if it's new if (this._modManager.Index.Game.ContainsKey(entry.XXHash)) { foreach (string additionalWadPath in this._modManager.Index.Game[entry.XXHash].Where(x => x != wadPath)) { if (!modWadFiles.ContainsKey(additionalWadPath)) { modWadFiles.Add(additionalWadPath, new WADFile(3, 0)); } if (entry.Type == EntryType.Uncompressed) { modWadFiles[additionalWadPath].AddEntry(entry.XXHash, entry.GetContent(false), false); } else if (entry.Type == EntryType.Compressed || entry.Type == EntryType.ZStandardCompressed) { modWadFiles[additionalWadPath].AddEntryCompressed(entry.XXHash, entry.GetContent(false), entry.UncompressedSize, entry.Type); } } } } } } void CollectWADFolders() { List <string> wadPaths = new List <string>(); foreach (ZipArchiveEntry zipEntry in GetEntries(@"WAD[\\/][\w.]+.wad.client[\\/].*")) { char ps = Pathing.GetPathSeparator(zipEntry.FullName); string wadName = zipEntry.FullName.Split(ps)[1]; string wadPath = this._modManager.Index.FindWADPath(wadName); string path = zipEntry.FullName.Replace(string.Format("WAD{0}{1}{0}", ps, wadName), "").Replace('\\', '/'); ulong hash = XXHash.XXH64(Encoding.ASCII.GetBytes(path.ToLower())); if (!modWadFiles.ContainsKey(wadPath)) { modWadFiles.Add(wadPath, new WADFile(3, 0)); wadPaths.Add(wadPath); } using (MemoryStream memoryStream = new MemoryStream()) { zipEntry.Open().CopyTo(memoryStream); if (Path.GetExtension(path) == ".wpk") { modWadFiles[wadPath].AddEntry(hash, memoryStream.ToArray(), false); } else { modWadFiles[wadPath].AddEntry(hash, memoryStream.ToArray(), true); } } } //Shared Entry Check foreach (string wadPath in wadPaths) { foreach (WADEntry entry in modWadFiles[wadPath].Entries) { //Check if the entry is present in the game files or if it's new if (this._modManager.Index.Game.ContainsKey(entry.XXHash)) { foreach (string additionalWadPath in this._modManager.Index.Game[entry.XXHash].Where(x => x != wadPath)) { if (!modWadFiles.ContainsKey(additionalWadPath)) { modWadFiles.Add(additionalWadPath, new WADFile(3, 0)); } modWadFiles[additionalWadPath].AddEntryCompressed(entry.XXHash, entry.GetContent(false), entry.UncompressedSize, EntryType.ZStandardCompressed); } } } } } void CollectRAWFiles() { foreach (ZipArchiveEntry zipEntry in GetEntries(@"RAW[\\/].*")) { char ps = Pathing.GetPathSeparator(zipEntry.FullName); string path = zipEntry.FullName.Replace(@"RAW" + ps, "").Replace('\\', '/'); ulong hash = XXHash.XXH64(Encoding.ASCII.GetBytes(path.ToLower())); List <string> fileWadFiles = new List <string>(); //Check if file exists, if not, we discard it if (this._modManager.Index.Game.ContainsKey(hash)) { fileWadFiles = this._modManager.Index.Game[hash]; foreach (string wadFilePath in fileWadFiles) { if (!modWadFiles.ContainsKey(wadFilePath)) { modWadFiles.Add(wadFilePath, new WADFile(3, 0)); } using (MemoryStream memoryStream = new MemoryStream()) { zipEntry.Open().CopyTo(memoryStream); modWadFiles[wadFilePath].AddEntry(hash, memoryStream.ToArray(), true); } } } } } }
public string Validate(ModManager modManager) { string validationError = ""; //Check for RAW, WAD and META folders, and collect entries from RAW and WAD IEnumerable <ZipArchiveEntry> wadEntries = GetEntries(@"WAD[\\/].*"); IEnumerable <ZipArchiveEntry> rawEntries = GetEntries(@"RAW[\\/].*"); IEnumerable <ZipArchiveEntry> metaEntries = GetEntries(@"META[\\/].*"); validationError = ValidateBaseFolders(); if (!string.IsNullOrEmpty(validationError)) { return(validationError); } validationError = ValidateBaseFoldersContent(); if (!string.IsNullOrEmpty(validationError)) { return(validationError); } return(string.Empty); string ValidateBaseFolders() { if (wadEntries.Count() == 0 && rawEntries.Count() == 0) { return(string.Format("{0} does not contain neither a WAD folder nor a RAW folder", GetID())); } //Check if META folder exists if (metaEntries.Count() != 0) { //If it does then we check if it contains info.json if (!metaEntries.Any(x => x.Name == "info.json")) { return(string.Format("The META folder of {0} does not contain a META/info.json file", GetID())); } } else { return(string.Format("{0} does not contain a META folder", GetID())); } return(string.Empty); } string ValidateBaseFoldersContent() { bool isInvalid = false; //Get all files in the WAD folder validationError = string.Format("The WAD folder of {0} contains invalid entries:\n", GetID()); foreach (ZipArchiveEntry entry in wadEntries) { if (!entry.FullName.Contains(".wad.client")) { isInvalid = true; validationError += entry.FullName + '\n'; } else { //See if the WAD file exists in the game string wadName = entry.FullName.Split(Pathing.GetPathSeparator(entry.FullName))[1]; if (string.IsNullOrEmpty(modManager.Index.FindWADPath(wadName))) { isInvalid = true; validationError += entry.FullName + '\n'; } } } if (isInvalid) { return(validationError); } //Get all files in RAW folder and see if they contain a reference to WAD files validationError = string.Format("The RAW folder of {0} contains invalid entries:\n", GetID()); foreach (ZipArchiveEntry entry in rawEntries) { if (entry.FullName.Contains(".wad.client")) { isInvalid = true; validationError += entry.FullName + '\n'; } } if (isInvalid) { return(validationError); } return(string.Empty); } }
public Dictionary <string, WadBuilder> GetWadFiles(LeagueFileIndex index) { if (this._wadFiles != null) { return(this._wadFiles); } Dictionary <string, WadBuilder> modWadFiles = new (); //Collect WAD files in WAD folder CollectWADFiles(); //Pack WAD folders files into WAD files CollectWADFolders(); //Collect files from the RAW folder CollectRAWFiles(); this._wadFiles = modWadFiles; return(modWadFiles); void CollectWADFiles() { foreach (ZipArchiveEntry zipEntry in GetEntries(@"^WAD[\\/][\w.]+.wad.client$")) { char ps = Pathing.GetPathSeparator(zipEntry.FullName); string wadPath = index.FindWADPath(zipEntry.FullName.Split(ps)[1]); zipEntry.ExtractToFile("wadtemp", true); modWadFiles.Add(wadPath, new WadBuilder(Wad.Mount(new MemoryStream(File.ReadAllBytes("wadtemp")), false))); File.Delete("wadtemp"); //We need to check each entry to see if they're shared across any other WAD files //if they are, we need to also modify those WADs foreach (var entry in modWadFiles[wadPath].Entries) { //Check if the entry is present in the game files or if it's new if (index.Game.ContainsKey(entry.Key)) { foreach (string additionalWadPath in index.Game[entry.Key].Where(x => x != wadPath)) { if (!modWadFiles.ContainsKey(additionalWadPath)) { modWadFiles.Add(additionalWadPath, new WadBuilder()); } modWadFiles[additionalWadPath].WithEntry(entry.Value); } } } } } void CollectWADFolders() { List <string> wadPaths = new List <string>(); foreach (ZipArchiveEntry zipEntry in GetEntries(@"^WAD[\\/][\w.]+.wad.client[\\/].*")) { char ps = Pathing.GetPathSeparator(zipEntry.FullName); string wadName = zipEntry.FullName.Split(ps)[1]; string wadPath = index.FindWADPath(wadName); string path = zipEntry.FullName.Replace(string.Format("WAD{0}{1}{0}", ps, wadName), "").Replace('\\', '/'); ulong hash = XXHash.XXH64(Encoding.ASCII.GetBytes(path.ToLower())); if (!modWadFiles.ContainsKey(wadPath)) { modWadFiles.Add(wadPath, new WadBuilder()); wadPaths.Add(wadPath); } WadEntryBuilder entryBuilder = new(); entryBuilder .WithPathXXHash(hash) .WithGenericDataStream(path, zipEntry.Open()); modWadFiles[wadPath].WithEntry(entryBuilder); } //Shared Entry Check foreach (string wadPath in wadPaths) { foreach (var entry in modWadFiles[wadPath].Entries) { //Check if the entry is present in the game files or if it's new if (index.Game.ContainsKey(entry.Key)) { foreach (string additionalWadPath in index.Game[entry.Key].Where(x => x != wadPath)) { if (!modWadFiles.ContainsKey(additionalWadPath)) { modWadFiles.Add(additionalWadPath, new WadBuilder()); } WadEntryBuilder entryBuilder = new (); entryBuilder .WithPathXXHash(entry.Key) .WithZstdDataStream(entry.Value.DataStream, entry.Value.CompressedSize, entry.Value.UncompressedSize); modWadFiles[additionalWadPath].WithEntry(entryBuilder); } } } } } void CollectRAWFiles() { foreach (ZipArchiveEntry zipEntry in GetEntries(@"^RAW[\\/].*")) { char ps = Pathing.GetPathSeparator(zipEntry.FullName); string path = zipEntry.FullName.Replace(@"RAW" + ps, "").Replace('\\', '/'); ulong hash = XXHash.XXH64(Encoding.ASCII.GetBytes(path.ToLower())); //Check if file exists, if not, we discard it if (index.Game.ContainsKey(hash)) { List <string> fileWadFiles = index.Game[hash]; foreach (string wadFilePath in fileWadFiles) { if (!modWadFiles.ContainsKey(wadFilePath)) { modWadFiles.Add(wadFilePath, new WadBuilder()); } WadEntryBuilder entryBuilder = new(); entryBuilder .WithPathXXHash(hash) .WithGenericDataStream(path, zipEntry.Open()); modWadFiles[wadFilePath].WithEntry(entryBuilder); } } } } }