wabbajack/Wabbajack.App/Screens/CompilerConfigurationViewModel.cs

209 lines
7.0 KiB
C#
Raw Normal View History

2021-10-13 21:51:00 +00:00
using System;
using System.Collections.Generic;
2021-10-14 04:46:43 +00:00
using System.IO;
using System.Linq;
using System.Reactive;
2021-10-14 04:46:43 +00:00
using System.Text.Json;
using System.Threading.Tasks;
using Avalonia.Controls.Mixins;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Wabbajack.App.Messages;
2021-10-14 04:46:43 +00:00
using Wabbajack.App.Models;
using Wabbajack.App.ViewModels;
2021-10-13 21:51:00 +00:00
using Wabbajack.Common;
using Wabbajack.Compiler;
using Wabbajack.DTOs;
2021-10-14 04:46:43 +00:00
using Wabbajack.DTOs.JsonConverters;
using Wabbajack.Installer;
using Wabbajack.Paths;
using Wabbajack.Paths.IO;
using Consts = Wabbajack.Compiler.Consts;
namespace Wabbajack.App.Screens;
public class CompilerConfigurationViewModel : ViewModelBase, IReceiverMarker
{
2021-10-14 04:46:43 +00:00
private readonly DTOSerializer _dtos;
private readonly SettingsManager _settingsManager;
2021-10-14 04:46:43 +00:00
public CompilerConfigurationViewModel(DTOSerializer dtos, SettingsManager settingsManager)
{
2021-10-14 04:46:43 +00:00
_settingsManager = settingsManager;
_dtos = dtos;
Activator = new ViewModelActivator();
AllGames = GameRegistry.Games.Values.ToArray();
2021-10-23 16:51:17 +00:00
2021-10-14 04:46:43 +00:00
StartCompilation = ReactiveCommand.Create(() => BeginCompilation().FireAndForget());
2021-10-13 21:51:00 +00:00
OutputFolder = KnownFolders.EntryPoint;
2021-10-23 16:51:17 +00:00
this.WhenActivated(disposables =>
{
2021-10-14 04:46:43 +00:00
LoadLastCompilation().FireAndForget();
this.WhenAnyValue(v => v.SettingsFile)
2021-10-23 16:51:17 +00:00
.Subscribe(location => { LoadNewSettingsFile(location).FireAndForget(); })
.DisposeWith(disposables);
2021-10-14 04:46:43 +00:00
});
}
2021-10-23 16:51:17 +00:00
[Reactive] public string Title { get; set; }
[Reactive] public AbsolutePath SettingsFile { get; set; }
[Reactive] public AbsolutePath Downloads { get; set; }
[Reactive] public GameMetaData BaseGame { get; set; }
[Reactive] public AbsolutePath Source { get; set; }
[Reactive] public AbsolutePath GamePath { get; set; }
[Reactive] public string SelectedProfile { get; set; }
[Reactive] public AbsolutePath OutputFolder { get; set; }
[Reactive] public IEnumerable<GameMetaData> AllGames { get; set; }
[Reactive] public ReactiveCommand<Unit, Unit> StartCompilation { get; set; }
[Reactive] public IEnumerable<RelativePath> AlwaysEnabled { get; set; } = Array.Empty<RelativePath>();
public AbsolutePath SettingsOutputLocation => Source.Combine(Title)
.WithExtension(IsMO2Compilation ? Ext.MO2CompilerSettings : Ext.CompilerSettings);
[Reactive] public bool IsMO2Compilation { get; set; }
private async Task LoadNewSettingsFile(AbsolutePath location)
2021-10-14 04:46:43 +00:00
{
if (location == default) return;
if (location.FileExists()) await LoadSettings(location);
}
private async Task LoadLastCompilation()
{
var location = await _settingsManager.Load<AbsolutePath>("last_compilation");
SettingsFile = location;
}
2021-10-14 04:46:43 +00:00
private async Task BeginCompilation()
{
var settings = GetSettings();
await SaveSettingsFile();
await _settingsManager.Save("last_compilation", SettingsOutputLocation);
2021-10-23 16:51:17 +00:00
2021-10-14 04:46:43 +00:00
MessageBus.Instance.Send(new StartCompilation(settings));
MessageBus.Instance.Send(new NavigateTo(typeof(CompilationViewModel)));
}
2021-10-14 04:46:43 +00:00
private CompilerSettings GetSettings()
{
2021-10-14 04:46:43 +00:00
return new MO2CompilerSettings
{
Downloads = Downloads,
2021-10-14 04:46:43 +00:00
Source = Source,
Game = BaseGame.Game,
2021-10-13 03:59:54 +00:00
Profile = SelectedProfile,
2021-10-13 21:51:00 +00:00
UseGamePaths = true,
OutputFile = OutputFolder.Combine(SelectedProfile).WithExtension(Ext.Wabbajack),
AlwaysEnabled = AlwaysEnabled.ToArray()
};
}
2021-10-14 04:46:43 +00:00
public bool AddAlwaysExcluded(AbsolutePath path)
{
if (!path.InFolder(Source)) return false;
var relative = path.RelativeTo(Source);
AlwaysEnabled = AlwaysEnabled.Append(relative).Distinct().ToArray();
return true;
}
public void RemoveAlwaysExcluded(RelativePath path)
{
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"];
2021-10-14 04:46:43 +00:00
BaseGame = GameRegistry.GetByFuzzyName(general["gameName"].FromMO2Ini());
Source = mo2Folder;
2021-10-23 16:51:17 +00:00
2021-10-14 04:46:43 +00:00
SelectedProfile = general["selected_profile"].FromMO2Ini();
GamePath = general["gamePath"].FromMO2Ini().ToAbsolutePath();
Title = SelectedProfile;
2021-10-23 16:51:17 +00:00
var settings = iniData["Settings"];
2021-10-14 04:46:43 +00:00
Downloads = settings["download_directory"].FromMO2Ini().ToAbsolutePath();
IsMO2Compilation = true;
2021-10-23 16:51:17 +00:00
2021-10-14 04:46:43 +00:00
// Find Always Enabled mods
foreach (var modFolder in mo2Folder.Combine("mods").EnumerateDirectories())
{
var iniFile = modFolder.Combine("meta.ini");
if (!iniFile.FileExists()) continue;
2021-10-23 16:51:17 +00:00
2021-10-14 04:46:43 +00:00
var data = iniFile.LoadIniFile();
var generalModData = data["General"];
2021-10-23 16:51:17 +00:00
if ((generalModData["notes"]?.Contains("WABBAJACK_ALWAYS_ENABLE") ?? false) ||
2021-10-14 04:46:43 +00:00
(generalModData["comments"]?.Contains("WABBAJACK_ALWAYS_ENABLE") ?? false))
AlwaysEnabled = AlwaysEnabled.Append(modFolder.RelativeTo(mo2Folder)).ToArray();
}
if (mo2Folder.Depth > 1)
OutputFolder = mo2Folder.Parent;
2021-10-23 16:51:17 +00:00
2021-10-14 04:46:43 +00:00
await SaveSettingsFile();
SettingsFile = SettingsOutputLocation;
}
}
2021-10-14 04:46:43 +00:00
}
2021-10-14 04:46:43 +00:00
private async Task SaveSettingsFile()
{
await using var st = SettingsOutputLocation.Open(FileMode.Create, FileAccess.Write, FileShare.None);
2021-10-23 16:51:17 +00:00
if (IsMO2Compilation)
await JsonSerializer.SerializeAsync(st, (MO2CompilerSettings) GetSettings(), _dtos.Options);
else
2021-10-14 04:46:43 +00:00
await JsonSerializer.SerializeAsync(st, GetSettings(), _dtos.Options);
}
2021-10-13 21:51:00 +00:00
2021-10-14 04:46:43 +00:00
private async Task LoadSettings(AbsolutePath path)
2021-10-13 21:51:00 +00:00
{
2021-10-14 04:46:43 +00:00
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();
2021-10-13 21:51:00 +00:00
}
2021-10-14 04:46:43 +00:00
private async Task<T> LoadSettingsFile<T>(AbsolutePath path)
2021-10-13 21:51:00 +00:00
{
2021-10-14 04:46:43 +00:00
await using var st = path.Open(FileMode.Open);
return (await JsonSerializer.DeserializeAsync<T>(st, _dtos.Options))!;
2021-10-13 21:51:00 +00:00
}
}