diff --git a/CHANGELOG.md b/CHANGELOG.md index 247c9e6f..f6a08e81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,21 +1,32 @@ ### Changelog +#### Version - 3.3.0.0 - TBA +* Fixed some UI issues arising from 3.2.0.0 changes - more informative error text, wiki link button +* Added optional JSON flag for `DisplayVersionOnlyInInstallerView` to enable the installer image to only show version number. +* Fixed manual downloader downloading in the OS's "Downloads" folder +* Added RAM Limit setting for downloads + * This fixes the High RAM usage (and sometimes app crashes) on some Hardware + Very High Speed Internet Connection Systems +* Added Fallout 4 (GOG) to the index +* Updated App to .NET 7.0 + * Should fix random crashes on some systems +* Updated GameFinder to 4.0.0 + #### Version - 3.2.0.1 - 7/23/2023 * Code cleanup: re-added some network and diagnostic code missing since 2.5 #### Version - 3.2.0.0 - 7/16/2023 - * Fixed issues related to high RAM usage - * The resumable downloads now reserve drive space to write to in advance instead of being managed in system RAM - * remove LoversLab from the "Logins" Setting because it is deprecated for ages now and only causes confusion, - just for the unlikely probability that LL will fix their proper API. - * Added safety to install path selection, to ensure that no files are deleted that are not intended to be. - * Fixed allowing back button during install which can result in multiple install processes - * fixed search filter not applying when pressing back button and reaccessing gallery - * Added more robust checking for protected location paths and subfolders for the launcher exe and install and download paths - * Fixed readme double opening when modlist details are prepoulated - * Added a check if Downloadpath is alongside Wabbajack.exe location, to match the install path check that already exists - * Added check for identical download and install paths - * Fixed No Delete and NoDelete being handled by stripping whitespace before the regex, to idiotproof things a bit +* Fixed issues related to high RAM usage +* The resumable downloads now reserve drive space to write to in advance instead of being managed in system RAM +* remove LoversLab from the "Logins" Setting because it is deprecated for ages now and only causes confusion, + just for the unlikely probability that LL will fix their proper API. +* Added safety to install path selection, to ensure that no files are deleted that are not intended to be. +* Fixed allowing back button during install which can result in multiple install processes +* fixed search filter not applying when pressing back button and reaccessing gallery +* Added more robust checking for protected location paths and subfolders for the launcher exe and install and download paths +* Fixed readme double opening when modlist details are prepoulated +* Added a check if Downloadpath is alongside Wabbajack.exe location, to match the install path check that already exists +* Added check for identical download and install paths +* Fixed No Delete and NoDelete being handled by stripping whitespace before the regex, to idiotproof things a bit #### Version - 3.1.0.0 - 5/7/2023 * Fixed Readme opening twice diff --git a/Wabbajack.App.Wpf/App.xaml.cs b/Wabbajack.App.Wpf/App.xaml.cs index 4fd29c41..dc9d2cd0 100644 --- a/Wabbajack.App.Wpf/App.xaml.cs +++ b/Wabbajack.App.Wpf/App.xaml.cs @@ -3,7 +3,6 @@ using System.Reactive.Concurrency; using System.Reactive.Disposables; using System.Runtime.InteropServices; using System.Security.Principal; -using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; using Microsoft.Extensions.DependencyInjection; @@ -166,7 +165,6 @@ namespace Wabbajack services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -182,7 +180,7 @@ namespace Wabbajack services.AddTransient(); // Login Managers - + //Disabled LL because it is currently not used and broken due to the way LL butchers their API //services.AddAllSingleton(); services.AddAllSingleton(); diff --git a/Wabbajack.App.Wpf/LauncherUpdater.cs b/Wabbajack.App.Wpf/LauncherUpdater.cs index 94e7031e..96d3fd6b 100644 --- a/Wabbajack.App.Wpf/LauncherUpdater.cs +++ b/Wabbajack.App.Wpf/LauncherUpdater.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.VisualBasic.CompilerServices; using Newtonsoft.Json; +using Wabbajack.Common; using Wabbajack.Downloaders; using Wabbajack.DTOs; using Wabbajack.DTOs.DownloadStates; @@ -27,9 +28,9 @@ namespace Wabbajack private readonly HttpClient _client; private readonly Client _wjclient; private readonly DTOSerializer _dtos; - + private readonly DownloadDispatcher _downloader; - + private static Uri GITHUB_REPO_RELEASES = new("https://api.github.com/repos/wabbajack-tools/wabbajack/releases"); public LauncherUpdater(ILogger logger, HttpClient client, Client wjclient, DTOSerializer dtos, @@ -41,8 +42,8 @@ namespace Wabbajack _dtos = dtos; _downloader = downloader; } - - + + public static Lazy CommonFolder = new (() => { var entryPoint = KnownFolders.EntryPoint; @@ -105,7 +106,7 @@ namespace Wabbajack var launcherFolder = KnownFolders.EntryPoint.Parent; var exePath = launcherFolder.Combine("Wabbajack.exe"); - + var launcherVersion = FileVersionInfo.GetVersionInfo(exePath.ToString()); if (release != default && release.version > Version.Parse(launcherVersion.FileVersion!)) @@ -119,7 +120,7 @@ namespace Wabbajack Name = release.asset.Name, Size = release.asset.Size }, tempPath, CancellationToken.None); - + if (tempPath.Size() != release.asset.Size) { _logger.LogInformation( @@ -130,12 +131,12 @@ namespace Wabbajack if (exePath.FileExists()) exePath.Delete(); await tempPath.MoveToAsync(exePath, true, CancellationToken.None); - + _logger.LogInformation("Finished updating wabbajack"); await _wjclient.SendMetric("updated_launcher", $"{launcherVersion.FileVersion} -> {release.version}"); } } - + private async Task GetReleases() { _logger.LogInformation("Getting new Wabbajack version list"); @@ -146,7 +147,7 @@ namespace Wabbajack private HttpRequestMessage MakeMessage(Uri uri) { var msg = new HttpRequestMessage(HttpMethod.Get, uri); - msg.UseChromeUserAgent(); + msg.AddChromeAgent(); return msg; } diff --git a/Wabbajack.App.Wpf/Settings.cs b/Wabbajack.App.Wpf/Settings.cs index 4a65f6d7..4ad1517c 100644 --- a/Wabbajack.App.Wpf/Settings.cs +++ b/Wabbajack.App.Wpf/Settings.cs @@ -1,84 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Reactive; -using System.Reactive.Subjects; -using System.Threading.Tasks; -using Newtonsoft.Json; -using Wabbajack.Compiler; +using Wabbajack.Downloaders; using Wabbajack.DTOs.JsonConverters; -using Wabbajack; using Wabbajack.Paths; -using Consts = Wabbajack.Consts; +using Wabbajack.RateLimiter; +using Wabbajack.Util; namespace Wabbajack { - [JsonName("MainSettings")] - [JsonObject(MemberSerialization.OptOut)] - public class MainSettings - { - public byte Version { get; set; } = Consts.SettingsVersion; - public double PosX { get; set; } - public double PosY { get; set; } - public double Height { get; set; } - public double Width { get; set; } - public InstallerSettings Installer { get; set; } = new(); - public FiltersSettings Filters { get; set; } = new(); - public CompilerSettings Compiler { get; set; } = new(); - public PerformanceSettings Performance { get; set; } = new(); - - private Subject _saveSignal = new(); - [JsonIgnore] - public IObservable SaveSignal => _saveSignal; - - public static async ValueTask<(MainSettings settings, bool loaded)> TryLoadTypicalSettings() - { - /* - if (!Consts.SettingsFile.Exists) - { - return default; - } - - // Version check - try - { - var settings = Consts.SettingsFile.FromJson(); - if (settings.Version == Consts.SettingsVersion) - return (settings, true); - } - catch (Exception ex) - { - Utils.Error(ex, "Error loading settings"); - } - - var backup = Consts.SettingsFile.AppendToName("-backup"); - await backup.DeleteAsync(); - - await Consts.SettingsFile.CopyToAsync(backup); - await Consts.SettingsFile.DeleteAsync(); -*/ - return default; - } - - public static async ValueTask SaveSettings(MainSettings settings) - { - settings._saveSignal.OnNext(Unit.Default); - - // Might add this if people are putting save work on other threads or other - // things that delay the operation. - //settings._saveSignal.OnCompleted(); - //await settings._saveSignal; - - //await settings.ToJsonAsync(Consts.SettingsFile); - } - } - - [JsonName("InstallerSettings")] - public class InstallerSettings - { - public AbsolutePath LastInstalledListLocation { get; set; } - public Dictionary Mo2ModlistSettings { get; } = new Dictionary(); - } - [JsonName("Mo2ModListInstallerSettings")] public class Mo2ModlistInstallationSettings { @@ -87,105 +14,41 @@ namespace Wabbajack public bool AutomaticallyOverrideExistingInstall { get; set; } } - [JsonName("FiltersSettings")] - [JsonObject(MemberSerialization.OptOut)] - public class FiltersSettings : ViewModel - { - public bool ShowNSFW { get; set; } - public bool OnlyInstalled { get; set; } - public string Game { get; set; } - public string Search { get; set; } - private bool _isPersistent = true; - public bool IsPersistent { get => _isPersistent; set => RaiseAndSetIfChanged(ref _isPersistent, value); } - - private bool _useCompression = false; - public bool UseCompression { get => _useCompression; set => RaiseAndSetIfChanged(ref _useCompression, value); } - public bool ShowUtilityLists { get; set; } - } - - [JsonName("PerformanceSettings")] - [JsonObject(MemberSerialization.OptOut)] public class PerformanceSettings : ViewModel { - public PerformanceSettings() + private readonly Configuration.MainSettings _settings; + private readonly int _defaultMaximumMemoryPerDownloadThreadMb; + + public PerformanceSettings(Configuration.MainSettings settings, IResource downloadResources, SystemParametersConstructor systemParams) { - _reduceHDDThreads = true; - _favorPerfOverRam = false; - _diskThreads = Environment.ProcessorCount; - _downloadThreads = Environment.ProcessorCount <= 8 ? Environment.ProcessorCount : 8; - } + var p = systemParams.Create(); - private int _downloadThreads; - public int DownloadThreads { get => _downloadThreads; set => RaiseAndSetIfChanged(ref _downloadThreads, value); } - - private int _diskThreads; - public int DiskThreads { get => _diskThreads; set => RaiseAndSetIfChanged(ref _diskThreads, value); } + _settings = settings; + // Split half of available memory among download threads + _defaultMaximumMemoryPerDownloadThreadMb = (int)(p.SystemMemorySize / downloadResources.MaxTasks / 1024 / 1024) / 2; + _maximumMemoryPerDownloadThreadMb = settings.PerformanceSettings.MaximumMemoryPerDownloadThreadMb; - private bool _reduceHDDThreads; - public bool ReduceHDDThreads { get => _reduceHDDThreads; set => RaiseAndSetIfChanged(ref _reduceHDDThreads, value); } - - private bool _favorPerfOverRam; - public bool FavorPerfOverRam { get => _favorPerfOverRam; set => RaiseAndSetIfChanged(ref _favorPerfOverRam, value); } - - private bool _networkWorkaroundMode; - public bool NetworkWorkaroundMode - { - get => _networkWorkaroundMode; - set + if (MaximumMemoryPerDownloadThreadMb < 0) { - Consts.UseNetworkWorkaroundMode = value; - RaiseAndSetIfChanged(ref _networkWorkaroundMode, value); + ResetMaximumMemoryPerDownloadThreadMb(); } } - - private bool _disableTextureResizing; - public bool DisableTextureResizing + private int _maximumMemoryPerDownloadThreadMb; + + public int MaximumMemoryPerDownloadThreadMb { - get => _disableTextureResizing; + get => _maximumMemoryPerDownloadThreadMb; set { - RaiseAndSetIfChanged(ref _disableTextureResizing, value); + RaiseAndSetIfChanged(ref _maximumMemoryPerDownloadThreadMb, value); + _settings.PerformanceSettings.MaximumMemoryPerDownloadThreadMb = value; } } - - - /* - public void SetProcessorSettings(ABatchProcessor processor) + public void ResetMaximumMemoryPerDownloadThreadMb() { - processor.DownloadThreads = DownloadThreads; - processor.DiskThreads = DiskThreads; - processor.ReduceHDDThreads = ReduceHDDThreads; - processor.FavorPerfOverRam = FavorPerfOverRam; - - if (processor is MO2Compiler mo2c) - mo2c.DisableTextureResizing = DisableTextureResizing; - }*/ + MaximumMemoryPerDownloadThreadMb = _defaultMaximumMemoryPerDownloadThreadMb; + } } - - [JsonName("CompilationModlistSettings")] - public class CompilationModlistSettings - { - public string ModListName { get; set; } - public string Version { get; set; } - public string Author { get; set; } - public string Description { get; set; } - public string Website { get; set; } - public string Readme { get; set; } - public bool IsNSFW { get; set; } - - public string MachineUrl { get; set; } - public AbsolutePath SplashScreen { get; set; } - public bool Publish { get; set; } - } - - [JsonName("MO2CompilationSettings")] - public class MO2CompilationSettings - { - public AbsolutePath DownloadLocation { get; set; } - public AbsolutePath LastCompiledProfileLocation { get; set; } - public Dictionary ModlistSettings { get; } = new Dictionary(); - } - } diff --git a/Wabbajack.App.Wpf/UserIntervention/ManualDownloadHandler.cs b/Wabbajack.App.Wpf/UserIntervention/ManualDownloadHandler.cs index 6bf219c1..003099bf 100644 --- a/Wabbajack.App.Wpf/UserIntervention/ManualDownloadHandler.cs +++ b/Wabbajack.App.Wpf/UserIntervention/ManualDownloadHandler.cs @@ -1,10 +1,7 @@ -using System.Security.Policy; using System.Threading; using System.Threading.Tasks; -using Wabbajack.DTOs; using Wabbajack.DTOs.DownloadStates; using Wabbajack.DTOs.Interventions; -using Wabbajack.Paths; namespace Wabbajack.UserIntervention; @@ -17,18 +14,18 @@ public class ManualDownloadHandler : BrowserWindowViewModel //await WaitForReady(); var archive = Intervention.Archive; var md = Intervention.Archive.State as Manual; - + HeaderText = $"Manual download ({md.Url.Host})"; - + Instructions = string.IsNullOrWhiteSpace(md.Prompt) ? $"Please download {archive.Name}" : md.Prompt; - await NavigateTo(md.Url); - - var uri = await WaitForDownloadUri(token, async () => + var task = WaitForDownloadUri(token, async () => { await RunJavaScript("Array.from(document.getElementsByTagName(\"iframe\")).forEach(f => f.remove())"); }); - + await NavigateTo(md.Url); + var uri = await task; + Intervention.Finish(uri); } } \ No newline at end of file diff --git a/Wabbajack.App.Wpf/UserIntervention/OAuth2LoginHandler.cs b/Wabbajack.App.Wpf/UserIntervention/OAuth2LoginHandler.cs index 1d287022..51f45c7b 100644 --- a/Wabbajack.App.Wpf/UserIntervention/OAuth2LoginHandler.cs +++ b/Wabbajack.App.Wpf/UserIntervention/OAuth2LoginHandler.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using System.Web; using Microsoft.Extensions.Logging; using ReactiveUI; +using Wabbajack.Common; using Wabbajack.DTOs.Interventions; using Wabbajack.DTOs.Logins; using Wabbajack.Messages; @@ -40,7 +41,7 @@ public abstract class OAuth2LoginHandler : BrowserWindowViewModel var tcs = new TaskCompletionSource(); await NavigateTo(tlogin.AuthorizationEndpoint); - + Browser!.Browser.CoreWebView2.Settings.UserAgent = "Wabbajack"; Browser!.Browser.NavigationStarting += (sender, args) => { @@ -50,7 +51,7 @@ public abstract class OAuth2LoginHandler : BrowserWindowViewModel tcs.TrySetResult(uri); } }; - + Instructions = $"Please log in and allow Wabbajack to access your {tlogin.SiteName} account"; var scopes = string.Join(" ", tlogin.Scopes); @@ -88,8 +89,7 @@ public abstract class OAuth2LoginHandler : BrowserWindowViewModel var msg = new HttpRequestMessage(); msg.Method = HttpMethod.Post; msg.RequestUri = tlogin.TokenEndpoint; - msg.Headers.Add("User-Agent", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36"); + msg.AddChromeAgent(); msg.Headers.Add("Cookie", string.Join(";", cookies.Select(c => $"{c.Name}={c.Value}"))); msg.Content = new FormUrlEncodedContent(formData.ToList()); @@ -101,6 +101,6 @@ public abstract class OAuth2LoginHandler : BrowserWindowViewModel Cookies = cookies, ResultState = data! }); - + } } \ No newline at end of file diff --git a/Wabbajack.App.Wpf/View Models/BrowserWindowViewModel.cs b/Wabbajack.App.Wpf/View Models/BrowserWindowViewModel.cs index b74cdd99..d0aa4a4c 100644 --- a/Wabbajack.App.Wpf/View Models/BrowserWindowViewModel.cs +++ b/Wabbajack.App.Wpf/View Models/BrowserWindowViewModel.cs @@ -23,7 +23,7 @@ public abstract class BrowserWindowViewModel : ViewModel [Reactive] public string HeaderText { get; set; } [Reactive] public string Instructions { get; set; } - + [Reactive] public string Address { get; set; } public BrowserWindow? Browser { get; set; } @@ -83,6 +83,11 @@ public abstract class BrowserWindowViewModel : ViewModel public async Task GetCookies(string domainEnding, CancellationToken token) { + // Strip www. before searching for cookies on a domain to handle websites saving their cookies like .example.org + if (domainEnding.StartsWith("www.")) + { + domainEnding = domainEnding[4..]; + } var cookies = (await _browser.CoreWebView2.CookieManager.GetCookiesAsync("")) .Where(c => c.Domain.EndsWith(domainEnding)); return cookies.Select(c => new Cookie @@ -112,18 +117,20 @@ public abstract class BrowserWindowViewModel : ViewModel { var source = new TaskCompletionSource(); var referer = _browser.Source; + while (_browser.CoreWebView2 == null) + await Task.Delay(10, token); + _browser.CoreWebView2.DownloadStarting += (sender, args) => { try { - source.SetResult(new Uri(args.DownloadOperation.Uri)); } catch (Exception) { source.SetCanceled(); } - + args.Cancel = true; args.Handled = true; }; @@ -144,12 +151,16 @@ public abstract class BrowserWindowViewModel : ViewModel } var cookies = await GetCookies(uri.Host, token); - return new ManualDownload.BrowserDownloadState(uri, cookies, new[] - { - ("Referer", referer.ToString()) - }); + return new ManualDownload.BrowserDownloadState( + uri, + cookies, + new[] + { + ("Referer", referer?.ToString() ?? uri.ToString()) + }, + _browser.CoreWebView2.Settings.UserAgent); } - + public async Task WaitForDownload(AbsolutePath path, CancellationToken token) { var source = new TaskCompletionSource(); diff --git a/Wabbajack.App.Wpf/View Models/Compilers/ModlistSettingsEditorVM.cs b/Wabbajack.App.Wpf/View Models/Compilers/ModlistSettingsEditorVM.cs deleted file mode 100644 index 1552b98e..00000000 --- a/Wabbajack.App.Wpf/View Models/Compilers/ModlistSettingsEditorVM.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System; -using System.Reactive.Linq; -using System.Windows.Input; -using DynamicData; -using Microsoft.WindowsAPICodePack.Dialogs; -using ReactiveUI; -using ReactiveUI.Fody.Helpers; -using Wabbajack.Common; -using Wabbajack; - -namespace Wabbajack -{ - public class ModlistSettingsEditorVM : ViewModel - { - private readonly CompilationModlistSettings _settings; - - [Reactive] - public string ModListName { get; set; } - - [Reactive] - public string VersionText { get; set; } - - private readonly ObservableAsPropertyHelper _version; - public Version Version => _version.Value; - - [Reactive] - public string AuthorText { get; set; } - - [Reactive] - public string Description { get; set; } - - public FilePickerVM ImagePath { get; } - - [Reactive] - public string Readme { get; set; } - - [Reactive] public string MachineUrl { get; set; } = ""; - [Reactive] public bool Publish { get; set; } = false; - - [Reactive] - public string Website { get; set; } - - [Reactive] - public bool IsNSFW { get; set; } - - public IObservable InError { get; } - - public ModlistSettingsEditorVM(CompilationModlistSettings settings) - { - _settings = settings; - ImagePath = new FilePickerVM - { - ExistCheckOption = FilePickerVM.CheckOptions.IfPathNotEmpty, - PathType = FilePickerVM.PathTypeOptions.File, - }; - ImagePath.Filters.Add(new CommonFileDialogFilter("Banner image", "*.png")); - - _version = this.WhenAny(x => x.VersionText) - .Select(x => - { - if (string.IsNullOrWhiteSpace(x)) - return new Version(0, 0); - - return !Version.TryParse(x, out var version) ? new Version(0, 0) : version; - }).ObserveOnGuiThread() - .ToProperty(this, x => x.Version); - - InError = this.WhenAny(x => x.ImagePath.ErrorState) - .Select(err => err.Failed) - .CombineLatest( - this.WhenAny(x => x.VersionText) - .Select(x => Version.TryParse(x, out _)), - (image, version) => !image && !version) - .Publish() - .RefCount(); - } - - public void Init() - { - AuthorText = _settings.Author; - if (!string.IsNullOrWhiteSpace(_settings.ModListName)) - { - ModListName = _settings.ModListName; - } - Description = _settings.Description; - Readme = _settings.Readme; - ImagePath.TargetPath = _settings.SplashScreen; - Website = _settings.Website; - VersionText = _settings.Version; - IsNSFW = _settings.IsNSFW; - MachineUrl = _settings.MachineUrl; - Publish = _settings.Publish; - } - - public void Save() - { - _settings.Version = VersionText; - _settings.Author = AuthorText; - _settings.ModListName = ModListName; - _settings.Description = Description; - _settings.Readme = Readme; - _settings.SplashScreen = ImagePath.TargetPath; - _settings.Website = Website; - _settings.IsNSFW = IsNSFW; - _settings.MachineUrl = MachineUrl; - _settings.Publish = Publish; - } - } -} diff --git a/Wabbajack.App.Wpf/View Models/Gallery/ModListGalleryVM.cs b/Wabbajack.App.Wpf/View Models/Gallery/ModListGalleryVM.cs index e91b3ce7..c87dfde5 100644 --- a/Wabbajack.App.Wpf/View Models/Gallery/ModListGalleryVM.cs +++ b/Wabbajack.App.Wpf/View Models/Gallery/ModListGalleryVM.cs @@ -80,7 +80,6 @@ namespace Wabbajack private readonly SettingsManager _settingsManager; private readonly CancellationToken _cancellationToken; - private FiltersSettings settings { get; set; } = new(); public ICommand ClearFiltersCommand { get; set; } public ModListGalleryVM(ILogger logger, Client wjClient, GameLocator locator, diff --git a/Wabbajack.App.Wpf/View Models/Gallery/ModListMetadataVM.cs b/Wabbajack.App.Wpf/View Models/Gallery/ModListMetadataVM.cs index 3bd14e44..93cce20c 100644 --- a/Wabbajack.App.Wpf/View Models/Gallery/ModListMetadataVM.cs +++ b/Wabbajack.App.Wpf/View Models/Gallery/ModListMetadataVM.cs @@ -82,6 +82,13 @@ namespace Wabbajack [Reactive] public string VersionText { get; private set; } + [Reactive] + public bool ImageContainsTitle { get; private set; } + + [Reactive] + + public bool DisplayVersionOnlyInInstallerView { get; private set; } + [Reactive] public IErrorResponse Error { get; private set; } @@ -123,6 +130,8 @@ namespace Wabbajack Metadata.DownloadMetadata.SizeOfArchives + Metadata.DownloadMetadata.SizeOfInstalledFiles ); VersionText = "Modlist version : " + Metadata.Version; + ImageContainsTitle = Metadata.ImageContainsTitle; + DisplayVersionOnlyInInstallerView = Metadata.DisplayVersionOnlyInInstallerView; IsBroken = metadata.ValidationSummary.HasFailures || metadata.ForceDown; // https://www.wabbajack.org/modlist/wj-featured/aldrnari OpenWebsiteCommand = ReactiveCommand.Create(() => UIUtils.OpenWebsite(new Uri($"https://www.wabbajack.org/modlist/{Metadata.NamespacedName}"))); diff --git a/Wabbajack.App.Wpf/View Models/Installers/InstallerVM.cs b/Wabbajack.App.Wpf/View Models/Installers/InstallerVM.cs index c5198d13..e5c16540 100644 --- a/Wabbajack.App.Wpf/View Models/Installers/InstallerVM.cs +++ b/Wabbajack.App.Wpf/View Models/Installers/InstallerVM.cs @@ -135,11 +135,14 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM, ICpuStatusVM public LogStream LoggerProvider { get; } private AbsolutePath LastInstallPath { get; set; } + + [Reactive] public bool OverwriteFiles { get; set; } // Command properties public ReactiveCommand ShowManifestCommand { get; } public ReactiveCommand OpenReadmeCommand { get; } + public ReactiveCommand OpenWikiCommand { get; } public ReactiveCommand OpenDiscordButton { get; } public ReactiveCommand VisitModListWebsiteCommand { get; } @@ -178,6 +181,11 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM, ICpuStatusVM UIUtils.OpenWebsite(new Uri(ModList!.Readme)); }, this.WhenAnyValue(vm => vm.LoadingLock.IsNotLoading, vm => vm.ModList.Readme, (isNotLoading, readme) => isNotLoading && !string.IsNullOrWhiteSpace(readme))); + OpenWikiCommand = ReactiveCommand.Create(() => + { + UIUtils.OpenWebsite(new Uri("https://wiki.wabbajack.org/index.html")); + }, this.WhenAnyValue(vm => vm.LoadingLock.IsNotLoading)); + VisitModListWebsiteCommand = ReactiveCommand.Create(() => { UIUtils.OpenWebsite(ModList!.Website); @@ -219,7 +227,10 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM, ICpuStatusVM { UIUtils.OpenFolder(Installer.Location.TargetPath); }); - + + this.WhenAnyValue(x => x.OverwriteFiles) + .Subscribe(x => ConfirmOverwrite()); + MessageBus.Current.Listen() .Subscribe(msg => LoadModlistFromGallery(msg.Path, msg.Metadata).FireAndForget()) .DisposeWith(CompositeDisposable); @@ -280,6 +291,10 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM, ICpuStatusVM { yield return ErrorResponse.Fail("Can't have identical install and download folders"); } + if (installPath.ToString().Length > 0 && downloadPath.ToString().Length > 0 && KnownFolders.IsSubDirectoryOf(installPath.ToString(), downloadPath.ToString())) + { + yield return ErrorResponse.Fail("Can't put the install folder inside the download folder"); + } foreach (var game in GameRegistry.Games) { if (!_gameLocator.TryFindLocation(game.Key, out var location)) @@ -304,31 +319,53 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM, ICpuStatusVM yield return ErrorResponse.Fail("Installing in this folder may overwrite Wabbajack"); } - if (installPath.ToString().Length != 0 && installPath != LastInstallPath && - !Installer.AutomaticallyOverwrite && + if (installPath.ToString().Length != 0 && installPath != LastInstallPath && !OverwriteFiles && Directory.EnumerateFileSystemEntries(installPath.ToString()).Any()) { - string message = - "There are existing files in the chosen install path, they will be deleted or overwritten (if updating existing modlist), continue?"; - string title = "Files found in install folder"; - MessageBoxButtons buttons = MessageBoxButtons.YesNo; - DialogResult result = MessageBox.Show(message, title, buttons); - if (result == DialogResult.Yes) - { - // everythings fine - } - else - { - Installer.Location.TargetPath = "".ToAbsolutePath(); - } + yield return ErrorResponse.Fail("There are files in the install folder, please tick 'Overwrite Installation' to confirm you want to install to this folder " + Environment.NewLine + + "if you are updating an existing modlist, then this is expected and can be overwritten."); } if (KnownFolders.IsInSpecialFolder(installPath) || KnownFolders.IsInSpecialFolder(downloadPath)) { - yield return ErrorResponse.Fail("Can't install a modlist into Windows protected locations - such as Downloads, Documents etc"); + yield return ErrorResponse.Fail("Can't install into Windows locations such as Documents etc, please make a new folder for the modlist - C:\\ModList\\ for example."); } + // Disabled Because it was causing issues for people trying to update lists. + //if (installPath.ToString().Length > 0 && downloadPath.ToString().Length > 0 && !HasEnoughSpace(installPath, downloadPath)){ + // yield return ErrorResponse.Fail("Can't install modlist due to lack of free hard drive space, please read the modlist Readme to learn more."); + //} } + /* + private bool HasEnoughSpace(AbsolutePath inpath, AbsolutePath downpath) + { + string driveLetterInPath = inpath.ToString().Substring(0,1); + string driveLetterDownPath = inpath.ToString().Substring(0,1); + DriveInfo driveUsedInPath = new DriveInfo(driveLetterInPath); + DriveInfo driveUsedDownPath = new DriveInfo(driveLetterDownPath); + long spaceRequiredforInstall = ModlistMetadata.DownloadMetadata.SizeOfInstalledFiles; + long spaceRequiredforDownload = ModlistMetadata.DownloadMetadata.SizeOfArchives; + long spaceInstRemaining = driveUsedInPath.AvailableFreeSpace; + long spaceDownRemaining = driveUsedDownPath.AvailableFreeSpace; + if ( driveLetterInPath == driveLetterDownPath) + { + long totalSpaceRequired = spaceRequiredforInstall + spaceRequiredforDownload; + if (spaceInstRemaining < totalSpaceRequired) + { + return false; + } + + } else + { + if( spaceInstRemaining < spaceRequiredforInstall || spaceDownRemaining < spaceRequiredforDownload) + { + return false; + } + } + return true; + + }*/ + private async Task BeginSlideShow(CancellationToken token) { while (!token.IsCancellationRequested) @@ -411,6 +448,13 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM, ICpuStatusVM } } + private void ConfirmOverwrite() + { + AbsolutePath prev = Installer.Location.TargetPath; + Installer.Location.TargetPath = "".ToAbsolutePath(); + Installer.Location.TargetPath = prev; + } + private async Task BeginInstall() { await Task.Run(async () => @@ -521,7 +565,14 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM, ICpuStatusVM private void PopulateSlideShow(ModList modList) { - SlideShowTitle = modList.Name; + if (ModlistMetadata.ImageContainsTitle && ModlistMetadata.DisplayVersionOnlyInInstallerView) + { + SlideShowTitle = "v" + ModlistMetadata.Version.ToString(); + } + else + { + SlideShowTitle = modList.Name; + } SlideShowAuthor = modList.Author; SlideShowDescription = modList.Description; SlideShowImage = ModListImage; @@ -551,4 +602,4 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM, ICpuStatusVM } } -} \ No newline at end of file +} diff --git a/Wabbajack.App.Wpf/View Models/Installers/MO2InstallerVM.cs b/Wabbajack.App.Wpf/View Models/Installers/MO2InstallerVM.cs index 8e87a272..f9bc25a4 100644 --- a/Wabbajack.App.Wpf/View Models/Installers/MO2InstallerVM.cs +++ b/Wabbajack.App.Wpf/View Models/Installers/MO2InstallerVM.cs @@ -1,37 +1,27 @@ using System; -using System.Collections.Generic; using System.Diagnostics; -using System.IO; -using System.Linq; using System.Reactive.Disposables; -using System.Reactive.Linq; -using System.Text; using System.Threading.Tasks; using ReactiveUI; using ReactiveUI.Fody.Helpers; -using Wabbajack.Common; using Wabbajack.Installer; -using Wabbajack; -using Wabbajack.DTOs; using Wabbajack.DTOs.Interventions; -using Wabbajack.Interventions; using Wabbajack.Paths; -using Wabbajack.Util; namespace Wabbajack { public class MO2InstallerVM : ViewModel, ISubInstallerVM { public InstallerVM Parent { get; } - + [Reactive] public ErrorResponse CanInstall { get; set; } [Reactive] public IInstaller ActiveInstallation { get; private set; } - - [Reactive] public Mo2ModlistInstallationSettings CurrentSettings { get; set; } + [Reactive] + public Mo2ModlistInstallationSettings CurrentSettings { get; set; } public FilePickerVM Location { get; } @@ -62,97 +52,13 @@ namespace Wabbajack DownloadLocation.TargetPath = newPath.Combine("downloads"); } }).DisposeWith(CompositeDisposable); - + DownloadLocation = new FilePickerVM() { ExistCheckOption = FilePickerVM.CheckOptions.Off, PathType = FilePickerVM.PathTypeOptions.Folder, PromptTitle = "Select a location for MO2 downloads", }; - /* TODO - DownloadLocation.AdditionalError = this.WhenAny(x => x.DownloadLocation.TargetPath) - .Select(x => Utils.IsDirectoryPathValid(x)); - Location.AdditionalError = Observable.CombineLatest( - this.WhenAny(x => x.Location.TargetPath), - this.WhenAny(x => x.DownloadLocation.TargetPath), - resultSelector: (target, download) => (target, download)) - .ObserveOn(RxApp.TaskpoolScheduler) - .Select(i => MO2Installer.CheckValidInstallPath(i.target, i.download, Parent.ModList?.SourceModList?.GameType.MetaData())) - .ObserveOnGuiThread(); - - _CanInstall = Observable.CombineLatest( - this.WhenAny(x => x.Location.ErrorState), - this.WhenAny(x => x.DownloadLocation.ErrorState), - installerVM.WhenAny(x => x.ModListLocation.ErrorState), - resultSelector: (loc, modlist, download) => - { - return ErrorResponse.FirstFail(loc, modlist, download); - }) - .ToProperty(this, nameof(CanInstall)); - - // Have Installation location updates modify the downloads location if empty or the same path - this.WhenAny(x => x.Location.TargetPath) - .Skip(1) // Don't do it initially - .Subscribe(installPath => - { - if (DownloadLocation.TargetPath == default || DownloadLocation.TargetPath == installPath) - { - if (installPath.Exists) DownloadLocation.TargetPath = installPath.Combine("downloads"); - } - }) - .DisposeWith(CompositeDisposable); - - // Have Download location updates change if the same as the install path - this.WhenAny(x => x.DownloadLocation.TargetPath) - .Skip(1) // Don't do it initially - .Subscribe(downloadPath => - { - if (downloadPath != default && downloadPath == Location.TargetPath) - { - DownloadLocation.TargetPath = Location.TargetPath.Combine("downloads"); - } - }) - .DisposeWith(CompositeDisposable); - - // Load settings - _CurrentSettings = installerVM.WhenAny(x => x.ModListLocation.TargetPath) - .Select(path => path == default ? null : installerVM.MWVM.Settings.Installer.Mo2ModlistSettings.TryCreate(path)) - .ToGuiProperty(this, nameof(CurrentSettings)); - this.WhenAny(x => x.CurrentSettings) - .Pairwise() - .Subscribe(settingsPair => - { - SaveSettings(settingsPair.Previous); - if (settingsPair.Current == null) return; - Location.TargetPath = settingsPair.Current.InstallationLocation; - DownloadLocation.TargetPath = settingsPair.Current.DownloadLocation; - AutomaticallyOverwrite = settingsPair.Current.AutomaticallyOverrideExistingInstall; - }) - .DisposeWith(CompositeDisposable); - installerVM.MWVM.Settings.SaveSignal - .Subscribe(_ => SaveSettings(CurrentSettings)) - .DisposeWith(CompositeDisposable); - - // Hook onto user interventions, and intercept MO2 specific ones for customization - this.WhenAny(x => x.ActiveInstallation) - .Select(x => x?.LogMessages ?? Observable.Empty()) - .Switch() - .Subscribe(x => - { - switch (x) - { - case ConfirmUpdateOfExistingInstall c: - if (AutomaticallyOverwrite) - { - c.Confirm(); - } - break; - default: - break; - } - }) - .DisposeWith(CompositeDisposable); - */ } public void Unload() @@ -205,7 +111,7 @@ namespace Wabbajack */ return true; } - + public IUserIntervention InterventionConverter(IUserIntervention intervention) { switch (intervention) diff --git a/Wabbajack.App.Wpf/View Models/MainWindowVM.cs b/Wabbajack.App.Wpf/View Models/MainWindowVM.cs index 804a14d6..cd1430ed 100644 --- a/Wabbajack.App.Wpf/View Models/MainWindowVM.cs +++ b/Wabbajack.App.Wpf/View Models/MainWindowVM.cs @@ -16,11 +16,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Orc.FileAssociation; using Wabbajack.Common; -using Wabbajack.Downloaders.GameFile; -using Wabbajack; using Wabbajack.DTOs.Interventions; using Wabbajack.Interventions; -using Wabbajack.LoginManagers; using Wabbajack.Messages; using Wabbajack.Models; using Wabbajack.Networking.WabbajackClientApi; @@ -39,8 +36,6 @@ namespace Wabbajack { public MainWindow MainWindow { get; } - public MainSettings Settings { get; } - [Reactive] public ViewModel ActivePane { get; private set; } @@ -76,7 +71,7 @@ namespace Wabbajack [Reactive] public bool UpdateAvailable { get; private set; } - public MainWindowVM(ILogger logger, MainSettings settings, Client wjClient, + public MainWindowVM(ILogger logger, Client wjClient, IServiceProvider serviceProvider, ModeSelectionVM modeSelectionVM, ModListGalleryVM modListGalleryVM, ResourceMonitor resourceMonitor, InstallerVM installer, CompilerVM compilerVM, SettingsVM settingsVM, WebBrowserVM webBrowserVM) { @@ -85,7 +80,6 @@ namespace Wabbajack _resourceMonitor = resourceMonitor; _serviceProvider = serviceProvider; ConverterRegistration.Register(); - Settings = settings; Installer = installer; Compiler = compilerVM; SettingsPane = settingsVM; diff --git a/Wabbajack.App.Wpf/View Models/Settings/SettingsVM.cs b/Wabbajack.App.Wpf/View Models/Settings/SettingsVM.cs index 44ced940..a32855ce 100644 --- a/Wabbajack.App.Wpf/View Models/Settings/SettingsVM.cs +++ b/Wabbajack.App.Wpf/View Models/Settings/SettingsVM.cs @@ -2,28 +2,32 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Linq; using System.Reflection; -using System.Text; using System.Threading.Tasks; using System.Windows.Input; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using ReactiveUI; -using Wabbajack; +using Wabbajack.Common; +using Wabbajack.Downloaders; using Wabbajack.LoginManagers; using Wabbajack.Messages; using Wabbajack.Networking.WabbajackClientApi; +using Wabbajack.RateLimiter; +using Wabbajack.Services.OSIntegrated; using Wabbajack.Services.OSIntegrated.TokenProviders; +using Wabbajack.Util; using Wabbajack.View_Models.Settings; namespace Wabbajack { public class SettingsVM : BackNavigatingVM { + private readonly Configuration.MainSettings _settings; + private readonly SettingsManager _settingsManager; + public LoginManagerVM Login { get; } public PerformanceSettings Performance { get; } - public FiltersSettings Filters { get; } public AuthorFilesVM AuthorFile { get; } public ICommand OpenTerminalCommand { get; } @@ -31,12 +35,30 @@ namespace Wabbajack public SettingsVM(ILogger logger, IServiceProvider provider) : base(logger) { - Login = new LoginManagerVM(provider.GetRequiredService>(), this, + _settings = provider.GetRequiredService(); + _settingsManager = provider.GetRequiredService(); + + Login = new LoginManagerVM(provider.GetRequiredService>(), this, provider.GetRequiredService>()); - AuthorFile = new AuthorFilesVM(provider.GetRequiredService>()!, + AuthorFile = new AuthorFilesVM(provider.GetRequiredService>()!, provider.GetRequiredService()!, provider.GetRequiredService()!, this); OpenTerminalCommand = ReactiveCommand.CreateFromTask(OpenTerminal); - BackCommand = ReactiveCommand.Create(NavigateBack.Send); + Performance = new PerformanceSettings( + _settings, + provider.GetRequiredService>(), + provider.GetRequiredService()); + BackCommand = ReactiveCommand.Create(() => + { + NavigateBack.Send(); + Unload(); + }); + } + + public override void Unload() + { + _settingsManager.Save(Configuration.MainSettings.SettingsFileName, _settings).FireAndForget(); + + base.Unload(); } private async Task OpenTerminal() diff --git a/Wabbajack.App.Wpf/Views/Common/CpuView.xaml.cs b/Wabbajack.App.Wpf/Views/Common/CpuView.xaml.cs index d56efa07..4541b3c4 100644 --- a/Wabbajack.App.Wpf/Views/Common/CpuView.xaml.cs +++ b/Wabbajack.App.Wpf/Views/Common/CpuView.xaml.cs @@ -1,24 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reactive.Disposables; -using System.Text; -using System.Threading.Tasks; +using System.Reactive.Disposables; using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; using ReactiveUI; -using ReactiveUI.Fody.Helpers; -using Wabbajack; -using System.Windows.Controls.Primitives; using System.Reactive.Linq; -using Wabbajack.Common; using Wabbajack.RateLimiter; namespace Wabbajack @@ -36,23 +19,12 @@ namespace Wabbajack public static readonly DependencyProperty ProgressPercentProperty = DependencyProperty.Register(nameof(ProgressPercent), typeof(Percent), typeof(CpuView), new FrameworkPropertyMetadata(default(Percent), WireNotifyPropertyChanged)); - public MainSettings SettingsHook - { - get => (MainSettings)GetValue(SettingsHookProperty); - set => SetValue(SettingsHookProperty, value); - } - public static readonly DependencyProperty SettingsHookProperty = DependencyProperty.Register(nameof(SettingsHook), typeof(MainSettings), typeof(CpuView), - new FrameworkPropertyMetadata(default(SettingsVM), WireNotifyPropertyChanged)); - - private bool _ShowingSettings; - public bool ShowingSettings { get => _ShowingSettings; set => this.RaiseAndSetIfChanged(ref _ShowingSettings, value); } - public CpuView() { InitializeComponent(); this.WhenActivated(disposable => { - + this.WhenAny(x => x.ViewModel.StatusList) .BindToStrict(this, x => x.CpuListControl.ItemsSource) .DisposeWith(disposable); diff --git a/Wabbajack.App.Wpf/Views/Installers/InstallationCompleteView.xaml b/Wabbajack.App.Wpf/Views/Installers/InstallationCompleteView.xaml index 74284763..f76f9d15 100644 --- a/Wabbajack.App.Wpf/Views/Installers/InstallationCompleteView.xaml +++ b/Wabbajack.App.Wpf/Views/Installers/InstallationCompleteView.xaml @@ -12,7 +12,7 @@ x:TypeArguments="local:InstallerVM" mc:Ignorable="d"> - + @@ -23,6 +23,7 @@ + + Text="Modlist Readme" /> + + + + + + + + + Background="Transparent" Grid.ColumnSpan="2" Margin="0,0,10,0"> diff --git a/Wabbajack.App.Wpf/Views/Installers/InstallationCompleteView.xaml.cs b/Wabbajack.App.Wpf/Views/Installers/InstallationCompleteView.xaml.cs index d2e70061..b4000b86 100644 --- a/Wabbajack.App.Wpf/Views/Installers/InstallationCompleteView.xaml.cs +++ b/Wabbajack.App.Wpf/Views/Installers/InstallationCompleteView.xaml.cs @@ -46,6 +46,9 @@ namespace Wabbajack this.WhenAny(x => x.ViewModel.OpenReadmeCommand) .BindToStrict(this, x => x.OpenReadmeButton.Command) .DisposeWith(dispose); + this.WhenAny(x => x.ViewModel.OpenWikiCommand) + .BindToStrict(this, x => x.OpenWikiButton.Command) + .DisposeWith(dispose); this.WhenAny(x => x.ViewModel.CloseWhenCompleteCommand) .BindToStrict(this, x => x.CloseButton.Command) .DisposeWith(dispose); diff --git a/Wabbajack.App.Wpf/Views/Installers/InstallationConfigurationView.xaml b/Wabbajack.App.Wpf/Views/Installers/InstallationConfigurationView.xaml index 225346f0..6580df93 100644 --- a/Wabbajack.App.Wpf/Views/Installers/InstallationConfigurationView.xaml +++ b/Wabbajack.App.Wpf/Views/Installers/InstallationConfigurationView.xaml @@ -39,6 +39,13 @@ FontSize="14" Text="Target Modlist" TextAlignment="Center" /> + + + + + + + diff --git a/Wabbajack.App.Wpf/Views/Installers/InstallationConfigurationView.xaml.cs b/Wabbajack.App.Wpf/Views/Installers/InstallationConfigurationView.xaml.cs index 121da58f..178780e7 100644 --- a/Wabbajack.App.Wpf/Views/Installers/InstallationConfigurationView.xaml.cs +++ b/Wabbajack.App.Wpf/Views/Installers/InstallationConfigurationView.xaml.cs @@ -39,14 +39,21 @@ namespace Wabbajack this.WhenAny(x => x.ViewModel.BeginCommand) .BindToStrict(this, x => x.BeginButton.Command) .DisposeWith(dispose); - + this.BindStrict(ViewModel, vm => vm.OverwriteFiles, x => x.OverwriteCheckBox.IsChecked) + .DisposeWith(dispose); + // Error handling - + this.WhenAnyValue(x => x.ViewModel.ErrorState) .Select(v => !v.Failed) .BindToStrict(this, view => view.BeginButton.IsEnabled) .DisposeWith(dispose); - + + this.WhenAnyValue(x => x.ViewModel.ErrorState) + .Select(v => v.Reason) + .BindToStrict(this, view => view.errorTextBox.Text) + .DisposeWith(dispose); + this.WhenAnyValue(x => x.ViewModel.ErrorState) .Select(v => v.Failed ? Visibility.Visible : Visibility.Hidden) .BindToStrict(this, view => view.ErrorSummaryIcon.Visibility) diff --git a/Wabbajack.App.Wpf/Views/Installers/InstallationView.xaml b/Wabbajack.App.Wpf/Views/Installers/InstallationView.xaml index 9dc049e9..39fc63ee 100644 --- a/Wabbajack.App.Wpf/Views/Installers/InstallationView.xaml +++ b/Wabbajack.App.Wpf/Views/Installers/InstallationView.xaml @@ -324,20 +324,6 @@ - diff --git a/Wabbajack.App.Wpf/Views/Installers/MO2InstallerConfigView.xaml b/Wabbajack.App.Wpf/Views/Installers/MO2InstallerConfigView.xaml index 5561d7fd..f47095f3 100644 --- a/Wabbajack.App.Wpf/Views/Installers/MO2InstallerConfigView.xaml +++ b/Wabbajack.App.Wpf/Views/Installers/MO2InstallerConfigView.xaml @@ -46,21 +46,5 @@ FontSize="14" PickerVM="{Binding DownloadLocation}" ToolTip="The directory where modlist archives will be downloaded to" /> - - - - - diff --git a/Wabbajack.App.Wpf/Views/Interventions/ConfirmUpdateOfExistingInstallView.xaml b/Wabbajack.App.Wpf/Views/Interventions/ConfirmUpdateOfExistingInstallView.xaml deleted file mode 100644 index 60620f63..00000000 --- a/Wabbajack.App.Wpf/Views/Interventions/ConfirmUpdateOfExistingInstallView.xaml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - + + + diff --git a/Wabbajack.App.Wpf/Views/Settings/PerformanceSettingsView.xaml.cs b/Wabbajack.App.Wpf/Views/Settings/PerformanceSettingsView.xaml.cs index efed2027..d2a0ee5c 100644 --- a/Wabbajack.App.Wpf/Views/Settings/PerformanceSettingsView.xaml.cs +++ b/Wabbajack.App.Wpf/Views/Settings/PerformanceSettingsView.xaml.cs @@ -1,4 +1,5 @@ using System; +using System.Reactive.Disposables; using ReactiveUI; using Wabbajack.Paths.IO; @@ -15,12 +16,21 @@ namespace Wabbajack this.WhenActivated(disposable => { + this.BindStrict( + ViewModel, + x => x.MaximumMemoryPerDownloadThreadMb, + x => x.MaximumMemoryPerDownloadThreadIntegerUpDown.Value) + .DisposeWith(disposable); this.EditResourceSettings.Command = ReactiveCommand.Create(() => { UIUtils.OpenFile( KnownFolders.WabbajackAppLocal.Combine("saved_settings", "resource_settings.json")); Environment.Exit(0); }); + ResetMaximumMemoryPerDownloadThread.Command = ReactiveCommand.Create(() => + { + ViewModel.ResetMaximumMemoryPerDownloadThreadMb(); + }); }); } } diff --git a/Wabbajack.App.Wpf/Wabbajack.App.Wpf.csproj b/Wabbajack.App.Wpf/Wabbajack.App.Wpf.csproj index 6cec0311..af71c310 100644 --- a/Wabbajack.App.Wpf/Wabbajack.App.Wpf.csproj +++ b/Wabbajack.App.Wpf/Wabbajack.App.Wpf.csproj @@ -2,7 +2,7 @@ WinExe - net6.0-windows + net7.0-windows true x64 win10-x64 @@ -73,12 +73,12 @@ - + NU1701 - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -95,11 +95,11 @@ - - - + + + - + diff --git a/Wabbajack.CLI.Builder/Wabbajack.CLI.Builder.csproj b/Wabbajack.CLI.Builder/Wabbajack.CLI.Builder.csproj index 28ed9b4e..87e50f36 100644 --- a/Wabbajack.CLI.Builder/Wabbajack.CLI.Builder.csproj +++ b/Wabbajack.CLI.Builder/Wabbajack.CLI.Builder.csproj @@ -1,14 +1,14 @@ - net6.0 + net7.0 enable enable - + diff --git a/Wabbajack.CLI/Wabbajack.CLI.csproj b/Wabbajack.CLI/Wabbajack.CLI.csproj index c9edf2b7..fe9ebfc9 100644 --- a/Wabbajack.CLI/Wabbajack.CLI.csproj +++ b/Wabbajack.CLI/Wabbajack.CLI.csproj @@ -1,4 +1,4 @@ - + Exe @@ -13,11 +13,12 @@ CS8600 CS8601 CS8618 + net7.0 - + diff --git a/Wabbajack.Common/HttpExtensions.cs b/Wabbajack.Common/HttpExtensions.cs index a0900120..b2ca8d39 100644 --- a/Wabbajack.Common/HttpExtensions.cs +++ b/Wabbajack.Common/HttpExtensions.cs @@ -14,12 +14,21 @@ namespace Wabbajack.Common; public static class HttpExtensions { + private const string ChromeUserAgent = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36"; public static HttpRequestMessage AddCookies(this HttpRequestMessage msg, Cookie[] cookies) { msg.Headers.Add("Cookie", string.Join(";", cookies.Select(c => $"{c.Name}={c.Value}"))); return msg; } - + + public static HttpRequestMessage AddChromeAgent(this HttpRequestMessage msg, string? overrideUserAgent = null) + { + msg.Headers.UserAgent.Clear(); + msg.Headers.Add("User-Agent", overrideUserAgent ?? ChromeUserAgent); + return msg; + } + public static HttpRequestMessage AddHeaders(this HttpRequestMessage msg, IEnumerable<(string Key, string Value)> headers) { foreach (var header in headers) @@ -29,17 +38,10 @@ public static class HttpExtensions return msg; } - public static HttpRequestMessage AddChromeAgent(this HttpRequestMessage msg) - { - msg.Headers.Add("User-Agent", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36"); - return msg; - } - public static HttpRequestMessage ToHttpRequestMessage(this ManualDownload.BrowserDownloadState browserState) { var msg = new HttpRequestMessage(HttpMethod.Get, browserState.Uri); - msg.AddChromeAgent(); + msg.AddChromeAgent(browserState.UserAgent); msg.AddCookies(browserState.Cookies); msg.AddHeaders(browserState.Headers); return msg; diff --git a/Wabbajack.Common/Wabbajack.Common.csproj b/Wabbajack.Common/Wabbajack.Common.csproj index 35b829e3..a382ae26 100644 --- a/Wabbajack.Common/Wabbajack.Common.csproj +++ b/Wabbajack.Common/Wabbajack.Common.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable GPL-3.0-or-later $(VERSION) @@ -34,7 +34,7 @@ - + diff --git a/Wabbajack.Compiler.Test/Wabbajack.Compiler.Test.csproj b/Wabbajack.Compiler.Test/Wabbajack.Compiler.Test.csproj index 019ec030..b9b77692 100644 --- a/Wabbajack.Compiler.Test/Wabbajack.Compiler.Test.csproj +++ b/Wabbajack.Compiler.Test/Wabbajack.Compiler.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false diff --git a/Wabbajack.Compiler/Wabbajack.Compiler.csproj b/Wabbajack.Compiler/Wabbajack.Compiler.csproj index 62584356..9ca4cf58 100644 --- a/Wabbajack.Compiler/Wabbajack.Compiler.csproj +++ b/Wabbajack.Compiler/Wabbajack.Compiler.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable $(VERSION) GPL-3.0-or-later diff --git a/Wabbajack.Compression.BSA.Test/Wabbajack.Compression.BSA.Test.csproj b/Wabbajack.Compression.BSA.Test/Wabbajack.Compression.BSA.Test.csproj index c9ee6010..270a509f 100644 --- a/Wabbajack.Compression.BSA.Test/Wabbajack.Compression.BSA.Test.csproj +++ b/Wabbajack.Compression.BSA.Test/Wabbajack.Compression.BSA.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false diff --git a/Wabbajack.Compression.BSA/Wabbajack.Compression.BSA.csproj b/Wabbajack.Compression.BSA/Wabbajack.Compression.BSA.csproj index ae648ab2..d9d11284 100644 --- a/Wabbajack.Compression.BSA/Wabbajack.Compression.BSA.csproj +++ b/Wabbajack.Compression.BSA/Wabbajack.Compression.BSA.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable true GPL-3.0-or-later diff --git a/Wabbajack.Compression.Zip.Test/Wabbajack.Compression.Zip.Test.csproj b/Wabbajack.Compression.Zip.Test/Wabbajack.Compression.Zip.Test.csproj index 3d04da28..6d15e005 100644 --- a/Wabbajack.Compression.Zip.Test/Wabbajack.Compression.Zip.Test.csproj +++ b/Wabbajack.Compression.Zip.Test/Wabbajack.Compression.Zip.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable false diff --git a/Wabbajack.Compression.Zip/Wabbajack.Compression.Zip.csproj b/Wabbajack.Compression.Zip/Wabbajack.Compression.Zip.csproj index bad41454..01178a67 100644 --- a/Wabbajack.Compression.Zip/Wabbajack.Compression.Zip.csproj +++ b/Wabbajack.Compression.Zip/Wabbajack.Compression.Zip.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable enable diff --git a/Wabbajack.Configuration/MainSettings.cs b/Wabbajack.Configuration/MainSettings.cs new file mode 100644 index 00000000..5b8bf4eb --- /dev/null +++ b/Wabbajack.Configuration/MainSettings.cs @@ -0,0 +1,27 @@ +namespace Wabbajack.Configuration; + +public class MainSettings +{ + public const string SettingsFileName = "app_settings"; + private const int SettingsVersion = 1; + + public int CurrentSettingsVersion { get; set; } + + public PerformanceSettings PerformanceSettings { get; set; } = new(); + + public bool Upgrade() + { + if (CurrentSettingsVersion == SettingsVersion) + { + return false; + } + + if (CurrentSettingsVersion < 1) + { + PerformanceSettings.MaximumMemoryPerDownloadThreadMb = -1; + } + + CurrentSettingsVersion = SettingsVersion; + return true; + } +} \ No newline at end of file diff --git a/Wabbajack.Configuration/PerformanceSettings.cs b/Wabbajack.Configuration/PerformanceSettings.cs new file mode 100644 index 00000000..93dff240 --- /dev/null +++ b/Wabbajack.Configuration/PerformanceSettings.cs @@ -0,0 +1,6 @@ +namespace Wabbajack.Configuration; + +public class PerformanceSettings +{ + public int MaximumMemoryPerDownloadThreadMb { get; set; } +} \ No newline at end of file diff --git a/Wabbajack.Configuration/Wabbajack.Configuration.csproj b/Wabbajack.Configuration/Wabbajack.Configuration.csproj new file mode 100644 index 00000000..cfadb03d --- /dev/null +++ b/Wabbajack.Configuration/Wabbajack.Configuration.csproj @@ -0,0 +1,9 @@ + + + + net7.0 + enable + enable + + + diff --git a/Wabbajack.DTOs.ConverterGenerators/Wabbajack.DTOs.ConverterGenerators.csproj b/Wabbajack.DTOs.ConverterGenerators/Wabbajack.DTOs.ConverterGenerators.csproj index f549991b..3831f9b2 100644 --- a/Wabbajack.DTOs.ConverterGenerators/Wabbajack.DTOs.ConverterGenerators.csproj +++ b/Wabbajack.DTOs.ConverterGenerators/Wabbajack.DTOs.ConverterGenerators.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net7.0 GPL-3.0-or-later $(VERSION) CS8600 diff --git a/Wabbajack.DTOs.Test/Wabbajack.DTOs.Test.csproj b/Wabbajack.DTOs.Test/Wabbajack.DTOs.Test.csproj index eb42bd83..6bc36413 100644 --- a/Wabbajack.DTOs.Test/Wabbajack.DTOs.Test.csproj +++ b/Wabbajack.DTOs.Test/Wabbajack.DTOs.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false diff --git a/Wabbajack.DTOs/Game/GameMetaData.cs b/Wabbajack.DTOs/Game/GameMetaData.cs index 36dc7c9f..1b4a4061 100644 --- a/Wabbajack.DTOs/Game/GameMetaData.cs +++ b/Wabbajack.DTOs/Game/GameMetaData.cs @@ -21,7 +21,7 @@ public class GameMetaData public int[] SteamIDs { get; internal init; } = Array.Empty(); // to get gog ids: https://www.gogdb.org - public int[] GOGIDs { get; internal init; } = Array.Empty(); + public long[] GOGIDs { get; internal init; } = Array.Empty(); // to get these ids, split the numbers from the letters in file names found in // C:\ProgramData\Origin\LocalContent\{game name)\*.mfst diff --git a/Wabbajack.DTOs/Game/GameRegistry.cs b/Wabbajack.DTOs/Game/GameRegistry.cs index 95bec0e6..4bf839a3 100644 --- a/Wabbajack.DTOs/Game/GameRegistry.cs +++ b/Wabbajack.DTOs/Game/GameRegistry.cs @@ -14,7 +14,7 @@ public static class GameRegistry { Game = Game.Morrowind, SteamIDs = new[] {22320}, - GOGIDs = new[] {1440163901, 1435828767}, + GOGIDs = new long[] {1440163901, 1435828767}, NexusName = "morrowind", NexusGameId = 100, MO2Name = "Morrowind", @@ -38,7 +38,7 @@ public static class GameRegistry MO2Name = "Oblivion", MO2ArchiveName = "oblivion", SteamIDs = new[] {22330}, - GOGIDs = new[] {1458058109}, + GOGIDs = new long[] {1458058109}, RequiredFiles = new[] { "oblivion.exe".ToRelativePath() @@ -56,7 +56,7 @@ public static class GameRegistry MO2Name = "Fallout 3", MO2ArchiveName = "fallout3", SteamIDs = new[] {22300, 22370}, // base game and GotY - GOGIDs = new[] {1454315831}, // GotY edition + GOGIDs = new long[] {1454315831}, // GotY edition RequiredFiles = new[] { "Fallout3.exe".ToRelativePath() @@ -73,7 +73,7 @@ public static class GameRegistry MO2Name = "New Vegas", MO2ArchiveName = "falloutnv", SteamIDs = new[] {22380, 22490}, // normal and RU version - GOGIDs = new[] {1454587428}, + GOGIDs = new long[] {1454587428}, RequiredFiles = new[] { "FalloutNV.exe".ToRelativePath() @@ -107,7 +107,7 @@ public static class GameRegistry MO2Name = "Skyrim Special Edition", MO2ArchiveName = "skyrimse", SteamIDs = new[] {489830}, - GOGIDs = new[] + GOGIDs = new long[] { 1711230643,// The Elder Scrolls V: Skyrim Special Edition AKA Base Game 1801825368,// The Elder Scrolls V: Skyrim Anniversary Edition AKA The Store Bundle @@ -130,6 +130,7 @@ public static class GameRegistry MO2Name = "Fallout 4", MO2ArchiveName = "fallout4", SteamIDs = new[] {377160}, + GOGIDs = new long[]{1998527297}, RequiredFiles = new[] { "Fallout4.exe".ToRelativePath() @@ -182,7 +183,7 @@ public static class GameRegistry MO2Name = "Enderal Special Edition", MO2ArchiveName = "enderalse", SteamIDs = new[] {976620}, - GOGIDs = new [] {1708684988}, + GOGIDs = new long[] {1708684988}, RequiredFiles = new[] { "SkyrimSE.exe".ToRelativePath() @@ -216,7 +217,7 @@ public static class GameRegistry MO2Name = "Darkest Dungeon", NexusGameId = 804, SteamIDs = new[] {262060}, - GOGIDs = new[] {1450711444}, + GOGIDs = new long[] {1450711444}, EpicGameStoreIDs = new[] {"b4eecf70e3fe4e928b78df7855a3fc2d"}, IsGenericMO2Plugin = true, RequiredFiles = new[] @@ -235,7 +236,7 @@ public static class GameRegistry MO2ArchiveName = "dishonored", NexusGameId = 802, SteamIDs = new[] {205100}, - GOGIDs = new[] {1701063787}, + GOGIDs = new long[] {1701063787}, RequiredFiles = new[] { @"Binaries\Win32\Dishonored.exe".ToRelativePath() @@ -252,7 +253,7 @@ public static class GameRegistry MO2Name = "The Witcher: Enhanced Edition", MO2ArchiveName = "witcher", SteamIDs = new[] {20900}, // normal and GotY - GOGIDs = new[] {1207658924}, // normal, GotY and both in packages + GOGIDs = new long[] {1207658924}, // normal, GotY and both in packages RequiredFiles = new[] { @"System\witcher.exe".ToRelativePath() @@ -269,7 +270,7 @@ public static class GameRegistry MO2Name = "The Witcher 3: Wild Hunt", MO2ArchiveName = "witcher3", SteamIDs = new[] {292030, 499450}, // normal and GotY - GOGIDs = new[] + GOGIDs = new long[] {1207664643, 1495134320, 1207664663, 1640424747}, // normal, GotY and both in packages RequiredFiles = new[] { @@ -287,7 +288,7 @@ public static class GameRegistry MO2ArchiveName = "stardewvalley", NexusGameId = 1303, SteamIDs = new[] {413150}, - GOGIDs = new[] {1453375253}, + GOGIDs = new long[] {1453375253}, IsGenericMO2Plugin = true, RequiredFiles = new[] { @@ -305,7 +306,7 @@ public static class GameRegistry MO2ArchiveName = "kingdomcomedeliverance", NexusGameId = 2298, SteamIDs = new[] {379430}, - GOGIDs = new[] {1719198803}, + GOGIDs = new long[] {1719198803}, IsGenericMO2Plugin = true, RequiredFiles = new[] { @@ -339,7 +340,7 @@ public static class GameRegistry NexusGameId = 1634, MO2Name = "No Man's Sky", SteamIDs = new[] {275850}, - GOGIDs = new[] {1446213994}, + GOGIDs = new long[] {1446213994}, RequiredFiles = new[] { @"Binaries\NMS.exe".ToRelativePath() @@ -356,7 +357,7 @@ public static class GameRegistry MO2Name = "Dragon Age: Origins", SteamIDs = new[] {47810}, OriginIDs = new[] {"DR:169789300", "DR:208591800"}, - GOGIDs = new[] {1949616134}, + GOGIDs = new long[] {1949616134}, RequiredFiles = new[] { @"bin_ship\daorigins.exe".ToRelativePath() @@ -404,7 +405,7 @@ public static class GameRegistry MO2Name = "Kerbal Space Program", NexusGameId = 272, SteamIDs = new[] {220200}, - GOGIDs = new[] {1429864849}, + GOGIDs = new long[] {1429864849}, IsGenericMO2Plugin = true, RequiredFiles = new[] { @@ -432,7 +433,7 @@ public static class GameRegistry { Game = Game.Cyberpunk2077, SteamIDs = new[] {1091500}, - GOGIDs = new [] {2093619782, 1423049311}, + GOGIDs = new long[] {2093619782, 1423049311}, EpicGameStoreIDs = new[] {"5beededaad9743df90e8f07d92df153f"}, MO2Name = "Cyberpunk 2077", NexusName = "cyberpunk2077", @@ -466,7 +467,7 @@ public static class GameRegistry { Game = Game.DragonsDogma, SteamIDs = new[] {367500 }, - GOGIDs = new []{1242384383}, + GOGIDs = new long[]{1242384383}, MO2Name = "Dragon's Dogma: Dark Arisen", MO2ArchiveName = "dragonsdogma", NexusName = "dragonsdogma", @@ -520,7 +521,7 @@ public static class GameRegistry MO2Name = "Mount & Blade II: Bannerlord", MO2ArchiveName = "mountandblade2bannerlord", SteamIDs = new[] { 261550 }, - GOGIDs = new [] { + GOGIDs = new long[] { 1564781494, //Mount & Blade II: Bannerlord : Game 1681929523, //Mount & Blade II: Bannerlord - Digital Deluxe : Package 1802539526, //Mount & Blade II: Bannerlord : Package diff --git a/Wabbajack.DTOs/Interventions/ManualDownload.cs b/Wabbajack.DTOs/Interventions/ManualDownload.cs index 15a3be24..84dda1dd 100644 --- a/Wabbajack.DTOs/Interventions/ManualDownload.cs +++ b/Wabbajack.DTOs/Interventions/ManualDownload.cs @@ -10,14 +10,14 @@ namespace Wabbajack.DTOs.Interventions; public class ManualDownload : AUserIntervention { public Archive Archive { get; } - + public ManualDownload(Archive archive) { Archive = archive; } - public record BrowserDownloadState(Uri Uri, Cookie[] Cookies, (string Key, string Value)[] Headers) + public record BrowserDownloadState(Uri Uri, Cookie[] Cookies, (string Key, string Value)[] Headers, string UserAgent) { - + } } \ No newline at end of file diff --git a/Wabbajack.DTOs/ModList/ModListMetadata.cs b/Wabbajack.DTOs/ModList/ModListMetadata.cs index fbb27dab..df3bfd50 100644 --- a/Wabbajack.DTOs/ModList/ModListMetadata.cs +++ b/Wabbajack.DTOs/ModList/ModListMetadata.cs @@ -30,6 +30,8 @@ public class ModlistMetadata [JsonPropertyName("image_contains_title")] public bool ImageContainsTitle { get; set; } + [JsonPropertyName("DisplayVersionOnlyInInstallerView")] public bool DisplayVersionOnlyInInstallerView { get; set; } + [JsonPropertyName("force_down")] public bool ForceDown { get; set; } [JsonPropertyName("links")] public LinksObject Links { get; set; } = new(); diff --git a/Wabbajack.DTOs/Wabbajack.DTOs.csproj b/Wabbajack.DTOs/Wabbajack.DTOs.csproj index 4e232d26..04b1cc65 100644 --- a/Wabbajack.DTOs/Wabbajack.DTOs.csproj +++ b/Wabbajack.DTOs/Wabbajack.DTOs.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable $(VERSION) GPL-3.0-or-later diff --git a/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj b/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj index 7544d14c..02afa7a1 100644 --- a/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj +++ b/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable enable diff --git a/Wabbajack.Downloaders.Dispatcher.Test/Wabbajack.Downloaders.Dispatcher.Test.csproj b/Wabbajack.Downloaders.Dispatcher.Test/Wabbajack.Downloaders.Dispatcher.Test.csproj index 901a70cc..9070839d 100644 --- a/Wabbajack.Downloaders.Dispatcher.Test/Wabbajack.Downloaders.Dispatcher.Test.csproj +++ b/Wabbajack.Downloaders.Dispatcher.Test/Wabbajack.Downloaders.Dispatcher.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false @@ -11,7 +11,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/Wabbajack.Downloaders.Dispatcher/Wabbajack.Downloaders.Dispatcher.csproj b/Wabbajack.Downloaders.Dispatcher/Wabbajack.Downloaders.Dispatcher.csproj index 0db2bd81..7cebb553 100644 --- a/Wabbajack.Downloaders.Dispatcher/Wabbajack.Downloaders.Dispatcher.csproj +++ b/Wabbajack.Downloaders.Dispatcher/Wabbajack.Downloaders.Dispatcher.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable $(VERSION) GPL-3.0-or-later diff --git a/Wabbajack.Downloaders.GameFile/GameLocator.cs b/Wabbajack.Downloaders.GameFile/GameLocator.cs index 2cf9aef9..8c2a9d94 100644 --- a/Wabbajack.Downloaders.GameFile/GameLocator.cs +++ b/Wabbajack.Downloaders.GameFile/GameLocator.cs @@ -5,6 +5,8 @@ using GameFinder.StoreHandlers.EGS; using GameFinder.StoreHandlers.GOG; using GameFinder.StoreHandlers.Origin; using GameFinder.StoreHandlers.Steam; +using GameFinder.StoreHandlers.Steam.Models; +using GameFinder.StoreHandlers.Steam.Models.ValueTypes; using Microsoft.Extensions.Logging; using Wabbajack.DTOs; using Wabbajack.Paths; @@ -19,10 +21,10 @@ public class GameLocator : IGameLocator private readonly EGSHandler? _egs; private readonly OriginHandler? _origin; - private readonly Dictionary _steamGames = new(); - private readonly Dictionary _gogGames = new(); - private readonly Dictionary _egsGames = new(StringComparer.OrdinalIgnoreCase); - private readonly Dictionary _originGames = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _steamGames = new(); + private readonly Dictionary _gogGames = new(); + private readonly Dictionary _egsGames = new(); + private readonly Dictionary _originGames = new(); private readonly Dictionary _locationCache; private readonly ILogger _logger; @@ -30,19 +32,20 @@ public class GameLocator : IGameLocator public GameLocator(ILogger logger) { _logger = logger; + var fileSystem = NexusMods.Paths.FileSystem.Shared; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { var windowsRegistry = new WindowsRegistry(); - _steam = new SteamHandler(windowsRegistry); - _gog = new GOGHandler(windowsRegistry); - _egs = new EGSHandler(windowsRegistry); - _origin = new OriginHandler(); + _steam = new SteamHandler(fileSystem, windowsRegistry); + _gog = new GOGHandler(windowsRegistry, fileSystem); + _egs = new EGSHandler(windowsRegistry, fileSystem); + _origin = new OriginHandler(fileSystem); } else { - _steam = new SteamHandler(null); + _steam = new SteamHandler(fileSystem, null); } _locationCache = new Dictionary(); @@ -54,7 +57,7 @@ public class GameLocator : IGameLocator { try { - FindStoreGames(_steam, _steamGames, game => game.Path); + FindStoreGames(_steam, _steamGames, game => (AbsolutePath)game.Path.GetFullPath()); } catch (Exception e) { @@ -63,7 +66,7 @@ public class GameLocator : IGameLocator try { - FindStoreGames(_gog, _gogGames, game => game.Path); + FindStoreGames(_gog, _gogGames, game => (AbsolutePath)game.Path.GetFullPath()); } catch (Exception e) { @@ -72,7 +75,7 @@ public class GameLocator : IGameLocator try { - FindStoreGames(_egs, _egsGames, game => game.InstallLocation); + FindStoreGames(_egs, _egsGames, game => (AbsolutePath)game.InstallLocation.GetFullPath()); } catch (Exception e) { @@ -81,7 +84,7 @@ public class GameLocator : IGameLocator try { - FindStoreGames(_origin, _originGames, game => game.InstallPath); + FindStoreGames(_origin, _originGames, game => (AbsolutePath)game.InstallPath.GetFullPath()); } catch (Exception e) { @@ -92,8 +95,9 @@ public class GameLocator : IGameLocator private void FindStoreGames( AHandler? handler, Dictionary paths, - Func getPath) - where TGame : class + Func getPath) + where TGame : class, IGame + where TId : notnull { if (handler is null) return; @@ -103,7 +107,7 @@ public class GameLocator : IGameLocator { try { - var path = getPath(game).ToAbsolutePath(); + var path = getPath(game); if (!path.DirectoryExists()) { _logger.LogError("Game does not exist: {Game}", game); @@ -160,28 +164,28 @@ public class GameLocator : IGameLocator foreach (var id in metaData.SteamIDs) { - if (!_steamGames.TryGetValue(id, out var found)) continue; + if (!_steamGames.TryGetValue(AppId.From((uint)id), out var found)) continue; path = found; return true; } foreach (var id in metaData.GOGIDs) { - if (!_gogGames.TryGetValue(id, out var found)) continue; + if (!_gogGames.TryGetValue(GOGGameId.From(id), out var found)) continue; path = found; return true; } foreach (var id in metaData.EpicGameStoreIDs) { - if (!_egsGames.TryGetValue(id, out var found)) continue; + if (!_egsGames.TryGetValue(EGSGameId.From(id), out var found)) continue; path = found; return true; } foreach (var id in metaData.OriginIDs) { - if (!_originGames.TryGetValue(id, out var found)) continue; + if (!_originGames.TryGetValue(OriginGameId.From(id), out var found)) continue; path = found; return true; } diff --git a/Wabbajack.Downloaders.GameFile/Wabbajack.Downloaders.GameFile.csproj b/Wabbajack.Downloaders.GameFile/Wabbajack.Downloaders.GameFile.csproj index 26f0e1ca..598216a2 100644 --- a/Wabbajack.Downloaders.GameFile/Wabbajack.Downloaders.GameFile.csproj +++ b/Wabbajack.Downloaders.GameFile/Wabbajack.Downloaders.GameFile.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable enable @@ -18,10 +18,10 @@ - - - - + + + + diff --git a/Wabbajack.Downloaders.GoogleDrive/GoogleDriveDownloader.cs b/Wabbajack.Downloaders.GoogleDrive/GoogleDriveDownloader.cs index 2dede342..c4906694 100644 --- a/Wabbajack.Downloaders.GoogleDrive/GoogleDriveDownloader.cs +++ b/Wabbajack.Downloaders.GoogleDrive/GoogleDriveDownloader.cs @@ -65,7 +65,7 @@ public class GoogleDriveDownloader : ADownloader iniData) { if (iniData.ContainsKey("directURL") && Uri.TryCreate(iniData["directURL"].CleanIniString(), UriKind.Absolute, out var uri)) @@ -74,8 +74,8 @@ public class GoogleDriveDownloader : ADownloader Priority.Normal; - - + + public async Task DownloadStream(Archive archive, Func> fn, CancellationToken token) { var state = archive.State as DTOs.DownloadStates.GoogleDrive; @@ -112,8 +112,8 @@ public class GoogleDriveDownloader : ADownloader c.Key.StartsWith("download_warning_")); @@ -124,7 +124,7 @@ public class GoogleDriveDownloader : ADownloaderGoogle Drive - Quota exceeded")) throw new Exception("Google Drive - Quota Exceeded"); - + doc.LoadHtml(txt); var action = doc.DocumentNode.DescendantsAndSelf() @@ -133,7 +133,7 @@ public class GoogleDriveDownloader : ADownloader d.GetAttributeValue("action", "")) .FirstOrDefault(); - if (action != null) + if (action != null) warning = ("download_warning_", "t"); } @@ -145,18 +145,18 @@ public class GoogleDriveDownloader : ADownloader - net6.0 + net7.0 enable $(VERSION) GPL-3.0-or-later diff --git a/Wabbajack.Downloaders.Http/Wabbajack.Downloaders.Http.csproj b/Wabbajack.Downloaders.Http/Wabbajack.Downloaders.Http.csproj index f0190d2e..e0fbecdb 100644 --- a/Wabbajack.Downloaders.Http/Wabbajack.Downloaders.Http.csproj +++ b/Wabbajack.Downloaders.Http/Wabbajack.Downloaders.Http.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable $(VERSION) GPL-3.0-or-later diff --git a/Wabbajack.Downloaders.IPS4OAuth2Downloader/Wabbajack.Downloaders.IPS4OAuth2Downloader.csproj b/Wabbajack.Downloaders.IPS4OAuth2Downloader/Wabbajack.Downloaders.IPS4OAuth2Downloader.csproj index ae2488eb..6fdce2ea 100644 --- a/Wabbajack.Downloaders.IPS4OAuth2Downloader/Wabbajack.Downloaders.IPS4OAuth2Downloader.csproj +++ b/Wabbajack.Downloaders.IPS4OAuth2Downloader/Wabbajack.Downloaders.IPS4OAuth2Downloader.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable diff --git a/Wabbajack.Downloaders.Interfaces/Wabbajack.Downloaders.Interfaces.csproj b/Wabbajack.Downloaders.Interfaces/Wabbajack.Downloaders.Interfaces.csproj index 88869b1c..d3acee8e 100644 --- a/Wabbajack.Downloaders.Interfaces/Wabbajack.Downloaders.Interfaces.csproj +++ b/Wabbajack.Downloaders.Interfaces/Wabbajack.Downloaders.Interfaces.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable GPL-3.0-or-later $(VERSION) diff --git a/Wabbajack.Downloaders.Manual/Wabbajack.Downloaders.Manual.csproj b/Wabbajack.Downloaders.Manual/Wabbajack.Downloaders.Manual.csproj index efbf5c33..575e7e12 100644 --- a/Wabbajack.Downloaders.Manual/Wabbajack.Downloaders.Manual.csproj +++ b/Wabbajack.Downloaders.Manual/Wabbajack.Downloaders.Manual.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable enable diff --git a/Wabbajack.Downloaders.MediaFire/Wabbajack.Downloaders.MediaFire.csproj b/Wabbajack.Downloaders.MediaFire/Wabbajack.Downloaders.MediaFire.csproj index 7c3378e9..883ad2d0 100644 --- a/Wabbajack.Downloaders.MediaFire/Wabbajack.Downloaders.MediaFire.csproj +++ b/Wabbajack.Downloaders.MediaFire/Wabbajack.Downloaders.MediaFire.csproj @@ -1,13 +1,13 @@ - net6.0 + net7.0 enable - + diff --git a/Wabbajack.Downloaders.Mega/Wabbajack.Downloaders.Mega.csproj b/Wabbajack.Downloaders.Mega/Wabbajack.Downloaders.Mega.csproj index 300a2784..2c58d3a0 100644 --- a/Wabbajack.Downloaders.Mega/Wabbajack.Downloaders.Mega.csproj +++ b/Wabbajack.Downloaders.Mega/Wabbajack.Downloaders.Mega.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable diff --git a/Wabbajack.Downloaders.ModDB/Wabbajack.Downloaders.ModDB.csproj b/Wabbajack.Downloaders.ModDB/Wabbajack.Downloaders.ModDB.csproj index ed35adc1..d32eb433 100644 --- a/Wabbajack.Downloaders.ModDB/Wabbajack.Downloaders.ModDB.csproj +++ b/Wabbajack.Downloaders.ModDB/Wabbajack.Downloaders.ModDB.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable diff --git a/Wabbajack.Downloaders.Nexus/Wabbajack.Downloaders.Nexus.csproj b/Wabbajack.Downloaders.Nexus/Wabbajack.Downloaders.Nexus.csproj index 96c12049..6fc137e1 100644 --- a/Wabbajack.Downloaders.Nexus/Wabbajack.Downloaders.Nexus.csproj +++ b/Wabbajack.Downloaders.Nexus/Wabbajack.Downloaders.Nexus.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable GPL-3.0-or-later $(VERSION) diff --git a/Wabbajack.Downloaders.VerificationCache/Wabbajack.Downloaders.VerificationCache.csproj b/Wabbajack.Downloaders.VerificationCache/Wabbajack.Downloaders.VerificationCache.csproj index 775a9597..864b1a37 100644 --- a/Wabbajack.Downloaders.VerificationCache/Wabbajack.Downloaders.VerificationCache.csproj +++ b/Wabbajack.Downloaders.VerificationCache/Wabbajack.Downloaders.VerificationCache.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable enable diff --git a/Wabbajack.Downloaders.WabbajackCDN/Wabbajack.Downloaders.WabbajackCDN.csproj b/Wabbajack.Downloaders.WabbajackCDN/Wabbajack.Downloaders.WabbajackCDN.csproj index c04a827f..c9a9c634 100644 --- a/Wabbajack.Downloaders.WabbajackCDN/Wabbajack.Downloaders.WabbajackCDN.csproj +++ b/Wabbajack.Downloaders.WabbajackCDN/Wabbajack.Downloaders.WabbajackCDN.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable $(VERSION) GPL-3.0-or-later diff --git a/Wabbajack.FileExtractor.Test/Wabbajack.FileExtractor.Test.csproj b/Wabbajack.FileExtractor.Test/Wabbajack.FileExtractor.Test.csproj index 6e070afe..40378dd9 100644 --- a/Wabbajack.FileExtractor.Test/Wabbajack.FileExtractor.Test.csproj +++ b/Wabbajack.FileExtractor.Test/Wabbajack.FileExtractor.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false @@ -11,7 +11,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/Wabbajack.FileExtractor/Wabbajack.FileExtractor.csproj b/Wabbajack.FileExtractor/Wabbajack.FileExtractor.csproj index 356afd7d..358a3e0a 100644 --- a/Wabbajack.FileExtractor/Wabbajack.FileExtractor.csproj +++ b/Wabbajack.FileExtractor/Wabbajack.FileExtractor.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable $(VERSION) GPL-3.0-or-later diff --git a/Wabbajack.Hashing.PHash.Test/Wabbajack.Hashing.PHash.Test.csproj b/Wabbajack.Hashing.PHash.Test/Wabbajack.Hashing.PHash.Test.csproj index 2f5f8283..7119afd0 100644 --- a/Wabbajack.Hashing.PHash.Test/Wabbajack.Hashing.PHash.Test.csproj +++ b/Wabbajack.Hashing.PHash.Test/Wabbajack.Hashing.PHash.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false diff --git a/Wabbajack.Hashing.PHash/Wabbajack.Hashing.PHash.csproj b/Wabbajack.Hashing.PHash/Wabbajack.Hashing.PHash.csproj index 0d66a3e1..78d738ce 100644 --- a/Wabbajack.Hashing.PHash/Wabbajack.Hashing.PHash.csproj +++ b/Wabbajack.Hashing.PHash/Wabbajack.Hashing.PHash.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable $(VERSION) GPL-3.0-or-later diff --git a/Wabbajack.Hashing.xxHash64.Benchmark/Wabbajack.Hashing.xxHash64.Benchmark.csproj b/Wabbajack.Hashing.xxHash64.Benchmark/Wabbajack.Hashing.xxHash64.Benchmark.csproj index 4e9b1f49..03dff657 100644 --- a/Wabbajack.Hashing.xxHash64.Benchmark/Wabbajack.Hashing.xxHash64.Benchmark.csproj +++ b/Wabbajack.Hashing.xxHash64.Benchmark/Wabbajack.Hashing.xxHash64.Benchmark.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net7.0 Wabbajac.Hash.xxHash64.Benchmark true diff --git a/Wabbajack.Hashing.xxHash64.Test/Wabbajack.Hashing.xxHash64.Test.csproj b/Wabbajack.Hashing.xxHash64.Test/Wabbajack.Hashing.xxHash64.Test.csproj index d4523c52..204f9d5f 100644 --- a/Wabbajack.Hashing.xxHash64.Test/Wabbajack.Hashing.xxHash64.Test.csproj +++ b/Wabbajack.Hashing.xxHash64.Test/Wabbajack.Hashing.xxHash64.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false diff --git a/Wabbajack.Hashing.xxHash64/Wabbajack.Hashing.xxHash64.csproj b/Wabbajack.Hashing.xxHash64/Wabbajack.Hashing.xxHash64.csproj index f6edd4e1..f26d307e 100644 --- a/Wabbajack.Hashing.xxHash64/Wabbajack.Hashing.xxHash64.csproj +++ b/Wabbajack.Hashing.xxHash64/Wabbajack.Hashing.xxHash64.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable $(VERSION) GPL-3.0-or-later diff --git a/Wabbajack.IO.Async/Wabbajack.IO.Async.csproj b/Wabbajack.IO.Async/Wabbajack.IO.Async.csproj index eb2460e9..6836c680 100644 --- a/Wabbajack.IO.Async/Wabbajack.IO.Async.csproj +++ b/Wabbajack.IO.Async/Wabbajack.IO.Async.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable enable diff --git a/Wabbajack.Installer.Test/Wabbajack.Installer.Test.csproj b/Wabbajack.Installer.Test/Wabbajack.Installer.Test.csproj index c1dbcbe2..590be299 100644 --- a/Wabbajack.Installer.Test/Wabbajack.Installer.Test.csproj +++ b/Wabbajack.Installer.Test/Wabbajack.Installer.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false @@ -11,7 +11,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/Wabbajack.Installer/Wabbajack.Installer.csproj b/Wabbajack.Installer/Wabbajack.Installer.csproj index 845d9ca3..28277612 100644 --- a/Wabbajack.Installer/Wabbajack.Installer.csproj +++ b/Wabbajack.Installer/Wabbajack.Installer.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable $(VERSION) GPL-3.0-or-later diff --git a/Wabbajack.Launcher/ViewModels/MainWindowViewModel.cs b/Wabbajack.Launcher/ViewModels/MainWindowViewModel.cs index 5b2c514b..75472aa3 100644 --- a/Wabbajack.Launcher/ViewModels/MainWindowViewModel.cs +++ b/Wabbajack.Launcher/ViewModels/MainWindowViewModel.cs @@ -231,7 +231,7 @@ public class MainWindowViewModel : ViewModelBase ShowInCenter = true, ContentTitle = "Wabbajack Launcher: Bad startup path", ContentMessage = - "Cannot start in the root of a drive, or protected folder locations such as Downloads, Desktop etc.\nPlease move Wabbajack to another folder." + "Cannot start in the root of a drive, or protected folder locations such as Downloads, Desktop etc.\nPlease move Wabbajack to another folder, creating a new folder if necessary ( example : C:\\Wabbajack\\), outside of these locations." }); var result = await msg.Show(); Environment.Exit(1); diff --git a/Wabbajack.Launcher/Wabbajack.Launcher.csproj b/Wabbajack.Launcher/Wabbajack.Launcher.csproj index a188ab0b..a47fefab 100644 --- a/Wabbajack.Launcher/Wabbajack.Launcher.csproj +++ b/Wabbajack.Launcher/Wabbajack.Launcher.csproj @@ -16,6 +16,7 @@ Resources\Icons\wabbajack.ico + net7.0-windows @@ -30,7 +31,7 @@ - + diff --git a/Wabbajack.Networking.BethesdaNet/Wabbajack.Networking.BethesdaNet.csproj b/Wabbajack.Networking.BethesdaNet/Wabbajack.Networking.BethesdaNet.csproj index 0267a74f..68bb36ab 100644 --- a/Wabbajack.Networking.BethesdaNet/Wabbajack.Networking.BethesdaNet.csproj +++ b/Wabbajack.Networking.BethesdaNet/Wabbajack.Networking.BethesdaNet.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable enable diff --git a/Wabbajack.Networking.Discord/Wabbajack.Networking.Discord.csproj b/Wabbajack.Networking.Discord/Wabbajack.Networking.Discord.csproj index 1061d857..c9ab6aab 100644 --- a/Wabbajack.Networking.Discord/Wabbajack.Networking.Discord.csproj +++ b/Wabbajack.Networking.Discord/Wabbajack.Networking.Discord.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable GPL-3.0-or-later $(VERSION) diff --git a/Wabbajack.Networking.GitHub/Wabbajack.Networking.GitHub.csproj b/Wabbajack.Networking.GitHub/Wabbajack.Networking.GitHub.csproj index d75d9f31..40e65542 100644 --- a/Wabbajack.Networking.GitHub/Wabbajack.Networking.GitHub.csproj +++ b/Wabbajack.Networking.GitHub/Wabbajack.Networking.GitHub.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable GPL-3.0-or-later $(VERSION) diff --git a/Wabbajack.Networking.Http.Interfaces/Wabbajack.Networking.Http.Interfaces.csproj b/Wabbajack.Networking.Http.Interfaces/Wabbajack.Networking.Http.Interfaces.csproj index e9ee3e62..5037943c 100644 --- a/Wabbajack.Networking.Http.Interfaces/Wabbajack.Networking.Http.Interfaces.csproj +++ b/Wabbajack.Networking.Http.Interfaces/Wabbajack.Networking.Http.Interfaces.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable $(VERSION) GPL-3.0-or-later diff --git a/Wabbajack.Networking.Http.Test/Wabbajack.Networking.Http.Test.csproj b/Wabbajack.Networking.Http.Test/Wabbajack.Networking.Http.Test.csproj index 0aecc8b7..a20f6ab2 100644 --- a/Wabbajack.Networking.Http.Test/Wabbajack.Networking.Http.Test.csproj +++ b/Wabbajack.Networking.Http.Test/Wabbajack.Networking.Http.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable false diff --git a/Wabbajack.Networking.Http/Extensions.cs b/Wabbajack.Networking.Http/Extensions.cs index 81b751e6..eed4666b 100644 --- a/Wabbajack.Networking.Http/Extensions.cs +++ b/Wabbajack.Networking.Http/Extensions.cs @@ -10,13 +10,6 @@ namespace Wabbajack.Networking.Http; public static class Extensions { - public static HttpRequestMessage UseChromeUserAgent(this HttpRequestMessage msg) - { - msg.Headers.UserAgent.Clear(); - msg.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"); - return msg; - } - public static async Task GetJsonFromSendAsync(this HttpClient client, HttpRequestMessage msg, JsonSerializerOptions opts, CancellationToken? token = null) { diff --git a/Wabbajack.Networking.Http/ResumableDownloader.cs b/Wabbajack.Networking.Http/ResumableDownloader.cs index ca07712c..025715e4 100644 --- a/Wabbajack.Networking.Http/ResumableDownloader.cs +++ b/Wabbajack.Networking.Http/ResumableDownloader.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Downloader; using Microsoft.Extensions.Logging; +using Wabbajack.Configuration; using Wabbajack.Hashing.xxHash64; using Wabbajack.Paths; using Wabbajack.Paths.IO; @@ -20,17 +21,19 @@ internal class ResumableDownloader private readonly HttpRequestMessage _msg; private readonly AbsolutePath _outputPath; private readonly AbsolutePath _packagePath; + private readonly PerformanceSettings _performanceSettings; private readonly ILogger _logger; private CancellationToken _token; private Exception? _error; - public ResumableDownloader(HttpRequestMessage msg, AbsolutePath outputPath, IJob job, ILogger logger) + public ResumableDownloader(HttpRequestMessage msg, AbsolutePath outputPath, IJob job, PerformanceSettings performanceSettings, ILogger logger) { _job = job; _msg = msg; _outputPath = outputPath; _packagePath = outputPath.WithExtension(Extension.FromPath(".download_package")); + _performanceSettings = performanceSettings; _logger = logger; } @@ -99,8 +102,10 @@ internal class ResumableDownloader private DownloadConfiguration CreateConfiguration(HttpRequestMessage message) { + var maximumMemoryPerDownloadThreadMb = Math.Max(0, _performanceSettings.MaximumMemoryPerDownloadThreadMb); var configuration = new DownloadConfiguration { + MaximumMemoryBufferBytes = maximumMemoryPerDownloadThreadMb * 1024 * 1024, Timeout = (int)TimeSpan.FromSeconds(120).TotalMilliseconds, ReserveStorageSpaceBeforeStartingDownload = true, RequestConfiguration = new RequestConfiguration diff --git a/Wabbajack.Networking.Http/SingleThreadedDownloader.cs b/Wabbajack.Networking.Http/SingleThreadedDownloader.cs index 4790d4ac..ed88e3bb 100644 --- a/Wabbajack.Networking.Http/SingleThreadedDownloader.cs +++ b/Wabbajack.Networking.Http/SingleThreadedDownloader.cs @@ -7,6 +7,7 @@ using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using Wabbajack.Configuration; using Wabbajack.Hashing.xxHash64; using Wabbajack.Networking.Http.Interfaces; using Wabbajack.Paths; @@ -19,18 +20,20 @@ public class SingleThreadedDownloader : IHttpDownloader { private readonly HttpClient _client; private readonly ILogger _logger; + private readonly PerformanceSettings _settings; - public SingleThreadedDownloader(ILogger logger, HttpClient client) + public SingleThreadedDownloader(ILogger logger, HttpClient client, MainSettings settings) { _logger = logger; _client = client; + _settings = settings.PerformanceSettings; } public async Task Download(HttpRequestMessage message, AbsolutePath outputPath, IJob job, CancellationToken token) { Exception downloadError = null!; - var downloader = new ResumableDownloader(message, outputPath, job, _logger); + var downloader = new ResumableDownloader(message, outputPath, job, _settings, _logger); for (var i = 0; i < 3; i++) { try diff --git a/Wabbajack.Networking.Http/Wabbajack.Networking.Http.csproj b/Wabbajack.Networking.Http/Wabbajack.Networking.Http.csproj index d285e4f4..2cf94a56 100644 --- a/Wabbajack.Networking.Http/Wabbajack.Networking.Http.csproj +++ b/Wabbajack.Networking.Http/Wabbajack.Networking.Http.csproj @@ -1,18 +1,19 @@ - net6.0 + net7.0 enable GPL-3.0-or-later $(VERSION) - + + diff --git a/Wabbajack.Networking.NexusApi.Test/Wabbajack.Networking.NexusApi.Test.csproj b/Wabbajack.Networking.NexusApi.Test/Wabbajack.Networking.NexusApi.Test.csproj index 552f015c..fac1ed50 100644 --- a/Wabbajack.Networking.NexusApi.Test/Wabbajack.Networking.NexusApi.Test.csproj +++ b/Wabbajack.Networking.NexusApi.Test/Wabbajack.Networking.NexusApi.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false diff --git a/Wabbajack.Networking.NexusApi/ProxiedNexusApi.cs b/Wabbajack.Networking.NexusApi/ProxiedNexusApi.cs index 21397c0d..703dc241 100644 --- a/Wabbajack.Networking.NexusApi/ProxiedNexusApi.cs +++ b/Wabbajack.Networking.NexusApi/ProxiedNexusApi.cs @@ -8,15 +8,15 @@ using Wabbajack.DTOs; using Wabbajack.DTOs.Logins; using Wabbajack.Networking.Http.Interfaces; using Wabbajack.Networking.NexusApi.DTOs; -using Wabbajack.Networking.WabbajackClientApi; using Wabbajack.RateLimiter; +using ClientConfiguration = Wabbajack.Networking.WabbajackClientApi.Configuration; namespace Wabbajack.Networking.NexusApi; public class ProxiedNexusApi : NexusApi { private readonly ITokenProvider _apiState; - private readonly Configuration _wabbajackClientConfiguration; + private readonly ClientConfiguration _wabbajackClientConfiguration; public HashSet ProxiedEndpoints = new() { @@ -28,7 +28,7 @@ public class ProxiedNexusApi : NexusApi public ProxiedNexusApi(ITokenProvider apiKey, ILogger logger, HttpClient client, IResource limiter, ApplicationInfo appInfo, JsonSerializerOptions jsonOptions, ITokenProvider apiState, - Configuration wabbajackClientConfiguration) + ClientConfiguration wabbajackClientConfiguration) : base(apiKey, logger, client, limiter, appInfo, jsonOptions) { _apiState = apiState; diff --git a/Wabbajack.Networking.NexusApi/Wabbajack.Networking.NexusApi.csproj b/Wabbajack.Networking.NexusApi/Wabbajack.Networking.NexusApi.csproj index 05977cf3..500ad9fa 100644 --- a/Wabbajack.Networking.NexusApi/Wabbajack.Networking.NexusApi.csproj +++ b/Wabbajack.Networking.NexusApi/Wabbajack.Networking.NexusApi.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable GPL-3.0-or-later $(VERSION) @@ -12,7 +12,7 @@ - + diff --git a/Wabbajack.Networking.Steam.Test/Wabbajack.Networking.Steam.Test.csproj b/Wabbajack.Networking.Steam.Test/Wabbajack.Networking.Steam.Test.csproj index b8f20c0b..c7e6d73b 100644 --- a/Wabbajack.Networking.Steam.Test/Wabbajack.Networking.Steam.Test.csproj +++ b/Wabbajack.Networking.Steam.Test/Wabbajack.Networking.Steam.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable false @@ -12,7 +12,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/Wabbajack.Networking.Steam/Wabbajack.Networking.Steam.csproj b/Wabbajack.Networking.Steam/Wabbajack.Networking.Steam.csproj index d9364b70..ee840362 100644 --- a/Wabbajack.Networking.Steam/Wabbajack.Networking.Steam.csproj +++ b/Wabbajack.Networking.Steam/Wabbajack.Networking.Steam.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable enable diff --git a/Wabbajack.Networking.WabbajackClientApi/Wabbajack.Networking.WabbajackClientApi.csproj b/Wabbajack.Networking.WabbajackClientApi/Wabbajack.Networking.WabbajackClientApi.csproj index 7aeb859b..55712888 100644 --- a/Wabbajack.Networking.WabbajackClientApi/Wabbajack.Networking.WabbajackClientApi.csproj +++ b/Wabbajack.Networking.WabbajackClientApi/Wabbajack.Networking.WabbajackClientApi.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable $(VERSION) GPL-3.0-or-later diff --git a/Wabbajack.Paths.IO.Test/Wabbajack.Paths.IO.Test.csproj b/Wabbajack.Paths.IO.Test/Wabbajack.Paths.IO.Test.csproj index bbd2b0ea..3948bc11 100644 --- a/Wabbajack.Paths.IO.Test/Wabbajack.Paths.IO.Test.csproj +++ b/Wabbajack.Paths.IO.Test/Wabbajack.Paths.IO.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false diff --git a/Wabbajack.Paths.IO/Wabbajack.Paths.IO.csproj b/Wabbajack.Paths.IO/Wabbajack.Paths.IO.csproj index 2494c58e..0cd88c4d 100644 --- a/Wabbajack.Paths.IO/Wabbajack.Paths.IO.csproj +++ b/Wabbajack.Paths.IO/Wabbajack.Paths.IO.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable GPL-3.0-or-later $(VERSION) diff --git a/Wabbajack.Paths.Test/Wabbajack.Paths.Test.csproj b/Wabbajack.Paths.Test/Wabbajack.Paths.Test.csproj index 1415da3d..a5d4fe49 100644 --- a/Wabbajack.Paths.Test/Wabbajack.Paths.Test.csproj +++ b/Wabbajack.Paths.Test/Wabbajack.Paths.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false diff --git a/Wabbajack.Paths/Wabbajack.Paths.csproj b/Wabbajack.Paths/Wabbajack.Paths.csproj index 2502d56d..1ffbca14 100644 --- a/Wabbajack.Paths/Wabbajack.Paths.csproj +++ b/Wabbajack.Paths/Wabbajack.Paths.csproj @@ -1,6 +1,6 @@ - net6.0 + net7.0 enable GPL-3.0-or-later $(VERSION) diff --git a/Wabbajack.RateLimiter.Test/Wabbajack.RateLimiter.Test.csproj b/Wabbajack.RateLimiter.Test/Wabbajack.RateLimiter.Test.csproj index 8b16f12f..3db11fcf 100644 --- a/Wabbajack.RateLimiter.Test/Wabbajack.RateLimiter.Test.csproj +++ b/Wabbajack.RateLimiter.Test/Wabbajack.RateLimiter.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable false diff --git a/Wabbajack.RateLimiter/Wabbajack.RateLimiter.csproj b/Wabbajack.RateLimiter/Wabbajack.RateLimiter.csproj index 72d6b4a4..444af79a 100644 --- a/Wabbajack.RateLimiter/Wabbajack.RateLimiter.csproj +++ b/Wabbajack.RateLimiter/Wabbajack.RateLimiter.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable diff --git a/Wabbajack.Server.Lib/Wabbajack.Server.Lib.csproj b/Wabbajack.Server.Lib/Wabbajack.Server.Lib.csproj index d69e3e3c..03942d81 100644 --- a/Wabbajack.Server.Lib/Wabbajack.Server.Lib.csproj +++ b/Wabbajack.Server.Lib/Wabbajack.Server.Lib.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable diff --git a/Wabbajack.Server/Wabbajack.Server.csproj b/Wabbajack.Server/Wabbajack.Server.csproj index 9abb308e..c31158e1 100644 --- a/Wabbajack.Server/Wabbajack.Server.csproj +++ b/Wabbajack.Server/Wabbajack.Server.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable enable Exe diff --git a/Wabbajack.Services.OSIntegrated/ServiceExtensions.cs b/Wabbajack.Services.OSIntegrated/ServiceExtensions.cs index 3a2b41e7..d89cf4e2 100644 --- a/Wabbajack.Services.OSIntegrated/ServiceExtensions.cs +++ b/Wabbajack.Services.OSIntegrated/ServiceExtensions.cs @@ -8,7 +8,9 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Wabbajack.Common; using Wabbajack.Compiler; +using Wabbajack.Configuration; using Wabbajack.Downloaders; using Wabbajack.Downloaders.GameFile; using Wabbajack.Downloaders.VerificationCache; @@ -79,24 +81,36 @@ public static class ServiceExtensions ? new BinaryPatchCache(s.GetRequiredService>(), s.GetService()!.CreateFolder().Path) : new BinaryPatchCache(s.GetRequiredService>(),KnownFolders.WabbajackAppLocal.Combine("PatchCache"))); - + service.AddSingleton(s => { var dtos = s.GetRequiredService(); return options.UseLocalCache ? new VerificationCache(s.GetRequiredService>(), - s.GetService()!.CreateFile().Path, + s.GetService()!.CreateFile().Path, TimeSpan.FromDays(1), dtos) : new VerificationCache(s.GetRequiredService>(), - KnownFolders.WabbajackAppLocal.Combine("VerificationCacheV2.sqlite"), + KnownFolders.WabbajackAppLocal.Combine("VerificationCacheV2.sqlite"), TimeSpan.FromDays(1), dtos); }); service.AddSingleton(new ParallelOptions {MaxDegreeOfParallelism = Environment.ProcessorCount}); - Func> GetSettings(IServiceProvider provider, string name) + MainSettings GetAppSettings(IServiceProvider provider, string name) + { + var settingsManager = provider.GetRequiredService(); + var settings = Task.Run(() => settingsManager.Load(name)).Result; + if (settings.Upgrade()) + { + settingsManager.Save(MainSettings.SettingsFileName, settings).FireAndForget(); + } + + return settings; + } + + Func> GetResourceSettings(IServiceProvider provider, string name) { return async () => { @@ -104,9 +118,9 @@ public static class ServiceExtensions return ((int) s.MaxTasks, s.MaxThroughput); }; } - + // Settings - + service.AddSingleton(s => new Configuration { EncryptedDataLocation = KnownFolders.WabbajackAppLocal.Combine("encrypted"), @@ -118,26 +132,27 @@ public static class ServiceExtensions service.AddSingleton(); service.AddSingleton(); - + service.AddSingleton(s => GetAppSettings(s, MainSettings.SettingsFileName)); + // Resources service.AddAllSingleton>(s => - new Resource("Downloads", GetSettings(s, "Downloads"), s.GetRequiredService())); + new Resource("Downloads", GetResourceSettings(s, "Downloads"), s.GetRequiredService())); - service.AddAllSingleton>(s => new Resource("Web Requests", GetSettings(s, "Web Requests"), s.GetRequiredService())); - service.AddAllSingleton>(s => new Resource("VFS", GetSettings(s, "VFS"), s.GetRequiredService())); + service.AddAllSingleton>(s => new Resource("Web Requests", GetResourceSettings(s, "Web Requests"), s.GetRequiredService())); + service.AddAllSingleton>(s => new Resource("VFS", GetResourceSettings(s, "VFS"), s.GetRequiredService())); service.AddAllSingleton>(s => - new Resource("File Hashing", GetSettings(s, "File Hashing"), s.GetRequiredService())); + new Resource("File Hashing", GetResourceSettings(s, "File Hashing"), s.GetRequiredService())); service.AddAllSingleton>(s => - new Resource("Wabbajack Client", GetSettings(s, "Wabbajack Client"), s.GetRequiredService())); + new Resource("Wabbajack Client", GetResourceSettings(s, "Wabbajack Client"), s.GetRequiredService())); service.AddAllSingleton>(s => - new Resource("File Extractor", GetSettings(s, "File Extractor"), s.GetRequiredService())); + new Resource("File Extractor", GetResourceSettings(s, "File Extractor"), s.GetRequiredService())); service.AddAllSingleton>(s => - new Resource("Compiler", GetSettings(s, "Compiler"), s.GetRequiredService())); + new Resource("Compiler", GetResourceSettings(s, "Compiler"), s.GetRequiredService())); service.AddAllSingleton>(s => - new Resource("Installer", GetSettings(s, "Installer"), s.GetRequiredService())); + new Resource("Installer", GetResourceSettings(s, "Installer"), s.GetRequiredService())); service.AddAllSingleton>(s => new Resource("User Intervention", 1, token: s.GetRequiredService())); @@ -154,7 +169,7 @@ public static class ServiceExtensions service.AddAllSingleton(); service.AddSteam(); - + service.AddSingleton(); service.AddSingleton(); service.AddBethesdaNet(); @@ -186,11 +201,11 @@ public static class ServiceExtensions service.AddAllSingleton(); else service.AddAllSingleton(); - + // ImageLoader if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) service.AddSingleton(); - else + else service.AddSingleton(); // Installer/Compiler Configuration @@ -214,9 +229,9 @@ public static class ServiceExtensions OSVersion = Environment.OSVersion.VersionString, Version = version }); - - + + return service; } @@ -224,7 +239,7 @@ public static class ServiceExtensions { // Get directories first and cache them, this freezes the directories were looking at // so any new ones don't show up in the middle of our deletes. - + var dirs = path.EnumerateDirectories().ToList(); var processIds = Process.GetProcesses().Select(p => p.Id).ToHashSet(); foreach (var dir in dirs) @@ -232,7 +247,7 @@ public static class ServiceExtensions var name = dir.FileName.ToString().Split("_"); if (!int.TryParse(name[0], out var processId)) continue; if (processIds.Contains(processId)) continue; - + try { dir.DeleteDirectory(); @@ -242,7 +257,7 @@ public static class ServiceExtensions // ignored } } - + } public class OSIntegratedOptions diff --git a/Wabbajack.Services.OSIntegrated/Wabbajack.Services.OSIntegrated.csproj b/Wabbajack.Services.OSIntegrated/Wabbajack.Services.OSIntegrated.csproj index b2cfce82..2223ea6d 100644 --- a/Wabbajack.Services.OSIntegrated/Wabbajack.Services.OSIntegrated.csproj +++ b/Wabbajack.Services.OSIntegrated/Wabbajack.Services.OSIntegrated.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable $(VERSION) GPL-3.0-or-later @@ -17,7 +17,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Wabbajack.VFS.Interfaces/Wabbajack.VFS.Interfaces.csproj b/Wabbajack.VFS.Interfaces/Wabbajack.VFS.Interfaces.csproj index bf68d60e..5b854cb5 100644 --- a/Wabbajack.VFS.Interfaces/Wabbajack.VFS.Interfaces.csproj +++ b/Wabbajack.VFS.Interfaces/Wabbajack.VFS.Interfaces.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable enable diff --git a/Wabbajack.VFS.Test/Wabbajack.VFS.Test.csproj b/Wabbajack.VFS.Test/Wabbajack.VFS.Test.csproj index ebcd2790..29e3421c 100644 --- a/Wabbajack.VFS.Test/Wabbajack.VFS.Test.csproj +++ b/Wabbajack.VFS.Test/Wabbajack.VFS.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false @@ -11,7 +11,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/Wabbajack.VFS/Wabbajack.VFS.csproj b/Wabbajack.VFS/Wabbajack.VFS.csproj index 07ec317f..a4501f7c 100644 --- a/Wabbajack.VFS/Wabbajack.VFS.csproj +++ b/Wabbajack.VFS/Wabbajack.VFS.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable $(VERSION) GPL-3.0-or-later diff --git a/Wabbajack.sln b/Wabbajack.sln index 33a2724b..1800043e 100644 --- a/Wabbajack.sln +++ b/Wabbajack.sln @@ -147,6 +147,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.CLI.Builder", "Wa EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Downloaders.VerificationCache", "Wabbajack.Downloaders.VerificationCache\Wabbajack.Downloaders.VerificationCache.csproj", "{D9560C73-4E58-4463-9DB9-D06491E0E1C8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Configuration", "Wabbajack.Configuration\Wabbajack.Configuration.csproj", "{E7CDACA6-D3FF-4CF6-8EF8-05FCD27F6FBE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -401,6 +403,10 @@ Global {D9560C73-4E58-4463-9DB9-D06491E0E1C8}.Debug|Any CPU.Build.0 = Debug|Any CPU {D9560C73-4E58-4463-9DB9-D06491E0E1C8}.Release|Any CPU.ActiveCfg = Release|Any CPU {D9560C73-4E58-4463-9DB9-D06491E0E1C8}.Release|Any CPU.Build.0 = Release|Any CPU + {E7CDACA6-D3FF-4CF6-8EF8-05FCD27F6FBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E7CDACA6-D3FF-4CF6-8EF8-05FCD27F6FBE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E7CDACA6-D3FF-4CF6-8EF8-05FCD27F6FBE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E7CDACA6-D3FF-4CF6-8EF8-05FCD27F6FBE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE