private async void ShotAsync(Action <IProgress <Tuple <string, double?> >, CancellationToken> action) { if (_busy) { return; } _busy = true; try { using (var waiting = new WaitingDialog { WindowStartupLocation = WindowStartupLocation.CenterScreen, Owner = null }) { waiting.Report(AsyncProgressEntry.Indetermitate); var cancellation = waiting.CancellationToken; Renderer.IsPaused = true; try { await Task.Run(() => { // ReSharper disable once AccessToDisposedClosure action(waiting, cancellation); }); } finally { Renderer.IsPaused = false; } } } catch (Exception e) { NonfatalError.Notify("Can’t build image", e); } finally { _busy = false; UpdateSize(); } }
public async Task <byte[]> GetModel(string key) { if (key != ExtraModels.KeyCrewExtra) { return(null); } using (var dialog = new WaitingDialog()) { dialog.Report(ControlsStrings.Common_Downloading); var data = await CmApiProvider.GetStaticDataBytesAsync("cs_crew", TimeSpan.FromDays(3), dialog, dialog.CancellationToken); if (data == null) { return(null); } return(await Task.Run(() => { using (var stream = new MemoryStream(data, false)) using (var archive = new ZipArchive(stream)) { return archive.GetEntry("Crew.kn5")?.Open().ReadAsBytesAndDispose(); } })); } }
public async Task <byte[]> GetModel(string key) { if (key != ExtraModels.KeyCrewExtra) { return(null); } var temporary = FilesStorage.Instance.GetTemporaryFilename("Crew.kn5"); if (!File.Exists(temporary)) { using (var dialog = new WaitingDialog()) { dialog.Report(ControlsStrings.Common_Downloading); var data = await CmApiProvider.GetDataAsync("static/get/cs_crew", dialog, dialog.CancellationToken); if (data == null) { return(null); } await Task.Run(() => { using (var stream = new MemoryStream(data, false)) using (var archive = new ZipArchive(stream)) { archive.GetEntry("Crew.kn5").ExtractToFile(temporary); } }); } } return(await FileUtils.ReadAllBytesAsync(temporary).ConfigureAwait(false)); }
protected override async Task ExecuteInner() { try { using (var waiting = new WaitingDialog()) { waiting.Report("Solving the issue…"); await _execute(waiting.CancellationToken); } } catch (TaskCanceledException) { return; } catch (Exception e) { NonfatalError.Notify("Can’t solve the issue", e); return; } if (_entry != null) { NonfatalError.Instance.Errors.Remove(_entry); } }
private static async Task <IReadOnlyList <UpdatePreviewError> > Run([NotNull] CarObject car, [CanBeNull] string skinId, [CanBeNull] IReadOnlyList <ToUpdatePreview> toUpdate, [CanBeNull] string presetFilename) { var carKn5 = FileUtils.GetMainCarFilename(car.Location, car.AcdData); if (!File.Exists(carKn5)) { ModernDialog.ShowMessage("Model not found"); return(null); } await PrepareAsync(); Kn5 kn5; using (var waiting = new WaitingDialog()) { waiting.Report("Loading model…"); kn5 = await Task.Run(() => Kn5.FromFile(carKn5)); } using (var renderer = new DarkKn5ObjectRenderer(CarDescription.FromKn5(kn5, car.Location, car.AcdData)) { AutoRotate = false, AutoAdjustTarget = false, AsyncTexturesLoading = true, AsyncOverridesLoading = true, AutoloadCarLights = false, AutoloadShowroomLights = false }) { var wrapper = new CmPreviewsFormWrapper(car, renderer, skinId, presetFilename); if (toUpdate != null) { wrapper.SetToUpdate(toUpdate); } wrapper.Form.Icon = AppIconService.GetAppIcon(); wrapper.Run(); return(wrapper.GetErrors()); } }
protected override async Task ExecuteInner() { try { using (var waiting = new WaitingDialog()) { waiting.Report("Solving the issue…"); await _execute(waiting.CancellationToken); } } catch (TaskCanceledException) { return; } catch (Exception e) { NonfatalError.Notify("Can’t solve the issue", e); return; } Solved = true; if (_entry != null) { NonfatalError.Instance.Errors.Remove(_entry); } }
public static async Task Run(TrackObjectBase track) { var modelsFilename = track.ModelsFilename; string kn5Filename = null; if (!File.Exists(modelsFilename)) { modelsFilename = null; kn5Filename = Path.Combine(track.Location, track.Id + ".kn5"); if (!File.Exists(kn5Filename)) { ModernDialog.ShowMessage("Model not found"); return; } } Kn5 kn5; using (var waiting = new WaitingDialog()) { waiting.Report("Loading model…"); kn5 = await Task.Run(() => modelsFilename != null ? Kn5.FromModelsIniFile(modelsFilename) : Kn5.FromFile(kn5Filename)); } using (var renderer = new TrackMapPreparationRenderer(kn5)) { var wrapper = new TrackMapRendererWrapper(track, renderer); wrapper.Form.Icon = AppIconService.GetAppIcon(); wrapper.Run(); } }
public static async Task JoinInvitation([NotNull] string ip, int port, [CanBeNull] string password) { OnlineManager.EnsureInitialized(); var list = OnlineManager.Instance.List; var source = new FakeSource(ip, port); var wrapper = new OnlineSourceWrapper(list, source); ServerEntry server; using (var waiting = new WaitingDialog()) { waiting.Report(ControlsStrings.Common_Loading); await wrapper.EnsureLoadedAsync(); server = list.GetByIdOrDefault(source.Id); if (server == null) { throw new Exception(@"Unexpected"); } } if (password != null) { server.Password = password; } var content = new OnlineServer(server) { Margin = new Thickness(0, 0, 0, -38), ToolBar = { FitWidth = true }, // Values taken from ModernDialog.xaml // TODO: Extract them to some style? Title = { FontSize = 24, FontWeight = FontWeights.Light, Margin = new Thickness(6, 0, 0, 8) } }; content.Title.SetValue(TextOptions.TextFormattingModeProperty, TextFormattingMode.Ideal); var dlg = new ModernDialog { ShowTitle = false, Content = content, MinHeight = 400, MinWidth = 450, MaxHeight = 99999, MaxWidth = 700, Padding = new Thickness(0), ButtonsMargin = new Thickness(8), SizeToContent = SizeToContent.Manual, ResizeMode = ResizeMode.CanResizeWithGrip, LocationAndSizeKey = @".OnlineServerDialog" }; dlg.SetBinding(Window.TitleProperty, new Binding { Path = new PropertyPath(nameof(server.DisplayName)), Source = server }); dlg.ShowDialog(); await wrapper.ReloadAsync(true); }
public async Task ReplaceSound(CarObject donor) { if (string.Equals(donor.Id, Id, StringComparison.OrdinalIgnoreCase)) { NonfatalError.Notify(ToolsStrings.Car_ReplaceSound_CannotReplace, "Source and destination are the same."); return; } try { using (var waiting = new WaitingDialog()) { waiting.Report(); var guids = donor.GuidsFilename; var soundbank = donor.SoundbankFilename; var newGuilds = GuidsFilename; var newSoundbank = SoundbankFilename; await Task.Run(() => { var destinations = new[] { newGuilds, newSoundbank }.Where(File.Exists).Select(x => new { Original = x, Backup = FileUtils.EnsureUnique($"{x}.bak") }).ToList(); foreach (var oldFile in destinations) { File.Move(oldFile.Original, oldFile.Backup); } try { if (File.Exists(guids) && File.Exists(soundbank)) { File.Copy(soundbank, newSoundbank); File.WriteAllText(newGuilds, File.ReadAllText(guids).Replace(donor.Id, Id)); } else if (File.Exists(soundbank) && donor.Author == AcCommonObject.AuthorKunos) { File.Copy(soundbank, newSoundbank); File.WriteAllText(newGuilds, File.ReadAllLines(FileUtils.GetSfxGuidsFilename(AcRootDirectory.Instance.RequireValue)) .Where(x => !x.Contains(@"} bank:/") || x.Contains(@"} bank:/common") || x.EndsWith(@"} bank:/" + donor.Id)) .Where(x => !x.Contains(@"} event:/") || x.Contains(@"} event:/cars/" + donor.Id + @"/")) .JoinToString(Environment.NewLine).Replace(donor.Id, Id)); } else { throw new InformativeException(ToolsStrings.Car_ReplaceSound_WrongCar, ToolsStrings.Car_ReplaceSound_WrongCar_Commentary); } } catch (Exception) { foreach (var oldFile in destinations) { if (File.Exists(oldFile.Original)) { File.Delete(oldFile.Original); } File.Move(oldFile.Backup, oldFile.Original); } throw; } FileUtils.Recycle(destinations.Select(x => x.Backup).ToArray()); }); } } catch (Exception e) { NonfatalError.Notify(ToolsStrings.Car_ReplaceSound_CannotReplace, ToolsStrings.Car_ReplaceSound_CannotReplace_Commentary, e); } }
private async Task <IReadOnlyList <UpdatePreviewError> > RunReady() { _checksum = _options.GetChecksum(); Logging.Debug(_checksum); _finished = false; _i = _j = 0; _waiting = new WaitingDialog { CancellationText = "Stop" }; var singleMode = _entries.Count == 1; _verySingleMode = singleMode && _entries[0].Skins?.Count == 1; var recycled = 0; if (!_verySingleMode) { _waiting.SetImage(null); if (SettingsHolder.CustomShowroom.PreviewsRecycleOld) { _waiting.SetMultiline(true); } } var step = 1d / _entries.Count; var postfix = string.Empty; _started = Stopwatch.StartNew(); _dispatcherTimer = new DispatcherTimer(TimeSpan.FromSeconds(0.5), DispatcherPriority.Background, TimerCallback, Application.Current?.Dispatcher ?? Dispatcher.CurrentDispatcher); _dispatcherTimer.Start(); for (_j = 0; _j < _entries.Count; _j++) { if (Cancel()) { return(_errors); } var entry = _entries[_j]; var progress = step * _j; _currentCar = entry.Car; _currentSkins = entry.Skins; if (_currentSkins == null) { _waiting.Report(new AsyncProgressEntry("Loading skins…" + postfix, _verySingleMode ? 0d : progress)); _waiting.SetDetails(GetDetails(_j, _currentCar, null, null)); await _currentCar.SkinsManager.EnsureLoadedAsync(); if (Cancel()) { return(_errors); } _currentSkins = _currentCar.EnabledOnlySkins.ToList(); UpdateApproximate(_currentSkins.Count); } var halfstep = step * 0.5 / _currentSkins.Count; for (_i = 0; _i < _currentSkins.Count; _i++) { if (Cancel()) { return(_errors); } _currentSkin = _currentSkins[_i]; _waiting.SetDetails(GetDetails(_j, _currentCar, _currentSkin, _currentSkins.Count - _i)); var subprogress = progress + step * (0.1 + 0.8 * _i / _currentSkins.Count); var filename = Path.Combine(_currentSkin.Location, _options.PreviewName); if (SettingsHolder.CustomShowroom.PreviewsRecycleOld && File.Exists(filename)) { if (++recycled > 5) { _recyclingWarning = true; } _waiting.Report(new AsyncProgressEntry($"Recycling current preview for {_currentSkin.DisplayName}…" + postfix, _verySingleMode ? 0d : subprogress)); await Task.Run(() => FileUtils.Recycle(filename)); } _waiting.Report(new AsyncProgressEntry($"Updating skin {_currentSkin.DisplayName}…" + postfix, _verySingleMode ? 0d : subprogress + halfstep)); try { await _updater.ShotAsync(_currentCar.Id, _currentSkin.Id, filename, _currentCar.AcdData, GetInformation(_currentCar, _currentSkin, _presetName, _checksum), PreviewReadyCallback); _shotSkins++; } catch (Exception e) { if (_errors.All(x => x.ToUpdate != entry)) { Logging.Warning(e); _errors.Add(new UpdatePreviewError(entry, e.Message, null)); } } } } _dispatcherTimer?.Stop(); _waiting.Report(new AsyncProgressEntry("Saving…" + postfix, _verySingleMode ? 0d : 0.999999d)); await _updater.WaitForProcessing(); _finished = true; if (_errors.Count > 0) { NonfatalError.Notify("Can’t update previews:\n" + _errors.Select(x => @"• " + x.Message.ToSentence()).JoinToString(";" + Environment.NewLine)); } return(_errors); }
public async Task <ArgumentHandleResult> ProgressRaceOnlineJoin(NameValueCollection p) { /* required arguments */ var ip = p.Get(@"ip"); var httpPort = FlexibleParser.TryParseInt(p.Get(@"httpPort")); var password = p.Get(@"plainPassword"); var encryptedPassword = p.Get(@"password"); if (string.IsNullOrWhiteSpace(ip)) { throw new InformativeException("IP is missing"); } if (!httpPort.HasValue) { throw new InformativeException("HTTP port is missing or is in invalid format"); } OnlineManager.EnsureInitialized(); if (string.IsNullOrWhiteSpace(password) && !string.IsNullOrWhiteSpace(encryptedPassword)) { password = OnlineServer.DecryptSharedPassword(ip, httpPort.Value, encryptedPassword); } var list = OnlineManager.Instance.List; var source = new FakeSource(ip, httpPort.Value); var wrapper = new OnlineSourceWrapper(list, source); ServerEntry server; using (var waiting = new WaitingDialog()) { waiting.Report(ControlsStrings.Common_Loading); await wrapper.EnsureLoadedAsync(); server = list.GetByIdOrDefault(source.Id); if (server == null) { throw new Exception(@"Unexpected"); } } if (password != null) { server.Password = password; } var content = new OnlineServer(server) { Margin = new Thickness(0, 0, 0, -43), ToolBar = { FitWidth = true }, // Values taken from ModernDialog.xaml // TODO: Extract them to some style? Title = { FontSize = 24, FontWeight = FontWeights.Light, Margin = new Thickness(6, 0, 0, 8) } }; content.Title.SetValue(TextOptions.TextFormattingModeProperty, TextFormattingMode.Ideal); var dlg = new ModernDialog { ShowTitle = false, Content = content, MinHeight = 400, MinWidth = 450, MaxHeight = 99999, MaxWidth = 700, Padding = new Thickness(0), ButtonsMargin = new Thickness(8), SizeToContent = SizeToContent.Manual, ResizeMode = ResizeMode.CanResizeWithGrip, LocationAndSizeKey = @".OnlineServerDialog" }; dlg.SetBinding(Window.TitleProperty, new Binding { Path = new PropertyPath(nameof(server.DisplayName)), Source = server }); dlg.ShowDialog(); await wrapper.ReloadAsync(true); return(ArgumentHandleResult.Successful); }
private static async Task <IReadOnlyList <UpdatePreviewError> > UpdatePreview(IReadOnlyList <ToUpdatePreview> entries, DarkPreviewsOptions options, string presetName = null, DarkPreviewsUpdater updater = null) { var localUpdater = updater == null; if (localUpdater) { updater = new DarkPreviewsUpdater(AcRootDirectory.Instance.RequireValue, options); } else { updater.SetOptions(options); } var errors = new List <UpdatePreviewError>(); try { if (options.Showroom != null && ShowroomsManager.Instance.GetById(options.Showroom) == null) { if (options.Showroom == "at_previews" && MissingShowroomHelper != null) { await MissingShowroomHelper.OfferToInstall("Kunos Previews Showroom (AT Previews Special)", "at_previews", "http://www.assettocorsa.net/assetto-corsa-v1-5-dev-diary-part-33/"); if (ShowroomsManager.Instance.GetById(options.Showroom) != null) { goto Action; } } throw new InformativeException("Can’t update preview", $"Showroom “{options.Showroom}” is missing"); } Action: var checksum = options.GetChecksum(); var finished = false; var j = 0; using (var waiting = new WaitingDialog()) { var cancellation = waiting.CancellationToken; var singleMode = entries.Count == 1; var verySingleMode = singleMode && entries[0].Skins?.Count == 1; var recycled = 0; if (!verySingleMode) { waiting.SetImage(null); if (SettingsHolder.CustomShowroom.PreviewsRecycleOld) { waiting.SetMultiline(true); } } var step = 1d / entries.Count; var postfix = string.Empty; var started = Stopwatch.StartNew(); var approximateSkinsPerCarCars = 1; var approximateSkinsPerCarSkins = 10; Action <int> updateApproximate = skinsPerCar => { approximateSkinsPerCarCars++; approximateSkinsPerCarSkins += skinsPerCar; }; Func <int, int> leftSkins = currentEntry => { var skinsPerCar = (double)approximateSkinsPerCarSkins / approximateSkinsPerCarCars; var result = 0d; for (var k = currentEntry; k < entries.Count; k++) { var entry = entries[k]; result += entry.Skins?.Count ?? skinsPerCar; } return(result.RoundToInt()); }; var shotSkins = 0; var recyclingWarning = false; Func <CarObject, CarSkinObject, int?, IEnumerable <string> > getDetails = (car, skin, currentEntrySkinsLeft) => { var left = leftSkins(j) + (currentEntrySkinsLeft ?? approximateSkinsPerCarSkins / approximateSkinsPerCarCars); // ReSharper disable once AccessToModifiedClosure var speed = shotSkins / started.Elapsed.TotalMinutes; var remainingTime = speed < 0.0001 ? "Unknown" : $"About {TimeSpan.FromMinutes(left / speed).ToReadableTime()}"; var remainingItems = $"About {left} {PluralizingConverter.Pluralize(left, ControlsStrings.CustomShowroom_SkinHeader).ToSentenceMember()}"; return(new[] { $"Car: {car?.DisplayName}", $"Skin: {skin?.DisplayName ?? "?"}", $"Speed: {speed:F2} {PluralizingConverter.Pluralize(10, ControlsStrings.CustomShowroom_SkinHeader).ToSentenceMember()}/{"min"}", $"Time remaining: {remainingTime}", $"Items remaining: {remainingItems}", // ReSharper disable once AccessToModifiedClosure recyclingWarning ? "[i]Recycling seems to take too long? If so, it can always be disabled in Settings.[/i]" : null }.NonNull()); }; for (j = 0; j < entries.Count; j++) { if (cancellation.IsCancellationRequested) { goto Cancel; } var entry = entries[j]; var progress = step * j; var car = entry.Car; var skins = entry.Skins; if (skins == null) { waiting.Report(new AsyncProgressEntry("Loading skins…" + postfix, verySingleMode ? 0d : progress)); waiting.SetDetails(getDetails(car, null, null)); await car.SkinsManager.EnsureLoadedAsync(); if (cancellation.IsCancellationRequested) { goto Cancel; } skins = car.EnabledOnlySkins.ToList(); updateApproximate(skins.Count); } var halfstep = step * 0.5 / skins.Count; for (var i = 0; i < skins.Count; i++) { if (cancellation.IsCancellationRequested) { goto Cancel; } var skin = skins[i]; waiting.SetDetails(getDetails(car, skin, skins.Count - i)); var subprogress = progress + step * (0.1 + 0.8 * i / skins.Count); if (SettingsHolder.CustomShowroom.PreviewsRecycleOld && File.Exists(skin.PreviewImage)) { if (++recycled > 5) { recyclingWarning = true; } waiting.Report(new AsyncProgressEntry($"Recycling current preview for {skin.DisplayName}…" + postfix, verySingleMode ? 0d : subprogress)); await Task.Run(() => FileUtils.Recycle(skin.PreviewImage)); } waiting.Report(new AsyncProgressEntry($"Updating skin {skin.DisplayName}…" + postfix, verySingleMode ? 0d : subprogress + halfstep)); try { await updater.ShotAsync(car.Id, skin.Id, skin.PreviewImage, car.AcdData, GetInformation(car, skin, presetName, checksum), () => { if (!verySingleMode) { ActionExtension.InvokeInMainThreadAsync(() => { // ReSharper disable once AccessToModifiedClosure if (!finished) { // ReSharper disable once AccessToDisposedClosure waiting.SetImage(skin.PreviewImage); } }); } }); shotSkins++; } catch (Exception e) { if (errors.All(x => x.ToUpdate != entry)) { errors.Add(new UpdatePreviewError(entry, e.Message, null)); } } } } waiting.Report(new AsyncProgressEntry("Saving…" + postfix, verySingleMode ? 0d : 0.999999d)); await updater.WaitForProcessing(); finished = true; } if (errors.Count > 0) { NonfatalError.Notify("Can’t update previews:\n" + errors.Select(x => @"• " + x.Message.ToSentence()).JoinToString(";" + Environment.NewLine)); } goto End; Cancel: for (; j < entries.Count; j++) { errors.Add(new UpdatePreviewError(entries[j], ControlsStrings.Common_Cancelled, null)); } End: return(errors); } catch (Exception e) { NonfatalError.Notify("Can’t update preview", e); return(null); } finally { if (localUpdater) { updater.Dispose(); GC.Collect(); } } }
public static async Task JoinInvitationNoUI([NotNull] string ip, int port, [CanBeNull] string password) { OnlineManager.EnsureInitialized(); var list = OnlineManager.Instance.List; var source = new FakeSource(ip, port); var wrapper = new OnlineSourceWrapper(list, source); var drive_opts = SettingsHolder.Drive; ServerEntry server; Logging.Write("Going through server list ..."); using (var waiting = new WaitingDialog()) { waiting.Report(ControlsStrings.Common_Loading); await wrapper.EnsureLoadedAsync(); server = list.GetByIdOrDefault(source.Id); if (server == null) { throw new Exception(@"Unexpected"); } } Logging.Write("Updating server infos ..."); await server.Update(ServerEntry.UpdateMode.Full, false, true); if (password != null) { server.Password = password; } //Change name here //We are going to use the server entry team name to match client local name. //Then we change the client online name to match the name required by the server. IReadOnlyList <ServerEntry.CurrentDriver> drivers = server.CurrentDrivers; Logging.Write("Going through all drivers ..."); if (drivers == null) { throw new Exception(@"Unexpected"); } foreach (var driver in drivers) { if (driver.Team == drive_opts.PlayerName) { drive_opts.PlayerNameOnline = driver.Name; break; } } Logging.Write("Joining server ...."); await server.JoinCommand.ExecuteAsync(null); Logging.Write("Checking booking time ..."); while (server.BookingTimeLeft > TimeSpan.Zero) { await Task.Delay(2000); } Logging.Write("Joining ..."); await server.JoinCommand.ExecuteAsync(ServerEntry.ActualJoin); await wrapper.ReloadAsync(true); }