public override async Task <bool> CheckForUpdates() { if (ClientProfile == null) { return(false); } if (ServerProfile == null) { return(false); } // Should never hit, earlier logic shouldn't even call the function if (!ServerProfile.IsOfficial) { return(false); } if (ClientProfile.Localization != ClientLocalization.Japan && ClientProfile.Localization != ClientLocalization.JapanHangame) { return(false); } PatcherContext.SetPatcherState(true); PatcherContext.UpdateMainProgress("Checking for updates...", "", 0, true, true); _officialPatchInfo = OfficialPatchInfo.Parse(MabiVersion.Versions .Find(version => version.Name == ClientProfile.Localization).PatchUrl); if (int.TryParse(_officialPatchInfo["main_version"], out var versionConverted)) { _remoteVersion = versionConverted; } if (_currentVersion == _remoteVersion) { PatcherContext.SetPatcherState(false); PatcherContext.UpdateMainProgress("", "", 0, false, false); return(false); } try { await Task.Run(() => _patchSequence = FindPatchSequence()); } catch (PatchSequenceNotFoundException ex) { Log.Exception(ex); PatcherContext.SetPatcherState(false); PatcherContext.UpdateMainProgress("", "", 0, false, false); return(false); } PatcherContext.SetPatcherState(false); PatcherContext.UpdateMainProgress("", "", 0, false, false); return(true); }
private async Task <List <FileDownloadInfo> > GetFileDownloadInfo() { double entries = ((ICollection)PatchData.files).Count; PatcherContext.UpdateMainProgress(Properties.Resources.ParsingManifest, $"0/{entries}", 0, false, true); var fileDownloadInfos = new List <FileDownloadInfo>(); await Task.Delay(1); int entry = 0; // Decode filepaths into new collection foreach (var file in PatchData["files"]) { entry++; PatcherContext.UpdateMainProgress(Properties.Resources.ParsingManifest, $"{entry}/{entries}", entry / entries * 100, false, true); var isDirectory = false; var filename = file.Name; var decodedFilename = DecodeFilename(filename); // Nexon does not intend for this file to be downloaded or this may be some other specification if (file.Value["objects"].Count == 0) { Log.Info(Properties.Resources.FileWithNoObjectsIgnored, decodedFilename); continue; } if (file.Value["objects"][0] == "__DIR__") { isDirectory = true; } var fileDownloadInfo = new FileDownloadInfo(decodedFilename, file.Value["fsize"].Value, isDirectory ? FileInfoType.Directory : FileInfoType.File); fileDownloadInfo.SetModifiedTimeDateTime(file.Value["mtime"].Value); if (isDirectory) { continue; } for (var i = 0; i < file.Value["objects"].Count; i++) { var filePartInfo = new FilePartInfo(file.Value["objects"][i].Value, decodedFilename, file.Value["objects_fsize"][i].Value, i); fileDownloadInfo.FileParts.Add(filePartInfo); } fileDownloadInfos.Add(fileDownloadInfo); } return(fileDownloadInfos); }
public override async Task <bool> RepairInstall() { var shouldUpdate = await CheckForUpdatesInternal(-1, true); if (shouldUpdate) { return(await ApplyUpdates()); } PatcherContext.SetPatcherState(false); PatcherContext.UpdateMainProgress("", "", 0, false, false); return(true); }
public void Finish() { double count = _downloadWrappers.Count; int completed = 0; _patcherContext.UpdateMainProgress(Properties.Resources.FinalizingFiles, $"{completed}/{count}", 0, false, true); var actions = _downloadWrappers.Values.Select(downloadWrapper => (Action)(() => { downloadWrapper.Finish(); Interlocked.Increment(ref completed); _patcherContext.UpdateMainProgress(Properties.Resources.FinalizingFiles, $"{completed}/{count}", completed / count * 100, false, true); })) .ToList(); _downloadWrappers.Clear(); Parallel.Invoke(new ParallelOptions { MaxDegreeOfParallelism = 10 }, actions.ToArray()); }
public override async Task <bool> CheckForUpdates() { if (ValidateAction(true)) { return(false); } PatcherContext.UpdateMainProgress(Properties.Resources.Initialize, "", 0, true, true); var completed = "true"; PatcherContext.SetPatcherState(true); PatcherContext.UpdateMainProgress(Properties.Resources.CheckingForUpdates, "", 0, true, true); if (!NexonApi.Instance.IsAccessTokenValid(ClientProfile.Guid)) { completed = ""; PatcherContext.RequestUserLogin(() => completed = "true", () => completed = "false"); } while (completed == "") { await Task.Delay(100); } if (completed == "false") { PatcherContext.SetPatcherState(false); PatcherContext.UpdateMainProgress("", "", 0, false, false); return(false); } var result = await CheckForUpdatesInternal(ReadVersion()); PatcherContext.SetPatcherState(false); PatcherContext.UpdateMainProgress("", "", 0, false, false); return(result); }
private async Task GetManifestJson(int version) { if (version == -1) { PatcherContext.UpdateMainProgress(Properties.Resources.GettingLatestVersion, "", 0, true, true); _version = version = await NexonApi.Instance.GetLatestVersion(); } PatcherContext.UpdateMainProgress(Properties.Resources.DownloadingManifest, "", 0, true, true); // Get Manifest String var manifestHashString = await NexonApi.Instance.GetManifestHashString(); // Download Manifest var buffer = DownloadManifestBuffer(manifestHashString); PatcherContext.UpdateMainProgress(Properties.Resources.DecompressingManifest, "", 0, true, true); // Decompress Manifest and Convert to Object var manifestContent = ZlibStream.UncompressString(buffer); var data = JsonConvert.DeserializeObject <dynamic>(manifestContent); PatchData = data; }
public override async Task <bool> ApplyUpdates() { if (ValidateAction()) { return(false); } PatcherContext.SetPatcherState(true); PatcherContext.ShowSession(); PatcherContext.UpdateMainProgress(Properties.Resources.ApplyingUpdates, "", 0, true, true); var patchDownloader = new PatchDownloader(Patches, ClientProfile, PatcherContext); bool result = false; try { await Task.Run(() => patchDownloader.Prepare()); result = await Task.Run(() => patchDownloader.Patch()); await Task.Run(() => patchDownloader.Cleanup()); } catch (Exception ex) { Log.Exception(ex, "Failed to patch!"); } finally { PatcherContext.UpdateMainProgress(result ? Properties.Resources.PatchComplete : Properties.Resources.PatchFailed); PatcherContext.SetPatcherState(false); PatcherContext.HideSession(); } return(result); }
private void GetPatchList(bool overrideSettings = false) { double entries = FileDownloadInfos.Count; PatcherContext.UpdateMainProgress(Properties.Resources.CheckingFiles, $"0/{entries}", 0, false, true); var entry = 0; foreach (var fileDownloadInfo in FileDownloadInfos) { entry++; PatcherContext.UpdateMainProgress(Properties.Resources.CheckingFiles, $"{entry}/{entries}", entry / entries * 100, false, true); var filePath = fileDownloadInfo.FileName; if (!overrideSettings) { if (filePath.StartsWith("package\\") && PatchSettingsManager.Instance.PatcherSettings.IgnorePackageFolder && !GetIsNewPackFile(filePath)) { continue; } } if (PatchIgnore.IgnoredFiles.Contains(filePath)) { Log.Info($"File: '{filePath}' in ignore list, file will not be patched!"); continue; } if (fileDownloadInfo.FileInfoType == FileInfoType.Directory) { if (Directory.Exists(fileDownloadInfo.FileName)) { continue; } Patches.Add(new Patch(fileDownloadInfo, PatchReason.DoesNotExist)); continue; } var modified = false; var fileExists = true; var actualModified = new DateTime(); var correctSize = true; long length = 0; if (File.Exists(filePath)) { length = new FileInfo(filePath).Length; actualModified = File.GetLastWriteTime(filePath); if (actualModified != fileDownloadInfo.LastModifiedDateTime) { modified = true; } else if (length != fileDownloadInfo.FileSize) { correctSize = false; } } else { fileExists = false; } if (!correctSize) { var patch = new Patch(fileDownloadInfo, PatchReason.SizeNotMatch); Patches.Add(patch); Log.Info(Properties.Resources.PatchRequiredForSize, filePath, patch.PatchReason.LocalizedPatchReason(), fileDownloadInfo.FileSize, length); continue; } if (!fileExists) { var patch = new Patch(fileDownloadInfo, PatchReason.DoesNotExist); Patches.Add(patch); Log.Info(Properties.Resources.PatchRequiredFor, filePath, patch.PatchReason.LocalizedPatchReason()); continue; } if (!modified) { continue; } if (actualModified > fileDownloadInfo.LastModifiedDateTime) { var patch = new Patch(fileDownloadInfo, PatchReason.Modified); Patches.Add(patch); Log.Info(Properties.Resources.PatchRequiredFor, filePath, patch.PatchReason.LocalizedPatchReason()); } else { var patch = new Patch(fileDownloadInfo); Patches.Add(patch); Log.Info(Properties.Resources.PatchRequiredFor, filePath, patch.PatchReason.LocalizedPatchReason()); } } }
public List <PatchFileInfo> Verify() { Log.Info(Properties.Resources.BeginningFileVerification); _patcherContext.UpdateMainProgress(Properties.Resources.BeginningFileVerification, isIndeterminate: true, isProgressbarVisible: true); var list = new List <PatchFileInfo>(); using (var md5 = MD5.Create()) { foreach (var patchFileInfo in PatchInfo.Files) { try { // TODO: Global Cancellation token CancellationToken.None.ThrowIfCancellationRequested(); } catch { break; } _patcherContext.UpdateMainProgress(string.Format(Properties.Resources.VerifyingFileName, patchFileInfo.Filename), isIndeterminate: true, isProgressbarVisible: true); try { using (var fileStream = new FileStream(Path.Combine(PatchInfo.PatchName, patchFileInfo.Filename), FileMode.Open)) { var actualHash = BitConverter.ToString(md5.ComputeHash(fileStream)).Replace("-", "") .ToLower(); if (actualHash != patchFileInfo.Md5Hash) { Log.Info(Properties.Resources.VerifyFailedMD5Hash, patchFileInfo.Filename, patchFileInfo.Md5Hash, actualHash); list.Add(patchFileInfo); } } } catch (Exception ex) { Log.Info(Properties.Resources.VerifyFailedException, patchFileInfo.Filename, ex.Message); list.Add(patchFileInfo); } } } Log.Info(Properties.Resources.FileVerificationComplete); _patcherContext.UpdateMainProgress(Properties.Resources.FileVerificationComplete); return(list); }
private PatchSequence FindPatchSequence(int currentVersion = -1, int remoteVersion = -1) { if (currentVersion == -1) { currentVersion = _currentVersion; } if (remoteVersion == -1) { remoteVersion = _remoteVersion; } Log.Info("Attempting to find sequence from {0} to {1}", currentVersion, remoteVersion); var patchInfos = new List <PatchInfo>(); var format = "Attempting to patch from {0} to {1}. Currently checking {2}."; try { using (var webClient = new WebClient()) { if (currentVersion == 0) { PatcherContext.UpdateMainProgress(string.Format(format, 0, remoteVersion, remoteVersion), "", 0, true, true); var patchInfo = GetPatchInfo(webClient, remoteVersion, $"{remoteVersion}_full.txt"); if (patchInfo == null) { throw new PatchSequenceNotFoundException(currentVersion, remoteVersion); } patchInfos.Add(patchInfo); } else { var fromNumber = currentVersion; var toNumber = remoteVersion; while (fromNumber != toNumber) { PatcherContext.UpdateMainProgress(string.Format(format, currentVersion, remoteVersion, fromNumber), "", (fromNumber - (double)currentVersion / (remoteVersion - currentVersion)), true, true); var patchInfo = GetPatchInfo(webClient, remoteVersion, $"{fromNumber}_to_{toNumber}.txt"); if (patchInfo != null) { patchInfos.Add(patchInfo); fromNumber = toNumber; toNumber += 5; } else if (--toNumber == fromNumber) { return(FindPatchSequence(0, remoteVersion)); } } } } } finally { PatcherContext.UpdateMainProgress(); } return(new PatchSequence(patchInfos)); }