public async Task <bool> TryToPack(AcCommonObjectPackerParams packerParams) { try { using (var waiting = packerParams.Progress == null ? WaitingDialog.Create("Packing…") : null) { var progress = waiting ?? packerParams.Progress; var cancellation = waiting?.CancellationToken ?? packerParams.Cancellation; await Task.Run(() => { var destination = packerParams.Destination ?? Path.Combine(Location, $"{Id}-{(this as IAcObjectVersionInformation)?.Version ?? "0"}-{DateTime.Now.ToUnixTimestamp()}.zip"); using (var output = File.Create(destination)) { Pack(output, packerParams, new Progress <string>(x => progress?.Report(AsyncProgressEntry.FromStringIndetermitate($"Packing: {x}…"))), cancellation); } if (cancellation.IsCancellationRequested) { return; } if (packerParams.ShowInExplorer) { WindowsHelper.ViewFile(destination); } }); } return(true); } catch (Exception e) { NonfatalError.Notify("Can’t pack", e); return(false); } }
public Task EnableMod(GenericMod mod) { return(_busy.Task(async() => { if (_enabler == null || mod.IsEnabled) { return; } var conflicts = await _enabler.CheckConflictsAsync(mod); if (conflicts.Length > 0 && ModernDialog.ShowMessage( conflicts.Select(x => $@"• “{Path.GetFileName(x.RelativeName)}” has already been altered by the “{x.ModName}” mod;") .JoinToString("\n").ToSentence () + $"\n\nEnabling {BbCodeBlock.Encode(mod.DisplayName)} may have adverse effects. Are you sure you want to enable this mod?", "Conflict", MessageBoxButton.YesNo, "genericMods.conflict") != MessageBoxResult.Yes) { return; } try { using (var waiting = WaitingDialog.Create("Enabling mod…")) { await _enabler.EnableAsync(mod, waiting, waiting.CancellationToken); Changed?.Invoke(this, EventArgs.Empty); if (waiting.CancellationToken.IsCancellationRequested) { waiting.Report(AsyncProgressEntry.FromStringIndetermitate("Cancellation…")); await _enabler.DisableAsync(mod); } } } catch (Exception e) { NonfatalError.Notify("Can’t enable mod", e); } })); }
public void Report(Showroom.ShootingProgress value) { Progress = new AsyncProgressEntry( string.Format(AppStrings.CarPreviews_Progress, _currentCar?.GetSkinById(value.SkinId)?.DisplayName ?? value.SkinId, value.SkinNumber + 1, value.TotalSkins), value.SkinNumber, value.TotalSkins); }
public IDisposable SetUploadProgress([CanBeNull] IProgress <AsyncProgressEntry> progress, long?suggestedTotal = null, Action callback = null) { var s = Stopwatch.StartNew(); void Handler(object sender, UploadProgressChangedEventArgs args) { if (s.Elapsed.TotalMilliseconds < 20) { return; } callback?.Invoke(); s.Restart(); var total = args.TotalBytesToSend; if (total == -1 && suggestedTotal != null && suggestedTotal > 0) { total = Math.Max(suggestedTotal.Value, args.BytesSent); } progress?.Report(AsyncProgressEntry.CreateUploading(args.BytesSent, total)); } UploadProgressChanged += Handler; return(new ActionAsDisposable(() => { UploadProgressChanged -= Handler; })); }
void IUserPresetable.ImportFromPresetData(string data) { if (_enabler == null || Enabled == null || Disabled == null) { return; } _busy.Task(async() => { await Task.Delay(10); var names = data.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); var enabled = Enabled.OfType <GenericMod>().OrderByDescending(x => x.AppliedOrder).ToList(); try { using (var waiting = WaitingDialog.Create("Loading mod profile…")) { for (var i = 0; i < enabled.Count; i++) { var mod = enabled[i]; waiting.Report(mod.DisplayName, i, enabled.Count); if (waiting.CancellationToken.IsCancellationRequested) { return; } await _enabler.DisableAsync(mod, null, waiting.CancellationToken); if (waiting.CancellationToken.IsCancellationRequested) { waiting.Report(AsyncProgressEntry.FromStringIndetermitate("Cancellation…")); await _enabler.EnableAsync(mod); } } for (var i = 0; i < names.Length; i++) { var mod = _enabler.GetByName(names[i]); if (mod == null) { continue; } waiting.Report(mod.DisplayName, i, enabled.Count); if (waiting.CancellationToken.IsCancellationRequested) { return; } await _enabler.EnableAsync(mod, null, waiting.CancellationToken); if (waiting.CancellationToken.IsCancellationRequested) { waiting.Report(AsyncProgressEntry.FromStringIndetermitate("Cancellation…")); await _enabler.DisableAsync(mod); } } } } catch (Exception e) { NonfatalError.Notify("Can’t load mod profile", e); } }).Forget(); }
private async Task <bool> FixAsync([NotNull] CarObject car, CarObject donor, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default(CancellationToken)) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Fixing sound…")); await car.ReplaceSound(donor); return(true); }
private Func <IProgress <AsyncProgressEntry>, CancellationToken, Task <bool> > FixAsync([NotNull] CarObject car, CarObject donor) { return(async(p, c) => { p?.Report(AsyncProgressEntry.FromStringIndetermitate("Fixing sound…")); await car.ReplaceSound(donor); return true; }); }
protected override Task <bool> FixAsync(CarObject car, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default(CancellationToken)) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Fixing car…")); var data = car.AcdData; if (data == null || data.IsEmpty) { return(Task.FromResult(false)); } Lut torque, power; try { torque = TorquePhysicUtils.LoadCarTorque(data); power = TorquePhysicUtils.TorqueToPower(torque); } catch (Exception e) { Logging.Error(e); return(Task.FromResult(false)); } var multipler = ActionExtension.InvokeInMainThread(() => { var dlg = new CarTransmissionLossSelector(car, torque.MaxY, power.MaxY); dlg.ShowDialog(); return(dlg.IsResultOk ? dlg.Multipler : (double?)null); }); if (!multipler.HasValue) { return(Task.FromResult(false)); } torque.TransformSelf(x => x.Y * multipler.Value); power.TransformSelf(x => x.Y * multipler.Value); if (car.SpecsTorqueCurve != null) { var torqueUi = new Lut(car.SpecsTorqueCurve.Points); torqueUi.TransformSelf(x => x.Y * multipler.Value); car.SpecsTorqueCurve = new GraphData(torqueUi); } if (car.SpecsPowerCurve != null) { var powerUi = new Lut(car.SpecsPowerCurve.Points); powerUi.TransformSelf(x => x.Y * multipler.Value); car.SpecsPowerCurve = new GraphData(powerUi); } car.SpecsTorque = SelectedAcObjectViewModel.SpecsFormat(AppStrings.CarSpecs_Torque_FormatTooltip, torque.MaxY.ToString(@"F0", CultureInfo.InvariantCulture)) + (multipler.Value == 1d ? "*" : ""); car.SpecsBhp = SelectedAcObjectViewModel.SpecsFormat(multipler.Value == 1d ? AppStrings.CarSpecs_PowerAtWheels_FormatTooltip : AppStrings.CarSpecs_Power_FormatTooltip, power.MaxY.ToString(@"F0", CultureInfo.InvariantCulture)); return(Task.FromResult(true)); }
public void Report(AsyncProgressEntry value) { var now = DateTime.Now; if ((now - _lastReport).TotalMilliseconds < 20d) { return; } _lastReport = now; ActionExtension.InvokeInMainThreadAsync(() => { _callback.Invoke(TrimProgressMessage(value, _trimStart)); }); }
protected override async Task <bool> LoadOverride(IProgress <AsyncProgressEntry> progress, CancellationToken cancellation) { if (_id != null) { var car = CarsManager.Instance.GetById(_id); if (car != null) { progress.Report(AsyncProgressEntry.Indetermitate); ObsoleteCars = new List <ObsoleteDetails> { await Task.Run(() => GetDetails(car, _models, true)) }; } else { ObsoleteCars = new List <ObsoleteDetails>(); } } else { var entries = new List <ObsoleteDetails>(); var filter = _filter == null ? null : Filter.Create(CarObjectTester.Instance, _filter); progress.Report(AsyncProgressEntry.FromStringIndetermitate("Loading cars…")); await CarsManager.Instance.EnsureLoadedAsync(); IEnumerable <CarObject> carsEnumerable = CarsManager.Instance.LoadedOnly.OrderBy(x => x.Name); if (filter != null) { carsEnumerable = carsEnumerable.Where(filter.Test); } var cars = carsEnumerable.ToList(); for (var i = 0; i < cars.Count; i++) { var car = cars[i]; progress.Report(new AsyncProgressEntry(car.Name, i, cars.Count)); try { var details = await Task.Run(() => GetDetails(car, _models, false)); if (details != null) { entries.Add(details); } } catch (Exception e) { NonfatalError.Notify($"Can’t check {car.DisplayName}", e); } } ObsoleteCars = entries; } return(ObsoleteCars.Count > 0); }
private static string TrimProgressMessage(AsyncProgressEntry value, string trimStart) { var msg = value.Message?.ToSentenceMember() ?? ""; if (trimStart != null && msg.Length > trimStart.Length && string.Equals(msg.Substring(0, trimStart.Length), trimStart, StringComparison.OrdinalIgnoreCase)) { msg = msg.Substring(trimStart.Length).TrimStart(); } return(msg); }
protected Task <bool> FixAsync([NotNull] CarObject car, Action <DataWrapper> action, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default(CancellationToken)) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Fixing car…")); return(Task.Run(() => { var data = car.AcdData; if (data == null || data.IsEmpty) { return false; } action(data); return true; })); }
private static async Task <byte[]> GetFlamesTexturesAsync(IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default(CancellationToken)) { if (_flamesTextures == null) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Loading flames textures…")); _flamesTextures = await CmApiProvider.GetStaticDataBytesAsync("flames", TimeSpan.FromDays(3), cancellation : cancellation); if (cancellation.IsCancellationRequested) { return(null); } } return(_flamesTextures); }
public static async Task <bool> FixSuspensionNodesAsync(CarObject car, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default(CancellationToken)) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Fixing car…")); return(await Task.Run(() => { var kn5Filename = FileUtils.GetMainCarFilename(car.Location, car.AcdData); if (kn5Filename == null || !File.Exists(kn5Filename)) { return false; } var kn5 = Kn5.FromFile(kn5Filename); FixSuspensionNodes(kn5); kn5.SaveRecyclingOriginal(kn5Filename); return true; })); }
public static async Task <bool> FixMissingTexturesAsync(CarObject car, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default(CancellationToken)) { var flamesTextures = await GetFlamesTexturesAsync(progress, cancellation); if (cancellation.IsCancellationRequested) { return(false); } progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Unpacking textures…")); return(await Task.Run(() => { var flamesDirectory = Path.Combine(car.Location, @"texture", @"flames"); flamesTextures.ExtractAsArchiveTo(flamesDirectory); return true; })); }
private Task <bool> FixAsync([NotNull] CarObject car, Action <Kn5> fix, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default(CancellationToken)) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Fixing car…")); return(Task.Run(() => { var kn5Filename = FileUtils.GetMainCarFilename(car.Location, car.AcdData); if (kn5Filename == null || !File.Exists(kn5Filename)) { return false; } var kn5 = Kn5.FromFile(kn5Filename); fix.Invoke(kn5); kn5.SaveRecyclingOriginal(kn5Filename); return true; })); }
public static async Task <bool> UpgradeToSecondVersionAsync(CarObject car, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default(CancellationToken)) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Updating data…")); if (!await Task.Run(() => { var data = car.AcdData; if (data == null || data.IsEmpty) { return(false); } var flames = data.GetIniFile("flames.ini"); var header = flames["HEADER"]; header.Set("EDIT_BIG", false); header.Set("EDIT_STATE", 4); header.Set("BURN_FUEL_MULT", 10); header.Set("FLASH_THRESHOLD", 7); foreach (var section in flames.GetSections("FLAME")) { section.Set("IS_LEFT", section.GetVector3("POSITION").FirstOrDefault() < 0d); section.Set("GROUP", 0); } flames.Save(); Logging.Write($"Fixed: flames.ini of {car.DisplayName}"); var flamesPresetsEncoded = @"jdPBjoIwEAbgOwlvUjedgSJ74MDGgia4kFIPaja8/1s4BVdaW1IPcIDhy/Dzcz/K+iDVX5qMp5uczpdOV5AmaXIflBy" + @"lnkZdKz1xGtDq1LZSVTxN+qahexX/4ux54AKYS4JGr4M0c6r9qVAIBiVnIGgOfRosGgI0vGR4wmDByBnOk3tfRkvG0NLluvQ+sPTLLm1b/h6cO" + @"PJIHEVg628aWl7NdSG2cbG6+bbrhmFgjHw/8F0MuMJ2u74ftosBbEfn2V5jhsxdGrBkIpDFTG8Wg5pkbDR9Kj6xTWxv+GY3stnO6alMrLZwQ7Ft" + @"J5Omq8ejE0rwM3I/bqt4/2mDL8d+Fp59JLuBLHSsInb3Ap0mGpatHw=="; var flamesPresets = data.GetRawFile(@"flame_presets.ini"); flamesPresets.Content = Encoding.UTF8.GetString(new DeflateStream( new MemoryStream(Convert.FromBase64String(flamesPresetsEncoded)), CompressionMode.Decompress).ReadAsBytesAndDispose()); flamesPresets.Save(); Logging.Write($"Fixed: flame_presets.ini of {car.DisplayName}"); return(true); }) || cancellation.IsCancellationRequested) { return(false); } return(await FixMissingTexturesAsync(car, progress, cancellation)); }
public async Task <bool> LoadAsync(ListAddCallback <ServerInformation> callback, IProgress <AsyncProgressEntry> progress, CancellationToken cancellation) { if (SteamIdHelper.Instance.Value == null) { throw new Exception(ToolsStrings.Common_SteamIdIsMissing); } var data = await Task.Run(() => KunosApiProvider.TryToGetList(progress == null ? null : new ProgressConverter(progress)), cancellation); // if (cancellation.IsCancellationRequested) return false; if (data == null) { throw new InformativeException(ToolsStrings.Online_CannotLoadData, ToolsStrings.Common_MakeSureInternetWorks); } progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Applying list…")); callback(data); return(true); }
public Task DisableMod(GenericMod mod) { return(_busy.Task(async() => { if (_enabler == null || !mod.IsEnabled) { return; } try { using (var waiting = WaitingDialog.Create("Disabling mod…")) { await _enabler.DisableAsync(mod, waiting, waiting.CancellationToken); Changed?.Invoke(this, EventArgs.Empty); if (waiting.CancellationToken.IsCancellationRequested) { waiting.Report(AsyncProgressEntry.FromStringIndetermitate("Cancellation…")); await _enabler.EnableAsync(mod); } } } catch (Exception e) { NonfatalError.Notify("Can’t disable mod", e); } })); }
private static async Task <IReadOnlyList <ExtraOption> > GetGbwRelatedExtraOptions(ContentEntryBase[] entries) { const string gbwWeatherPart = "_gbW_"; const string gbwPpFilterPart = "__gbW"; if (!entries.Any(x => x.Id.Contains(gbwWeatherPart))) { // This is not the GBW pack return(new ExtraOption[0]); } var gbwWeatherIds = entries.Where(x => x.Id.Contains(gbwWeatherPart) && x is WeatherContentEntry) .Select(x => x.Id).ToList(); if (gbwWeatherIds.Count < 10) { // It contains some GBW weather, but not a lot — not the pack return(new ExtraOption[0]); } await WeatherManager.Instance.EnsureLoadedAsync(); // Now, when data is loaded, we’re ready to create some extra options IEnumerable <ExtraOption> GetOptions() { { var installedWeatherIds = WeatherManager.Instance.WrappersList.Select(x => x.Id).Where(x => x.Contains(gbwWeatherPart)).ToList(); var obsoleteWeatherIds = installedWeatherIds.ApartFrom(gbwWeatherIds).ToList(); if (obsoleteWeatherIds.Count > 0) { var obsoleteLine = obsoleteWeatherIds.Select(x => $"“{WeatherManager.Instance.GetById(x)?.DisplayName ?? x}”") .JoinToReadableString(); yield return(new ExtraOption("Remove obsolete GBW weather", $"Installed, but not found here: {obsoleteLine}.", async(progress, cancellation) => { progress.Report(AsyncProgressEntry.FromStringIndetermitate("Removing obsolete GBW weather…")); await WeatherManager.Instance.EnsureLoadedAsync(); await WeatherManager.Instance.DeleteAsync(obsoleteWeatherIds); }, activeByDefault: true)); } } { var gbwPpFilterIds = entries.Where(x => x.Id.Contains(gbwPpFilterPart) && x is PpFilterContentEntry) .Select(x => x.Id).ToList(); var installedPpFilterIds = PpFiltersManager.Instance.WrappersList.Select(x => x.Id).Where(x => x.Contains(gbwPpFilterPart)).ToList(); var obsoletePpFilterIds = installedPpFilterIds.ApartFrom(gbwPpFilterIds).ToList(); if (obsoletePpFilterIds.Count > 0) { var obsoleteLine = obsoletePpFilterIds.Select(x => $"“{PpFiltersManager.Instance.GetById(x)?.DisplayName ?? x}”") .JoinToReadableString(); yield return(new ExtraOption("Remove obsolete GBW PP-filters", $"Installed, but not found here: {obsoleteLine}.", async(progress, cancellation) => { progress.Report(AsyncProgressEntry.FromStringIndetermitate("Removing obsolete GBW PP-filters…")); await PpFiltersManager.Instance.EnsureLoadedAsync(); await PpFiltersManager.Instance.DeleteAsync(obsoletePpFilterIds); }, activeByDefault: true)); } } } return(GetOptions().ToList()); }
public async Task <Scanned> GetEntriesAsync([NotNull] List <IFileInfo> list, string baseId, string baseName, [CanBeNull] IProgress <AsyncProgressEntry> progress, CancellationToken cancellation) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Scanning…")); var result = new List <ContentEntryBase>(); var missingContent = false; Exception readException = null; var s = Stopwatch.StartNew(); var root = new DirectoryNode(_installationParams.FallbackId ?? baseId, null); root.ForceName(baseName); foreach (var info in list) { root.Add(info); } Logging.Debug($"Building tree: {s.Elapsed.TotalMilliseconds:F1} ms"); s.Restart(); var queue = new Queue <DirectoryNode>(); queue.Enqueue(root); while (queue.Count > 0) { var directory = queue.Dequeue(); ContentEntryBase found; try { found = await CheckDirectoryNode(directory, cancellation).ConfigureAwait(false); // WHY IT DOES NOT WORK? if (cancellation.IsCancellationRequested) { break; } } catch (Exception e) when(e.IsCancelled()) { break; } catch (MissingContentException) { missingContent = true; continue; } catch (Exception e) { Logging.Warning(e); readException = e; continue; } if (found != null) { result.Add(found); } else { foreach (var value in directory.Directories) { queue.Enqueue(value); } foreach (var value in directory.Files) { try { found = await CheckFileNode(value, cancellation).ConfigureAwait(false); if (cancellation.IsCancellationRequested) { break; } } catch (Exception e) when(e.IsCancelled()) { break; } catch (MissingContentException) { missingContent = true; continue; } catch (Exception e) { Logging.Warning(e); readException = e; continue; } if (found != null) { result.Add(found); } } } } Logging.Debug($"Scanning directories: {s.Elapsed.TotalMilliseconds:F1} ms"); return(new Scanned(result, missingContent, readException)); }
public static async Task <T> PostMultipart <T>(string url, object metadata, string authToken, byte[] data, string contentType, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default(CancellationToken)) { try { const string boundary = "--fdfmkj4ixeyfzuxr6q3yp66ry53lerk98g33ow29e0khjjor"; var prefix = Encoding.UTF8.GetBytes(boundary + "\nContent-Type: application/json; charset=UTF-8\n\n" + JsonConvert.SerializeObject(metadata) + "\n\n" + boundary + "\nContent-Type: " + contentType + "\n\n"); var postfix = Encoding.UTF8.GetBytes("\n" + boundary + "--"); var total = prefix.Length + data.Length + postfix.Length; var request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.UserAgent = InternalUtils.GetKunosUserAgent(); request.ContentType = "multipart/related; boundary=" + boundary.Substring(2); request.ContentLength = total; request.Headers["Authorization"] = "Bearer " + authToken; using (var stream = await request.GetRequestStreamAsync()) { if (cancellation.IsCancellationRequested) { return(default(T)); } progress?.Report(AsyncProgressEntry.CreateUploading(0, total)); await stream.WriteAsync(prefix, 0, prefix.Length, cancellation); if (cancellation.IsCancellationRequested) { return(default(T)); } const int blockSize = 10240; for (var i = 0; i < data.Length; i += blockSize) { progress?.Report(AsyncProgressEntry.CreateUploading(prefix.Length + i, total)); await stream.WriteAsync(data, i, Math.Min(blockSize, data.Length - i), cancellation); if (cancellation.IsCancellationRequested) { return(default(T)); } } progress?.Report(AsyncProgressEntry.CreateUploading(prefix.Length + data.Length, total)); await stream.WriteAsync(postfix, 0, postfix.Length, cancellation); if (cancellation.IsCancellationRequested) { return(default(T)); } } string result; using (var response = (HttpWebResponse)await request.GetResponseAsync()) using (var stream = response.GetResponseStream()) { if (cancellation.IsCancellationRequested) { return(default(T)); } if (stream == null) { return(default(T)); } using (var reader = new StreamReader(stream, Encoding.UTF8)) { result = await reader.ReadToEndAsync(); if (cancellation.IsCancellationRequested) { return(default(T)); } } } // Logging.Write("Upload result: " + result); return(JsonConvert.DeserializeObject <T>(result)); } catch (WebException e) { using (var stream = e.Response.GetResponseStream()) { Logging.Warning("Prepare() error: " + e); if (stream != null) { Logging.Warning("Prepare() response: " + new StreamReader(stream, Encoding.UTF8).ReadToEnd()); } } return(default(T)); } catch (Exception e) { Logging.Warning("Prepare() error: " + e); return(default(T)); } }
private async Task TryToPing() { var pingId = ++_pingId; for (var attemptsLeft = Math.Max(SettingsHolder.Online.PingAttempts, 1); attemptsLeft > 0; attemptsLeft--) { var lastAttempt = attemptsLeft == 1; var debugPinging = Ip == OptionDebugPing; if (debugPinging) { Logging.Debug("Pinging THAT server, attempts left: " + (attemptsLeft - 1)); Logging.Debug("Timeout: " + SettingsHolder.Online.PingTimeout); Logging.Debug("Threads pinging: " + SettingsHolder.Online.ThreadsPing); } UpdateProgress = new AsyncProgressEntry("Pinging server…", 0.3); var pair = SettingsHolder.Online.ThreadsPing ? await Task.Run(() => KunosApiProvider.TryToPingServer(Ip, Port, SettingsHolder.Online.PingTimeout, debugPinging)) : await KunosApiProvider.TryToPingServerAsync(Ip, Port, SettingsHolder.Online.PingTimeout, debugPinging); if (pingId != _pingId) { return; } if (debugPinging) { if (pair == null) { Logging.Warning("Result: FAILED"); } else { Logging.Debug($"Result: {pair.Item2.TotalMilliseconds:F1} ms"); } } if (pair != null) { Ping = (long)pair.Item2.TotalMilliseconds; _updatePingFailed = false; break; } if (lastAttempt) { Ping = null; _updatePingFailed = true; // resultStatus = ServerStatus.Error; // return; } else { await Task.Delay(150); if (pingId != _pingId) { return; } } } UpdateErrorsList(); }
public async Task Update(UpdateMode mode, bool background = false, bool fast = false) { if (_updating) { return; } _updating = true; _pingId++; var driversCount = -1; var resultStatus = ServerStatus.Ready; try { // If it’s a background update, don’t change anything in UI to avoid flashing if (!background) { CurrentDrivers = null; Status = ServerStatus.Loading; IsAvailable = false; } // Reset some update-state values PrepareErrorsList(); // Nothing loaded at all! var informationUpdated = false; if (!IsFullyLoaded) { UpdateProgress = new AsyncProgressEntry(ToolsStrings.Online_LoadingActualInformation, 0.1); ServerInformationComplete loaded; try { loaded = await GetInformationDirectly(); } catch (HttpRequestException e) { if (e.InnerException is WebException webException) { _updateWebException = webException; } else { _updateException = e; } resultStatus = ServerStatus.Error; return; } catch (WebException e) { _updateWebException = e; resultStatus = ServerStatus.Error; return; } var update = UpdateValues(loaded, false, true); if (update != null) { resultStatus = update.Value; if (update != ServerStatus.MissingContent) { // Loaded data isn’t for this server (port by which it was loaded differs). // Won’t even set drivers count in this case, whole data is obviously wrong. return; } } driversCount = loaded.Clients; // Set this flag to True so we won’t use GetInformationDirectly() again later informationUpdated = true; } // Extended mode for server wrapping thing var informationLoadedExtended = false; ServerCarsInformation carsInformation = null; if (DetailsPort != null) { try { var extended = await GetExtendedInformationDirectly(); var update = UpdateValues(extended, false, true); if (update != null) { resultStatus = update.Value; if (update != ServerStatus.MissingContent) { UpdateValuesExtended(null); return; } } UpdateValuesExtended(extended); driversCount = extended.Clients; carsInformation = extended.Players; informationLoadedExtended = true; } catch (Exception e) { Logging.Warning(e); DetailsPort = null; UpdateValuesExtended(null); return; } } else if (DetailsId != null) { try { var extended = await CmApiProvider.GetOnlineDataAsync(DetailsId); if (extended != null) { Country = extended.Country?.FirstOrDefault() ?? Country; CountryId = extended.Country?.ArrayElementAtOrDefault(1) ?? CountryId; Sessions?.ForEach((x, i) => x.Duration = extended.Durations?.ElementAtOrDefault(i) ?? x.Duration); } UpdateValuesExtended(extended); } catch (Exception e) { Logging.Warning(e); UpdateValuesExtended(null); return; } } else { UpdateValuesExtended(null); } // Update information if (!informationLoadedExtended && (mode != UpdateMode.Lite || !(Sessions?.Count > 0) // if there are no sessions (!), maybe information is damaged, let’s re-download )) { UpdateProgress = new AsyncProgressEntry(ToolsStrings.Online_LoadingActualInformation, 0.2); ServerInformationComplete loaded; try { // If informationUpdated is True and settings set to update-information-directly mode, this method // will return 0. loaded = await GetInformation(informationUpdated); } catch (WebException e) { _updateWebException = e; resultStatus = ServerStatus.Error; return; } if (loaded != null) { if (loaded.Ip == Ip && loaded.PortHttp == PortHttp || informationUpdated || loaded.LoadedDirectly) { // If loaded information is compatible with existing, use it immediately. Otherwise — apparently, // server changed — we’ll try to load an actual data directly from it later, but only if it wasn’t // loaded just before that and loaded information wasn’t loaded from it. var update = UpdateValues(loaded, false, true); if (update != null) { resultStatus = update.Value; if (update != ServerStatus.MissingContent) { return; } } driversCount = loaded.Clients; } else { ServerInformation directlyLoaded; try { directlyLoaded = await GetInformationDirectly(); } catch (WebException e) { _updateWebException = e; resultStatus = ServerStatus.Error; return; } var update = UpdateValues(directlyLoaded, false, true); if (update != null) { resultStatus = update.Value; if (update != ServerStatus.MissingContent) { return; } } driversCount = loaded.Clients; } } } // Load players list if (carsInformation == null) { UpdateProgress = new AsyncProgressEntry(ToolsStrings.Online_LoadingPlayersList, 0.4); try { carsInformation = await KunosApiProvider.GetCarsInformationAsync(Ip, PortHttp); } catch (WebException e) { _updateWebException = e; resultStatus = ServerStatus.Error; return; } } if (!BookingMode) { CurrentDriversCount = carsInformation.Cars.Count(x => x.IsConnected); driversCount = -1; } var currentDrivers = (BookingMode ? carsInformation.Cars : carsInformation.Cars.Where(x => x.IsConnected)) .Select(x => { var driver = CurrentDrivers?.FirstOrDefault(y => y.SameAs(x)) ?? new CurrentDriver(x, RequiredCspVersion != 0); return(driver); }) .ToList(); if (CurrentDrivers == null || !CurrentDrivers.SequenceEqual(currentDrivers)) { CurrentDrivers = currentDrivers; var count = 0; var booked = false; foreach (var x in currentDrivers) { if (x.IsConnected) { count++; } if (x.IsBookedForPlayer) { booked = true; SetSelectedCarEntry(Cars?.GetByIdOrDefault(x.CarId, StringComparison.OrdinalIgnoreCase)); } } ConnectedDrivers = count; IsBookedForPlayer = booked; } if (Cars == null) { Logging.Unexpected(); _updateDriversMissing = true; resultStatus = ServerStatus.Error; return; } for (int i = 0, c = Cars.Count; i < c; i++) { var entry = Cars[i]; var wrapper = entry.CarWrapper; CarObject car; // Load car if not loaded if (wrapper != null) { if (wrapper.IsLoaded) { car = (CarObject)wrapper.Value; } else { UpdateProgress = new AsyncProgressEntry(string.Format(ToolsStrings.Online_LoadingCars, wrapper.Id), 0.5 + 0.4 * i / c); await Task.Delay(fast? 10 : 50); car = (CarObject)await wrapper.LoadedAsync(); } car.SubscribeWeak(OnContentNameChanged); } else { car = null; } // Load skin if (car?.SkinsManager.IsLoaded == false) { UpdateProgress = new AsyncProgressEntry(string.Format(ToolsStrings.Online_LoadingSkins, car.DisplayName), 0.5 + 0.4 * (0.5 + i) / c); await Task.Delay(fast? 10 : 50); await car.SkinsManager.EnsureLoadedAsync(); } // Set next available skin if (CurrentSessionType == Game.SessionType.Booking) { entry.SetAvailableSkinId(car?.SelectedSkin?.Id, null); entry.Total = 0; entry.Available = 0; entry.IsAvailable = true; } else { var cars = carsInformation.Cars.Where(x => x.IsEntryList && string.Equals(x.CarId, entry.Id, StringComparison.OrdinalIgnoreCase)).ToList(); ServerActualCarInformation availableSkin; if (BookingMode) { availableSkin = cars.FirstOrDefault(x => x.IsRequestedGuid); entry.Total = 0; entry.Available = 0; entry.IsAvailable = true; } else { availableSkin = cars.FirstOrDefault(y => !y.IsConnected); entry.Total = cars.Count; entry.Available = cars.Count(y => !y.IsConnected); entry.IsAvailable = entry.Available > 0; } entry.SetAvailableSkinId(availableSkin?.CarSkinId, RequiredCspVersion == 0 ? null : availableSkin?.CspParams); } } var missingContentUpdate = UpdateMissingContentExtended(resultStatus == ServerStatus.MissingContent); if (missingContentUpdate.HasValue) { resultStatus = missingContentUpdate.Value; } if (IsBookedForPlayer) { FixedCar = true; } else { FixedCar = false; LoadSelectedCar(); } // Ping server if (Ping == null || mode == UpdateMode.Full || !SettingsHolder.Online.PingOnlyOnce) { if (mode == UpdateMode.Lite) { await TryToPing(); } else { TryToPing().Ignore(); } } } catch (Exception e) { _updateException = e; resultStatus = ServerStatus.Error; Logging.Error(e); } finally { if (driversCount != -1) { CurrentDriversCount = driversCount; } UpdateProgress = AsyncProgressEntry.Ready; Status = !SettingsHolder.Online.LoadServersWithMissingContent && resultStatus == ServerStatus.MissingContent ? ServerStatus.Error : resultStatus; UpdateMissingContent(); UpdateErrorsList(); AvailableUpdate(); _updating = false; } }
public static async Task <string> LoadAsyncTo(string argument, FlexibleLoaderGetPreferredDestinationCallback getPreferredDestination, [CanBeNull] FlexibleLoaderReportDestinationCallback reportDestination, Action <FlexibleLoaderMetaInformation> reportMetaInformation = null, Func <bool> checkIfPaused = null, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Finding fitting loader…")); var loader = await CreateLoaderAsync(argument, cancellation) ?? throw new OperationCanceledException(); try { using (var order = KillerOrder.Create(new CookieAwareWebClient(), TimeSpan.FromMinutes(10))) { var client = order.Victim; if (_proxy != null) { client.Proxy = _proxy; } progress?.Report(AsyncProgressEntry.Indetermitate); cancellation.ThrowIfCancellationRequested(); cancellation.Register(client.CancelAsync); if (!await loader.PrepareAsync(client, cancellation)) { throw new InformativeException("Can’t load file", "Loader preparation failed."); } cancellation.ThrowIfCancellationRequested(); reportMetaInformation?.Invoke(FlexibleLoaderMetaInformation.FromLoader(loader)); var initialProgressCallback = true; var reportStopwatch = Stopwatch.StartNew(); var progressStopwatch = new AsyncProgressBytesStopwatch(); if (loader.UsesClientToDownload) { client.DownloadProgressChanged += (sender, args) => { if (initialProgressCallback) { reportMetaInformation?.Invoke(FlexibleLoaderMetaInformation.FromLoader(loader)); initialProgressCallback = false; } if (reportStopwatch.Elapsed.TotalMilliseconds < 20) { return; } order.Delay(); reportStopwatch.Restart(); progress?.Report(AsyncProgressEntry.CreateDownloading(args.BytesReceived, args.TotalBytesToReceive == -1 && loader.TotalSize.HasValue ? Math.Max(loader.TotalSize.Value, args.BytesReceived) : args.TotalBytesToReceive, progressStopwatch)); }; } var loaded = await loader.DownloadAsync(client, getPreferredDestination, reportDestination, checkIfPaused, loader.UsesClientToDownload?null : new Progress <long>(p => { if (initialProgressCallback) { reportMetaInformation?.Invoke(FlexibleLoaderMetaInformation.FromLoader(loader)); initialProgressCallback = false; } if (reportStopwatch.Elapsed.TotalMilliseconds < 20) { return; } order.Delay(); reportStopwatch.Restart(); progress?.Report(loader.TotalSize.HasValue ? AsyncProgressEntry.CreateDownloading(p, loader.TotalSize.Value, progressStopwatch) : new AsyncProgressEntry(string.Format(UiStrings.Progress_Downloading, p.ToReadableSize(1)), null)); }), cancellation); cancellation.ThrowIfCancellationRequested(); Logging.Write("Loaded: " + loaded); return(loaded); } } catch (Exception e) when(cancellation.IsCancellationRequested || e.IsCancelled()) { Logging.Warning("Cancelled"); throw new OperationCanceledException(); } catch (Exception e) { Logging.Warning(e); throw; } }
public async Task <IReadOnlyList <ServerInformationComplete> > ScanForServers(string address, IProgress <AsyncProgressEntry> progress, CancellationToken cancellation) { if (address == null) { throw new ArgumentNullException(nameof(address)); } // assume address is something like [HOSTNAME]:[HTTP PORT] if (!KunosApiProvider.ParseAddress(address, out var ip, out var port)) { throw new Exception(ToolsStrings.Online_CannotParseAddress); } if (port > 0) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate(ToolsStrings.Online_GettingInformationDirectly)); ServerInformationComplete information; try { information = await KunosApiProvider.GetInformationDirectAsync(ip, port); } catch (WebException) { if (cancellation.IsCancellationRequested) { return(null); } // assume address is [HOSTNAME]:[TCP PORT] progress?.Report(AsyncProgressEntry.FromStringIndetermitate(ToolsStrings.Online_TryingToFindOutHttpPort)); var pair = await KunosApiProvider.TryToPingServerAsync(ip, port, SettingsHolder.Online.PingTimeout); if (cancellation.IsCancellationRequested) { return(null); } if (pair != null) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate(ToolsStrings.Online_GettingInformationDirectly_SecondAttempt)); try { information = await KunosApiProvider.GetInformationDirectAsync(ip, pair.Item1); } catch (WebException) { information = null; } } else { information = null; } } if (cancellation.IsCancellationRequested) { return(null); } return(information == null ? new ServerInformationComplete[0] : new [] { information }); } else { var result = new List <ServerInformationComplete>(); // assume address is [HOSTNAME] progress?.Report(AsyncProgressEntry.FromStringIndetermitate(ToolsStrings.Common_Scanning)); var scanned = 0; var portsDiapason = PortsDiapason.Create(SettingsHolder.Online.PortsEnumeration); var total = portsDiapason.Count(); await portsDiapason.Select(async p => { var pair = await KunosApiProvider.TryToPingServerAsync(ip, p, SettingsHolder.Online.ScanPingTimeout); if (pair != null && pair.Item1 > 1024 && pair.Item1 < 65536) { if (cancellation.IsCancellationRequested) { return; } try { var information = await KunosApiProvider.GetInformationDirectAsync(ip, pair.Item1); if (cancellation.IsCancellationRequested) { return; } result.Add(information); } catch (WebException) { } } scanned++; progress?.Report(new AsyncProgressEntry(string.Format(ToolsStrings.Online_ScanningProgress, scanned, total, PluralizingConverter.PluralizeExt(result.Count, ToolsStrings.Online_ScanningProgress_Found)), scanned, total)); }).WhenAll(200, cancellation); return(result); } }
public void Report(int value) { _target.Report(value == 0 ? AsyncProgressEntry.Indetermitate : AsyncProgressEntry.FromStringIndetermitate(string.Format(ToolsStrings.OnlineSource_Loading_Fallback, value + 1))); }
public async Task <string> PostMultipart(string url, object metadata, string authToken, [NotNull] byte[] data, string contentType, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default(CancellationToken), NameValueCollection extraHeaders = null) { try { const string boundary = "--fdfmkj4ixeyfzuxr6q3yp66ry53lerk98g33ow29e0khjjor"; var prefix = Encoding.UTF8.GetBytes(boundary + "\nContent-Type: application/json; charset=UTF-8\n\n" + JsonConvert.SerializeObject(metadata) + "\n\n" + boundary + "\nContent-Type: " + contentType + "\n\n"); var postfix = Encoding.UTF8.GetBytes("\n" + boundary + "--"); var total = prefix.Length + data.Length + postfix.Length; var request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.UserAgent = InternalUtils.GetKunosUserAgent(); request.ContentType = "multipart/related; boundary=" + boundary.Substring(2); request.ContentLength = total; request.Headers["Authorization"] = "Bearer " + authToken; if (extraHeaders != null) { foreach (string header in extraHeaders) { request.Headers[header] = extraHeaders[header]; } } var stopwatch = new AsyncProgressBytesStopwatch(); using (var stream = await request.GetRequestStreamAsync()) { if (cancellation.IsCancellationRequested) { return(null); } progress?.Report(AsyncProgressEntry.CreateUploading(0, total, stopwatch)); await stream.WriteAsync(prefix, 0, prefix.Length, cancellation); if (cancellation.IsCancellationRequested) { return(null); } const int blockSize = 10240; for (var i = 0; i < data.Length; i += blockSize) { progress?.Report(AsyncProgressEntry.CreateUploading(prefix.Length + i, total, stopwatch)); await stream.WriteAsync(data, i, Math.Min(blockSize, data.Length - i), cancellation); if (cancellation.IsCancellationRequested) { return(null); } } progress?.Report(AsyncProgressEntry.CreateUploading(prefix.Length + data.Length, total, stopwatch)); await stream.WriteAsync(postfix, 0, postfix.Length, cancellation); if (cancellation.IsCancellationRequested) { return(null); } } string result; using (var response = (HttpWebResponse)await request.GetResponseAsync()) using (var stream = response.GetResponseStream()) { if (cancellation.IsCancellationRequested) { return(null); } if (stream == null) { return(null); } using (var reader = new StreamReader(stream, Encoding.UTF8)) { result = await reader.ReadToEndAsync(); if (cancellation.IsCancellationRequested) { return(null); } } } return(result); } catch (Exception e) { var wrapped = ApiException.Wrap(e, cancellation); if (wrapped == null) { throw; } throw wrapped; } }
protected override Task <bool> FixAsync(CarObject car, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default(CancellationToken)) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Fixing car…")); return(CarReplaceTyresDialog.Run(car)); }
public static async Task <string> LoadAsyncTo(string argument, string destination, IProgress <AsyncProgressEntry> progress = null, Action <FlexibleLoaderMetaInformation> metaInformationCallback = null, CancellationToken cancellation = default(CancellationToken)) { var loader = CreateLoader(argument); try { using (var order = KillerOrder.Create(new CookieAwareWebClient { Headers = { [HttpRequestHeader.UserAgent] = CmApiProvider.UserAgent } }, TimeSpan.FromMinutes(10))) { var client = order.Victim; if (_proxy != null) { client.Proxy = _proxy; } progress?.Report(AsyncProgressEntry.Indetermitate); cancellation.ThrowIfCancellationRequested(); cancellation.Register(client.CancelAsync); if (!await loader.PrepareAsync(client, cancellation)) { throw new InformativeException("Can’t load file", "Loader preparation failed."); } cancellation.ThrowIfCancellationRequested(); metaInformationCallback?.Invoke(new FlexibleLoaderMetaInformation(loader.TotalSize, loader.FileName, loader.Version)); var s = Stopwatch.StartNew(); if (loader.UsesClientToDownload) { client.DownloadProgressChanged += (sender, args) => { if (s.Elapsed.TotalMilliseconds > 20) { order.Delay(); s.Restart(); } else { return; } var total = args.TotalBytesToReceive; if (total == -1 && loader.TotalSize != -1) { total = Math.Max(loader.TotalSize, args.BytesReceived); } progress?.Report(AsyncProgressEntry.CreateDownloading(args.BytesReceived, total)); }; } await loader.DownloadAsync(client, destination, loader.UsesClientToDownload?null : new Progress <double>(p => { if (s.Elapsed.TotalMilliseconds > 20) { order.Delay(); s.Restart(); } else { return; } var total = loader.TotalSize; progress?.Report(total == -1 ? new AsyncProgressEntry("Loading…", p) : AsyncProgressEntry.CreateDownloading((long)(p * total), total)); }), cancellation); cancellation.ThrowIfCancellationRequested(); } } catch (Exception) when(cancellation.IsCancellationRequested) { throw new OperationCanceledException(); } return(destination); }