mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Settings manager
This commit is contained in:
parent
f4f4b80968
commit
51015eaa81
@ -9,6 +9,6 @@
|
|||||||
<Button x:Name="DeleteButton">
|
<Button x:Name="DeleteButton">
|
||||||
<i:MaterialIcon Kind="MinusCircle"></i:MaterialIcon>
|
<i:MaterialIcon Kind="MinusCircle"></i:MaterialIcon>
|
||||||
</Button>
|
</Button>
|
||||||
<TextBlock x:Name="Text"></TextBlock>
|
<TextBlock x:Name="Text" VerticalAlignment="Center"></TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</UserControl>
|
</UserControl>
|
62
Wabbajack.App/Models/SettingsManager.cs
Normal file
62
Wabbajack.App/Models/SettingsManager.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Wabbajack.Common;
|
||||||
|
using Wabbajack.DTOs.JsonConverters;
|
||||||
|
using Wabbajack.Paths;
|
||||||
|
using Wabbajack.Paths.IO;
|
||||||
|
|
||||||
|
namespace Wabbajack.App.Models;
|
||||||
|
|
||||||
|
public class SettingsManager
|
||||||
|
{
|
||||||
|
private readonly Configuration _configuration;
|
||||||
|
private readonly DTOSerializer _dtos;
|
||||||
|
private readonly ILogger<SettingsManager> _logger;
|
||||||
|
|
||||||
|
public SettingsManager(ILogger<SettingsManager> logger, Configuration configuration, DTOSerializer dtos)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_dtos = dtos;
|
||||||
|
_configuration = configuration;
|
||||||
|
_configuration.SavedSettingsLocation.CreateDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
private AbsolutePath GetPath(string key) => _configuration.SavedSettingsLocation.Combine(key).WithExtension(Ext.Json);
|
||||||
|
|
||||||
|
public async Task Save<T>(string key, T value)
|
||||||
|
{
|
||||||
|
var tmp = GetPath(key).WithExtension(Ext.Temp);
|
||||||
|
await using (var s = tmp.Open(FileMode.Create, FileAccess.Write))
|
||||||
|
{
|
||||||
|
await JsonSerializer.SerializeAsync(s, value, _dtos.Options);
|
||||||
|
}
|
||||||
|
await tmp.MoveToAsync(GetPath(key), true, CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<T> Load<T>(string key)
|
||||||
|
where T : new()
|
||||||
|
{
|
||||||
|
var path = GetPath(key);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (path.FileExists())
|
||||||
|
{
|
||||||
|
await using (var s = path.Open(FileMode.Create, FileAccess.Write))
|
||||||
|
{
|
||||||
|
await JsonSerializer.DeserializeAsync<T>(s, _dtos.Options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Loading settings {Key}", key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new T();
|
||||||
|
}
|
||||||
|
}
|
@ -15,8 +15,8 @@
|
|||||||
<controls:FileSelectionBox Grid.Column="1" Grid.Row="1" x:Name="SettingsFile"
|
<controls:FileSelectionBox Grid.Column="1" Grid.Row="1" x:Name="SettingsFile"
|
||||||
AllowedExtensions=".txt|.json">
|
AllowedExtensions=".txt|.json">
|
||||||
</controls:FileSelectionBox>
|
</controls:FileSelectionBox>
|
||||||
<Label Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right">Mod List Folder:</Label>
|
<Label Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right">Source:</Label>
|
||||||
<controls:FileSelectionBox Grid.Column="1" Grid.Row="2" x:Name="BaseFolder" SelectFolder="True"></controls:FileSelectionBox>
|
<controls:FileSelectionBox Grid.Column="1" Grid.Row="2" x:Name="Source" SelectFolder="True"></controls:FileSelectionBox>
|
||||||
<Label Grid.Column="0" Grid.Row="3" HorizontalAlignment="Right">Downloads Folder:</Label>
|
<Label Grid.Column="0" Grid.Row="3" HorizontalAlignment="Right">Downloads Folder:</Label>
|
||||||
<controls:FileSelectionBox Grid.Column="1" Grid.Row="3" x:Name="DownloadsFolder" SelectFolder="True"></controls:FileSelectionBox>
|
<controls:FileSelectionBox Grid.Column="1" Grid.Row="3" x:Name="DownloadsFolder" SelectFolder="True"></controls:FileSelectionBox>
|
||||||
<Label Grid.Column="0" Grid.Row="4" HorizontalAlignment="Right">Base Game:</Label>
|
<Label Grid.Column="0" Grid.Row="4" HorizontalAlignment="Right">Base Game:</Label>
|
||||||
@ -51,8 +51,11 @@
|
|||||||
|
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid ColumnDefinitions="*, Auto" Grid.Row="2">
|
<Grid ColumnDefinitions="*, Auto, Auto" Grid.Row="2">
|
||||||
<Button Grid.Column="1" x:Name="StartCompilation">
|
<Button Grid.Column="1" x:Name="InferSettings" Click="InferSettings_OnClick">
|
||||||
|
<TextBlock>Infer Settings</TextBlock>
|
||||||
|
</Button>
|
||||||
|
<Button Grid.Column="2" x:Name="StartCompilation">
|
||||||
<TextBlock>Start Compilation</TextBlock>
|
<TextBlock>Start Compilation</TextBlock>
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Interactivity;
|
||||||
|
using Avalonia.Threading;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using Wabbajack.App.Controls;
|
using Wabbajack.App.Controls;
|
||||||
using Wabbajack.App.Views;
|
using Wabbajack.App.Views;
|
||||||
@ -20,12 +23,18 @@ namespace Wabbajack.App.Screens
|
|||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
this.Bind(ViewModel, vm => vm.BasePath, view => view.BaseFolder.SelectedPath)
|
this.Bind(ViewModel, vm => vm.SettingsFile, view => view.SettingsFile.SelectedPath)
|
||||||
|
.DisposeWith(disposables);
|
||||||
|
|
||||||
|
this.Bind(ViewModel, vm => vm.Title, view => view.Title.Text)
|
||||||
.DisposeWith(disposables);
|
.DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.SettingsFile, view => view.SettingsFile.SelectedPath)
|
this.Bind(ViewModel, vm => vm.SettingsFile, view => view.SettingsFile.SelectedPath)
|
||||||
.DisposeWith(disposables);
|
.DisposeWith(disposables);
|
||||||
|
|
||||||
|
this.Bind(ViewModel, vm => vm.Source, view => view.Source.SelectedPath)
|
||||||
|
.DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.Downloads, view => view.DownloadsFolder.SelectedPath)
|
this.Bind(ViewModel, vm => vm.Downloads, view => view.DownloadsFolder.SelectedPath)
|
||||||
.DisposeWith(disposables);
|
.DisposeWith(disposables);
|
||||||
|
|
||||||
@ -61,5 +70,21 @@ namespace Wabbajack.App.Screens
|
|||||||
if (!string.IsNullOrWhiteSpace(result))
|
if (!string.IsNullOrWhiteSpace(result))
|
||||||
ViewModel!.AddAlwaysExcluded(result.ToAbsolutePath());
|
ViewModel!.AddAlwaysExcluded(result.ToAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InferSettings_OnClick(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
var dialog = new OpenFileDialog()
|
||||||
|
{
|
||||||
|
Title = "Select a modlist.txt file",
|
||||||
|
Filters = new List<FileDialogFilter> { new() {Extensions = new List<string> {"txt"}, Name = "modlist.txt"}},
|
||||||
|
AllowMultiple = false
|
||||||
|
};
|
||||||
|
var result = await dialog.ShowAsync(App.MainWindow);
|
||||||
|
if (result is { Length: > 0 })
|
||||||
|
await ViewModel!.InferSettingsFromModlistTxt(result.First().ToAbsolutePath());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Avalonia.Controls.Mixins;
|
using Avalonia.Controls.Mixins;
|
||||||
using DynamicData;
|
using DynamicData;
|
||||||
@ -10,10 +13,12 @@ using ReactiveUI;
|
|||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using Wabbajack.App.Extensions;
|
using Wabbajack.App.Extensions;
|
||||||
using Wabbajack.App.Messages;
|
using Wabbajack.App.Messages;
|
||||||
|
using Wabbajack.App.Models;
|
||||||
using Wabbajack.App.ViewModels;
|
using Wabbajack.App.ViewModels;
|
||||||
using Wabbajack.Common;
|
using Wabbajack.Common;
|
||||||
using Wabbajack.Compiler;
|
using Wabbajack.Compiler;
|
||||||
using Wabbajack.DTOs;
|
using Wabbajack.DTOs;
|
||||||
|
using Wabbajack.DTOs.JsonConverters;
|
||||||
using Wabbajack.Installer;
|
using Wabbajack.Installer;
|
||||||
using Wabbajack.Paths;
|
using Wabbajack.Paths;
|
||||||
using Wabbajack.Paths.IO;
|
using Wabbajack.Paths.IO;
|
||||||
@ -23,6 +28,12 @@ namespace Wabbajack.App.Screens;
|
|||||||
|
|
||||||
public class CompilerConfigurationViewModel : ViewModelBase, IReceiverMarker
|
public class CompilerConfigurationViewModel : ViewModelBase, IReceiverMarker
|
||||||
{
|
{
|
||||||
|
private readonly DTOSerializer _dtos;
|
||||||
|
private readonly SettingsManager _settingsManager;
|
||||||
|
|
||||||
|
[Reactive]
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
[Reactive]
|
[Reactive]
|
||||||
public AbsolutePath SettingsFile { get; set; }
|
public AbsolutePath SettingsFile { get; set; }
|
||||||
|
|
||||||
@ -33,7 +44,7 @@ public class CompilerConfigurationViewModel : ViewModelBase, IReceiverMarker
|
|||||||
public GameMetaData BaseGame { get; set; }
|
public GameMetaData BaseGame { get; set; }
|
||||||
|
|
||||||
[Reactive]
|
[Reactive]
|
||||||
public AbsolutePath BasePath { get; set; }
|
public AbsolutePath Source { get; set; }
|
||||||
|
|
||||||
[Reactive]
|
[Reactive]
|
||||||
public AbsolutePath GamePath { get; set; }
|
public AbsolutePath GamePath { get; set; }
|
||||||
@ -53,96 +64,66 @@ public class CompilerConfigurationViewModel : ViewModelBase, IReceiverMarker
|
|||||||
[Reactive]
|
[Reactive]
|
||||||
public IEnumerable<RelativePath> AlwaysEnabled { get; set; } = Array.Empty<RelativePath>();
|
public IEnumerable<RelativePath> AlwaysEnabled { get; set; } = Array.Empty<RelativePath>();
|
||||||
|
|
||||||
|
public AbsolutePath SettingsOutputLocation => Source.Combine(Title).WithExtension(IsMO2Compilation ? Ext.MO2CompilerSettings : Ext.CompilerSettings);
|
||||||
|
|
||||||
public CompilerConfigurationViewModel()
|
[Reactive]
|
||||||
|
public bool IsMO2Compilation { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public CompilerConfigurationViewModel(DTOSerializer dtos, SettingsManager settingsManager)
|
||||||
{
|
{
|
||||||
|
_settingsManager = settingsManager;
|
||||||
|
_dtos = dtos;
|
||||||
Activator = new ViewModelActivator();
|
Activator = new ViewModelActivator();
|
||||||
|
|
||||||
AllGames = GameRegistry.Games.Values.ToArray();
|
AllGames = GameRegistry.Games.Values.ToArray();
|
||||||
|
|
||||||
StartCompilation = ReactiveCommand.Create(() => BeginCompilation());
|
StartCompilation = ReactiveCommand.Create(() => BeginCompilation().FireAndForget());
|
||||||
|
|
||||||
OutputFolder = KnownFolders.EntryPoint;
|
OutputFolder = KnownFolders.EntryPoint;
|
||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated((CompositeDisposable disposables) =>
|
||||||
{
|
{
|
||||||
var tuples = this.WhenAnyValue(vm => vm.SettingsFile)
|
LoadLastCompilation().FireAndForget();
|
||||||
.Where(file => file != default)
|
|
||||||
.SelectAsync(disposables, InterpretSettingsFile)
|
|
||||||
.Where(t => t != default)
|
|
||||||
.ObserveOn(RxApp.MainThreadScheduler);
|
|
||||||
|
|
||||||
tuples.Select(t => t.Downloads)
|
|
||||||
.BindTo(this, vm => vm.Downloads)
|
|
||||||
.DisposeWith(disposables);
|
|
||||||
|
|
||||||
tuples.Select(t => t.Root)
|
|
||||||
.BindTo(this, vm => vm.BasePath)
|
|
||||||
.DisposeWith(disposables);
|
|
||||||
|
|
||||||
tuples.Select(t => t.Game)
|
|
||||||
.BindTo(this, vm => vm.BaseGame)
|
|
||||||
.DisposeWith(disposables);
|
|
||||||
|
|
||||||
tuples.Select(t => t.SelectedProfile)
|
|
||||||
.BindTo(this, vm => vm.SelectedProfile)
|
|
||||||
.DisposeWith(disposables);
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BeginCompilation()
|
private async Task LoadLastCompilation()
|
||||||
{
|
{
|
||||||
var settings = new MO2CompilerSettings
|
var location = await _settingsManager.Load<AbsolutePath>("last_compilation");
|
||||||
|
if (location == default) return;
|
||||||
|
if (location.FileExists()) await LoadSettings(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task BeginCompilation()
|
||||||
|
{
|
||||||
|
var settings = GetSettings();
|
||||||
|
await SaveSettingsFile();
|
||||||
|
await _settingsManager.Save("last_compilation", SettingsOutputLocation);
|
||||||
|
|
||||||
|
MessageBus.Instance.Send(new StartCompilation(settings));
|
||||||
|
MessageBus.Instance.Send(new NavigateTo(typeof(CompilationViewModel)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private CompilerSettings GetSettings()
|
||||||
|
{
|
||||||
|
return new MO2CompilerSettings
|
||||||
{
|
{
|
||||||
Downloads = Downloads,
|
Downloads = Downloads,
|
||||||
Source = BasePath,
|
Source = Source,
|
||||||
Game = BaseGame.Game,
|
Game = BaseGame.Game,
|
||||||
Profile = SelectedProfile,
|
Profile = SelectedProfile,
|
||||||
UseGamePaths = true,
|
UseGamePaths = true,
|
||||||
OutputFile = OutputFolder.Combine(SelectedProfile).WithExtension(Ext.Wabbajack),
|
OutputFile = OutputFolder.Combine(SelectedProfile).WithExtension(Ext.Wabbajack),
|
||||||
AlwaysEnabled = AlwaysEnabled.ToArray()
|
AlwaysEnabled = AlwaysEnabled.ToArray()
|
||||||
};
|
};
|
||||||
|
|
||||||
MessageBus.Instance.Send(new StartCompilation(settings));
|
|
||||||
MessageBus.Instance.Send(new NavigateTo(typeof(CompilationViewModel)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async ValueTask<(AbsolutePath Root, AbsolutePath Downloads, AbsolutePath Settings, GameMetaData Game, string SelectedProfile)>
|
|
||||||
InterpretSettingsFile(AbsolutePath settingsFile)
|
|
||||||
{
|
|
||||||
if (settingsFile.FileName == "modlist.txt".ToRelativePath() && settingsFile.Depth > 3)
|
|
||||||
{
|
|
||||||
var mo2Folder = settingsFile.Parent.Parent.Parent;
|
|
||||||
var compilerSettingsFile = settingsFile.Parent.Combine(Consts.CompilerSettings);
|
|
||||||
var mo2Ini = mo2Folder.Combine(Consts.MO2IniName);
|
|
||||||
if (mo2Ini.FileExists())
|
|
||||||
{
|
|
||||||
var iniData = mo2Ini.LoadIniFile();
|
|
||||||
|
|
||||||
var general = iniData["General"];
|
|
||||||
|
|
||||||
var game = GameRegistry.GetByFuzzyName(general["gameName"].FromMO2Ini());
|
|
||||||
|
|
||||||
var selectedProfile = general["selected_profile"].FromMO2Ini();
|
|
||||||
var gamePath = general["gamePath"].FromMO2Ini().ToAbsolutePath();
|
|
||||||
|
|
||||||
var settings = iniData["Settings"];
|
|
||||||
var downloadFolder = settings["download_directory"].FromMO2Ini().ToAbsolutePath();
|
|
||||||
|
|
||||||
|
|
||||||
return (mo2Folder, downloadFolder, compilerSettingsFile, game, selectedProfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return default;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AddAlwaysExcluded(AbsolutePath path)
|
public bool AddAlwaysExcluded(AbsolutePath path)
|
||||||
{
|
{
|
||||||
if (!path.InFolder(BasePath)) return false;
|
if (!path.InFolder(Source)) return false;
|
||||||
var relative = path.RelativeTo(BasePath);
|
var relative = path.RelativeTo(Source);
|
||||||
AlwaysEnabled = AlwaysEnabled.Append(relative).Distinct().ToArray();
|
AlwaysEnabled = AlwaysEnabled.Append(relative).Distinct().ToArray();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -152,4 +133,89 @@ public class CompilerConfigurationViewModel : ViewModelBase, IReceiverMarker
|
|||||||
AlwaysEnabled = AlwaysEnabled.Where(p => p != path).ToArray();
|
AlwaysEnabled = AlwaysEnabled.Where(p => p != path).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task InferSettingsFromModlistTxt(AbsolutePath settingsFile)
|
||||||
|
{
|
||||||
|
if (settingsFile.FileName == "modlist.txt".ToRelativePath() && settingsFile.Depth > 3)
|
||||||
|
{
|
||||||
|
var mo2Folder = settingsFile.Parent.Parent.Parent;
|
||||||
|
var mo2Ini = mo2Folder.Combine(Consts.MO2IniName);
|
||||||
|
if (mo2Ini.FileExists())
|
||||||
|
{
|
||||||
|
var iniData = mo2Ini.LoadIniFile();
|
||||||
|
|
||||||
|
var general = iniData["General"];
|
||||||
|
|
||||||
|
BaseGame = GameRegistry.GetByFuzzyName(general["gameName"].FromMO2Ini());
|
||||||
|
Source = mo2Folder;
|
||||||
|
|
||||||
|
SelectedProfile = general["selected_profile"].FromMO2Ini();
|
||||||
|
GamePath = general["gamePath"].FromMO2Ini().ToAbsolutePath();
|
||||||
|
Title = SelectedProfile;
|
||||||
|
|
||||||
|
var settings = iniData["Settings"];
|
||||||
|
Downloads = settings["download_directory"].FromMO2Ini().ToAbsolutePath();
|
||||||
|
IsMO2Compilation = true;
|
||||||
|
|
||||||
|
|
||||||
|
// Find Always Enabled mods
|
||||||
|
foreach (var modFolder in mo2Folder.Combine("mods").EnumerateDirectories())
|
||||||
|
{
|
||||||
|
var iniFile = modFolder.Combine("meta.ini");
|
||||||
|
if (!iniFile.FileExists()) continue;
|
||||||
|
|
||||||
|
var data = iniFile.LoadIniFile();
|
||||||
|
var generalModData = data["General"];
|
||||||
|
if ((generalModData["notes"]?.Contains("WABBAJACK_ALWAYS_ENABLE") ?? false) ||
|
||||||
|
(generalModData["comments"]?.Contains("WABBAJACK_ALWAYS_ENABLE") ?? false))
|
||||||
|
{
|
||||||
|
AlwaysEnabled = AlwaysEnabled.Append(modFolder.RelativeTo(mo2Folder)).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mo2Folder.Depth > 1)
|
||||||
|
OutputFolder = mo2Folder.Parent;
|
||||||
|
|
||||||
|
await SaveSettingsFile();
|
||||||
|
SettingsFile = SettingsOutputLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SaveSettingsFile()
|
||||||
|
{
|
||||||
|
await using var st = SettingsOutputLocation.Open(FileMode.Create, FileAccess.Write, FileShare.None);
|
||||||
|
if (IsMO2Compilation)
|
||||||
|
await JsonSerializer.SerializeAsync(st, (MO2CompilerSettings)GetSettings(), _dtos.Options);
|
||||||
|
else
|
||||||
|
await JsonSerializer.SerializeAsync(st, GetSettings(), _dtos.Options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task LoadSettings(AbsolutePath path)
|
||||||
|
{
|
||||||
|
CompilerSettings s;
|
||||||
|
if (path.Extension == Ext.MO2CompilerSettings)
|
||||||
|
{
|
||||||
|
var mo2 = await LoadSettingsFile<MO2CompilerSettings>(path);
|
||||||
|
AlwaysEnabled = mo2.AlwaysEnabled;
|
||||||
|
SelectedProfile = mo2.Profile;
|
||||||
|
s = mo2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
Source = s.Source;
|
||||||
|
Downloads = s.Downloads;
|
||||||
|
OutputFolder = s.OutputFile.Depth > 1 ? s.OutputFile.Parent : s.OutputFile;
|
||||||
|
BaseGame = s.Game.MetaData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<T> LoadSettingsFile<T>(AbsolutePath path)
|
||||||
|
{
|
||||||
|
await using var st = path.Open(FileMode.Open);
|
||||||
|
return (await JsonSerializer.DeserializeAsync<T>(st, _dtos.Options))!;
|
||||||
|
}
|
||||||
}
|
}
|
@ -92,6 +92,8 @@ namespace Wabbajack.App
|
|||||||
SavedSettingsLocation = KnownFolders.WabbajackAppLocal.Combine("saved_settings")
|
SavedSettingsLocation = KnownFolders.WabbajackAppLocal.Combine("saved_settings")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddSingleton<SettingsManager>();
|
||||||
|
|
||||||
services.AddSingleton(s =>
|
services.AddSingleton(s =>
|
||||||
{
|
{
|
||||||
App.FrameworkInitialized += App_FrameworkInitialized;
|
App.FrameworkInitialized += App_FrameworkInitialized;
|
||||||
|
@ -20,5 +20,8 @@ namespace Wabbajack.Common
|
|||||||
public static Extension Json = new(".json");
|
public static Extension Json = new(".json");
|
||||||
public static Extension Md = new(".md");
|
public static Extension Md = new(".md");
|
||||||
public static Extension MetaData = new(".metadata");
|
public static Extension MetaData = new(".metadata");
|
||||||
|
public static Extension CompilerSettings = new(".compiler_settings");
|
||||||
|
public static Extension MO2CompilerSettings = new (".mo2_compiler_settings");
|
||||||
|
public static Extension Temp = new(".temp");
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,7 +25,7 @@ namespace Wabbajack.Compiler.CompilationSteps
|
|||||||
.SelectMany(p => _mo2Compiler._settings.Source.Combine("profiles", p, "modlist.txt").ReadAllLines())
|
.SelectMany(p => _mo2Compiler._settings.Source.Combine("profiles", p, "modlist.txt").ReadAllLines())
|
||||||
.Where(line => line.StartsWith("+") || line.EndsWith("_separator"))
|
.Where(line => line.StartsWith("+") || line.EndsWith("_separator"))
|
||||||
.Select(line => line[1..].ToRelativePath().RelativeTo(_mo2Compiler.MO2ModsFolder))
|
.Select(line => line[1..].ToRelativePath().RelativeTo(_mo2Compiler.MO2ModsFolder))
|
||||||
//.Concat(alwaysEnabled)
|
.Concat(_mo2Compiler.Mo2Settings.AlwaysEnabled.Select(r => r.RelativeTo(_mo2Compiler.Settings.Source)))
|
||||||
//.Except(alwaysDisabled)
|
//.Except(alwaysDisabled)
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ namespace Wabbajack.Compiler
|
|||||||
{
|
{
|
||||||
public class MO2Compiler : ACompiler
|
public class MO2Compiler : ACompiler
|
||||||
{
|
{
|
||||||
private MO2CompilerSettings _mo2Settings => (MO2CompilerSettings)Settings;
|
public MO2CompilerSettings Mo2Settings => (MO2CompilerSettings)Settings;
|
||||||
|
|
||||||
public MO2Compiler(ILogger<MO2Compiler> logger, FileExtractor.FileExtractor extractor, FileHashCache hashCache, Context vfs,
|
public MO2Compiler(ILogger<MO2Compiler> logger, FileExtractor.FileExtractor extractor, FileHashCache hashCache, Context vfs,
|
||||||
TemporaryFileManager manager, MO2CompilerSettings settings, ParallelOptions parallelOptions, DownloadDispatcher dispatcher,
|
TemporaryFileManager manager, MO2CompilerSettings settings, ParallelOptions parallelOptions, DownloadDispatcher dispatcher,
|
||||||
@ -31,12 +31,12 @@ namespace Wabbajack.Compiler
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbsolutePath MO2ModsFolder => _settings.Source.Combine(Consts.MO2ModFolderName);
|
public AbsolutePath MO2ModsFolder => Settings.Source.Combine(Consts.MO2ModFolderName);
|
||||||
|
|
||||||
|
|
||||||
public IniData MO2Ini { get; }
|
public IniData MO2Ini { get; }
|
||||||
|
|
||||||
public AbsolutePath MO2ProfileDir => _settings.Source.Combine(Consts.MO2Profiles, _mo2Settings.Profile);
|
public AbsolutePath MO2ProfileDir => Settings.Source.Combine(Consts.MO2Profiles, Mo2Settings.Profile);
|
||||||
|
|
||||||
public ConcurrentBag<Directive> ExtraFiles { get; private set; } = new();
|
public ConcurrentBag<Directive> ExtraFiles { get; private set; } = new();
|
||||||
public Dictionary<AbsolutePath, IniData> ModInis { get; set; } = new();
|
public Dictionary<AbsolutePath, IniData> ModInis { get; set; } = new();
|
||||||
@ -47,19 +47,19 @@ namespace Wabbajack.Compiler
|
|||||||
|
|
||||||
public override async Task<bool> Begin(CancellationToken token)
|
public override async Task<bool> Begin(CancellationToken token)
|
||||||
{
|
{
|
||||||
await _wjClient.SendMetric("begin_compiling", _mo2Settings.Profile);
|
await _wjClient.SendMetric("begin_compiling", Mo2Settings.Profile);
|
||||||
|
|
||||||
var roots = new List<AbsolutePath> {_settings.Source, _settings.Downloads};
|
var roots = new List<AbsolutePath> {Settings.Source, Settings.Downloads};
|
||||||
roots.AddRange(_settings.OtherGames.Append(_settings.Game).Select(g => _locator.GameLocation(g)));
|
roots.AddRange(Settings.OtherGames.Append(Settings.Game).Select(g => _locator.GameLocation(g)));
|
||||||
|
|
||||||
await _vfs.AddRoots(roots, token);
|
await _vfs.AddRoots(roots, token);
|
||||||
|
|
||||||
await InferMetas(token);
|
await InferMetas(token);
|
||||||
|
|
||||||
await _vfs.AddRoot(_settings.Downloads, token);
|
await _vfs.AddRoot(Settings.Downloads, token);
|
||||||
|
|
||||||
// Find all Downloads
|
// Find all Downloads
|
||||||
IndexedArchives = await _settings.Downloads.EnumerateFiles()
|
IndexedArchives = await Settings.Downloads.EnumerateFiles()
|
||||||
.Where(f => f.WithExtension(Ext.Meta).FileExists())
|
.Where(f => f.WithExtension(Ext.Meta).FileExists())
|
||||||
.PMap(_parallelOptions,
|
.PMap(_parallelOptions,
|
||||||
async f => new IndexedArchive(_vfs.Index.ByRootPath[f])
|
async f => new IndexedArchive(_vfs.Index.ByRootPath[f])
|
||||||
@ -77,9 +77,9 @@ namespace Wabbajack.Compiler
|
|||||||
await CleanInvalidArchivesAndFillState();
|
await CleanInvalidArchivesAndFillState();
|
||||||
|
|
||||||
|
|
||||||
var mo2Files = _settings.Source.EnumerateFiles()
|
var mo2Files = Settings.Source.EnumerateFiles()
|
||||||
.Where(p => p.FileExists())
|
.Where(p => p.FileExists())
|
||||||
.Select(p => new RawSourceFile(_vfs.Index.ByRootPath[p], p.RelativeTo(_settings.Source)));
|
.Select(p => new RawSourceFile(_vfs.Index.ByRootPath[p], p.RelativeTo(Settings.Source)));
|
||||||
|
|
||||||
// If Game Folder Files exists, ignore the game folder
|
// If Game Folder Files exists, ignore the game folder
|
||||||
IndexedFiles = IndexedArchives.SelectMany(f => f.File.ThisAndAllChildren)
|
IndexedFiles = IndexedArchives.SelectMany(f => f.File.ThisAndAllChildren)
|
||||||
@ -101,7 +101,7 @@ namespace Wabbajack.Compiler
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModInis = _settings.Source.Combine(Consts.MO2ModFolderName)
|
ModInis = Settings.Source.Combine(Consts.MO2ModFolderName)
|
||||||
.EnumerateDirectories()
|
.EnumerateDirectories()
|
||||||
.Select(f =>
|
.Select(f =>
|
||||||
{
|
{
|
||||||
@ -147,18 +147,18 @@ namespace Wabbajack.Compiler
|
|||||||
|
|
||||||
ModList = new ModList
|
ModList = new ModList
|
||||||
{
|
{
|
||||||
GameType = _settings.Game,
|
GameType = Settings.Game,
|
||||||
WabbajackVersion = Consts.CurrentMinimumWabbajackVersion,
|
WabbajackVersion = Consts.CurrentMinimumWabbajackVersion,
|
||||||
Archives = SelectedArchives.ToArray(),
|
Archives = SelectedArchives.ToArray(),
|
||||||
Directives = InstallDirectives.ToArray(),
|
Directives = InstallDirectives.ToArray(),
|
||||||
Name = _settings.ModListName,
|
Name = Settings.ModListName,
|
||||||
Author = _settings.ModListAuthor,
|
Author = Settings.ModListAuthor,
|
||||||
Description = _settings.ModListDescription,
|
Description = Settings.ModListDescription,
|
||||||
Readme = _settings.ModlistReadme,
|
Readme = Settings.ModlistReadme,
|
||||||
Image = ModListImage != default ? ModListImage.FileName : default,
|
Image = ModListImage != default ? ModListImage.FileName : default,
|
||||||
Website = _settings.ModListWebsite,
|
Website = Settings.ModListWebsite,
|
||||||
Version = _settings.ModlistVersion,
|
Version = Settings.ModlistVersion,
|
||||||
IsNSFW = _settings.ModlistIsNSFW
|
IsNSFW = Settings.ModlistIsNSFW
|
||||||
};
|
};
|
||||||
|
|
||||||
await InlineFiles(token);
|
await InlineFiles(token);
|
||||||
@ -242,7 +242,7 @@ namespace Wabbajack.Compiler
|
|||||||
new IncludeRegex(this, "^[^\\\\]*\\.bat$"),
|
new IncludeRegex(this, "^[^\\\\]*\\.bat$"),
|
||||||
new IncludeModIniData(this),
|
new IncludeModIniData(this),
|
||||||
new DirectMatch(this),
|
new DirectMatch(this),
|
||||||
new IncludeTaggedFiles(this, _settings.Include),
|
new IncludeTaggedFiles(this, Settings.Include),
|
||||||
// TODO: rework tagged files
|
// TODO: rework tagged files
|
||||||
// new IncludeTaggedFolders(this, Consts.WABBAJACK_INCLUDE),
|
// new IncludeTaggedFolders(this, Consts.WABBAJACK_INCLUDE),
|
||||||
new IgnoreExtension(this, Ext.Pyc),
|
new IgnoreExtension(this, Ext.Pyc),
|
||||||
@ -272,7 +272,7 @@ namespace Wabbajack.Compiler
|
|||||||
// TODO
|
// TODO
|
||||||
//new zEditIntegration.IncludeZEditPatches(this),
|
//new zEditIntegration.IncludeZEditPatches(this),
|
||||||
|
|
||||||
new IncludeTaggedFiles(this, _settings.NoMatchInclude),
|
new IncludeTaggedFiles(this, Settings.NoMatchInclude),
|
||||||
new IncludeRegex(this, ".*\\.txt"),
|
new IncludeRegex(this, ".*\\.txt"),
|
||||||
new IgnorePathContains(this,@"\Edit Scripts\Export\"),
|
new IgnorePathContains(this,@"\Edit Scripts\Export\"),
|
||||||
new IgnoreExtension(this, new Extension(".CACHE")),
|
new IgnoreExtension(this, new Extension(".CACHE")),
|
||||||
|
Loading…
Reference in New Issue
Block a user