Пример #1
0
        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();
        }
Пример #2
0
        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);
                }
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
        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();
        }
Пример #5
0
        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));
            }
        }
Пример #6
0
        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);
                            }
                        }
                    }
                }
            }
        }
Пример #7
0
        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);
            }
        }
Пример #8
0
        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);
                        }
                    }
                }
            }
        }