Merge pull request #185 from wabbajack-tools/clearer-compiler-interface

Clearer compiler interface
This commit is contained in:
Timothy Baldridge 2019-11-17 17:35:25 -07:00 committed by GitHub
commit 50bbd0eb1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 259 additions and 137 deletions

View File

@ -23,17 +23,16 @@ namespace Wabbajack.Common
private static readonly Subject<CPUStatus> _Status = new Subject<CPUStatus>();
public IObservable<CPUStatus> Status => _Status;
public static int ThreadCount { get; } = Environment.ProcessorCount;
public static List<Thread> Threads { get; private set; }
public WorkQueue()
public WorkQueue(int threadCount = 0)
{
StartThreads();
StartThreads(threadCount == 0 ? Environment.ProcessorCount : threadCount);
}
private void StartThreads()
private void StartThreads(int threadCount)
{
Threads = Enumerable.Range(0, ThreadCount)
Threads = Enumerable.Range(0, threadCount)
.Select(idx =>
{
var thread = new Thread(() => ThreadBody(idx));

View File

@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ReactiveUI;
using Wabbajack.Common;
using Wabbajack.VirtualFileSystem;
namespace Wabbajack.Lib
{
public abstract class ABatchProcessor : IBatchProcessor
{
public WorkQueue Queue { get; private set; }
private bool _configured = false;
public void Dispose()
{
Queue?.Shutdown();
}
public Context VFS { get; private set; }
protected StatusUpdateTracker UpdateTracker { get; private set; }
private Subject<float> _percentCompleted { get; } = new Subject<float>();
/// <summary>
/// The current progress of the entire processing system on a scale of 0.0 to 1.0
/// </summary>
public IObservable<float> PercentCompleted => _percentCompleted;
private Subject<string> _textStatus { get; } = new Subject<string>();
/// <summary>
/// The current status of the processor as a text string
/// </summary>
public IObservable<string> TextStatus => _textStatus;
private Subject<CPUStatus> _queueStatus { get; } = new Subject<CPUStatus>();
public IObservable<CPUStatus> QueueStatus => _queueStatus;
private Subject<bool> _isRunning { get; } = new Subject<bool>();
public IObservable<bool> IsRunning => _isRunning;
private Thread _processorThread { get; set; }
protected void ConfigureProcessor(int steps, int threads = 0)
{
if (_configured)
throw new InvalidDataException("Can't configure a processor twice");
Queue = new WorkQueue(threads);
UpdateTracker = new StatusUpdateTracker(steps);
Queue.Status.Subscribe(_queueStatus);
UpdateTracker.Progress.Subscribe(_percentCompleted);
UpdateTracker.StepName.Subscribe(_textStatus);
VFS = new Context(Queue) { UpdateTracker = UpdateTracker };
_configured = true;
}
protected abstract bool _Begin();
public Task<bool> Begin()
{
_isRunning.OnNext(true);
var _tcs = new TaskCompletionSource<bool>();
if (_processorThread != null)
{
throw new InvalidDataException("Can't start the processor twice");
}
_processorThread = new Thread(() =>
{
try
{
_tcs.SetResult(_Begin());
}
catch (Exception ex)
{
_tcs.SetException(ex);
}
finally
{
_isRunning.OnNext(false);
}
});
_processorThread.Priority = ThreadPriority.BelowNormal;
_processorThread.Start();
return _tcs.Task;
}
public void Terminate()
{
Queue?.Shutdown();
_processorThread?.Abort();
_isRunning.OnNext(false);
}
}
}

View File

@ -17,15 +17,11 @@ using Path = Alphaleonis.Win32.Filesystem.Path;
namespace Wabbajack.Lib
{
public abstract class ACompiler
public abstract class ACompiler : ABatchProcessor
{
public string ModListName, ModListAuthor, ModListDescription, ModListImage, ModListWebsite, ModListReadme;
public string WabbajackVersion;
public StatusUpdateTracker UpdateTracker { get; protected set; }
public WorkQueue Queue { get; protected set; }
protected static string _vfsCacheName = "vfs_compile_cache.bin";
/// <summary>
/// A stream of tuples of ("Update Title", 0.25) which represent the name of the current task
@ -34,8 +30,6 @@ namespace Wabbajack.Lib
public IObservable<(string, float)> ProgressUpdates => _progressUpdates;
protected readonly Subject<(string, float)> _progressUpdates = new Subject<(string, float)>();
public Context VFS { get; internal set; }
public ModManager ModManager;
public string GamePath;
@ -43,6 +37,8 @@ namespace Wabbajack.Lib
public string ModListOutputFolder;
public string ModListOutputFile;
public bool ShowReportWhenFinished { get; set; } = true;
public List<Archive> SelectedArchives = new List<Archive>();
public List<Directive> InstallDirectives = new List<Directive>();
public List<RawSourceFile> AllFiles = new List<RawSourceFile>();
@ -128,7 +124,7 @@ namespace Wabbajack.Lib
public void ShowReport()
{
//if (!ShowReportWhenFinished) return;
if (!ShowReportWhenFinished) return;
var file = Path.GetTempFileName() + ".html";
File.WriteAllText(file, ModList.ReportHTML);
@ -207,8 +203,6 @@ namespace Wabbajack.Lib
return null;
}
public abstract bool Compile();
public Directive RunStack(IEnumerable<ICompilationStep> stack, RawSourceFile source)
{
Utils.Status($"Compiling {source.Path}");
@ -223,11 +217,5 @@ namespace Wabbajack.Lib
public abstract IEnumerable<ICompilationStep> GetStack();
public abstract IEnumerable<ICompilationStep> MakeStack();
protected ACompiler()
{
ProgressUpdates.Subscribe(itm => Utils.Log($"{itm.Item2} - {itm.Item1}"));
Queue = new WorkQueue();
}
}
}

View File

@ -12,14 +12,10 @@ using Path = Alphaleonis.Win32.Filesystem.Path;
namespace Wabbajack.Lib
{
public abstract class AInstaller
public abstract class AInstaller : ABatchProcessor
{
public bool IgnoreMissingFiles { get; internal set; } = false;
public StatusUpdateTracker UpdateTracker { get; protected set; }
public WorkQueue Queue { get; protected set; }
public Context VFS { get; internal set; }
public string OutputFolder { get; set; }
public string DownloadFolder { get; set; }
@ -29,13 +25,6 @@ namespace Wabbajack.Lib
public ModList ModList { get; internal set; }
public Dictionary<string, string> HashedArchives { get; set; }
protected AInstaller()
{
Queue = new WorkQueue();
}
public abstract void Install();
public void Info(string msg)
{
Utils.Log(msg);

View File

@ -13,11 +13,11 @@ namespace Wabbajack.Lib.CompilationSteps
private readonly IEnumerable<string> _include_directly;
private readonly List<ICompilationStep> _microstack;
private readonly List<ICompilationStep> _microstackWithInclude;
private readonly Compiler _mo2Compiler;
private readonly MO2Compiler _mo2Compiler;
public DeconstructBSAs(ACompiler compiler) : base(compiler)
{
_mo2Compiler = (Compiler) compiler;
_mo2Compiler = (MO2Compiler) compiler;
_include_directly = _mo2Compiler.ModInis.Where(kv =>
{
var general = kv.Value.General;

View File

@ -9,11 +9,11 @@ namespace Wabbajack.Lib.CompilationSteps
public class IgnoreDisabledMods : ACompilationStep
{
private readonly IEnumerable<string> _allEnabledMods;
private readonly Compiler _mo2Compiler;
private readonly MO2Compiler _mo2Compiler;
public IgnoreDisabledMods(ACompiler compiler) : base(compiler)
{
_mo2Compiler = (Compiler) compiler;
_mo2Compiler = (MO2Compiler) compiler;
var alwaysEnabled = _mo2Compiler.ModInis.Where(f => IsAlwaysEnabled(f.Value)).Select(f => f.Key).ToHashSet();
_allEnabledMods = _mo2Compiler.SelectedProfiles

View File

@ -8,11 +8,11 @@ namespace Wabbajack.Lib.CompilationSteps
public class IgnoreOtherProfiles : ACompilationStep
{
private readonly IEnumerable<string> _profiles;
private readonly Compiler _mo2Compiler;
private readonly MO2Compiler _mo2Compiler;
public IgnoreOtherProfiles(ACompiler compiler) : base(compiler)
{
_mo2Compiler = (Compiler) compiler;
_mo2Compiler = (MO2Compiler) compiler;
_profiles = _mo2Compiler.SelectedProfiles
.Select(p => Path.Combine("profiles", p) + "\\")

View File

@ -7,11 +7,11 @@ namespace Wabbajack.Lib.CompilationSteps
{
public class IncludeStubbedConfigFiles : ACompilationStep
{
private readonly Compiler _mo2Compiler;
private readonly MO2Compiler _mo2Compiler;
public IncludeStubbedConfigFiles(ACompiler compiler) : base(compiler)
{
_mo2Compiler = (Compiler) compiler;
_mo2Compiler = (MO2Compiler) compiler;
}
public override Directive Run(RawSourceFile source)

View File

@ -9,11 +9,11 @@ namespace Wabbajack.Lib.CompilationSteps
{
private readonly IEnumerable<string> _includeDirectly;
private readonly string _tag;
private readonly Compiler _mo2Compiler;
private readonly MO2Compiler _mo2Compiler;
public IncludeTaggedMods(ACompiler compiler, string tag) : base(compiler)
{
_mo2Compiler = (Compiler) compiler;
_mo2Compiler = (MO2Compiler) compiler;
_tag = tag;
_includeDirectly = _mo2Compiler.ModInis.Where(kv =>
{

View File

@ -9,11 +9,11 @@ namespace Wabbajack.Lib.CompilationSteps
public class IncludeThisProfile : ACompilationStep
{
private readonly IEnumerable<string> _correctProfiles;
private readonly Compiler _mo2Compiler;
private readonly MO2Compiler _mo2Compiler;
public IncludeThisProfile(ACompiler compiler) : base(compiler)
{
_mo2Compiler = (Compiler) compiler;
_mo2Compiler = (MO2Compiler) compiler;
_correctProfiles = _mo2Compiler.SelectedProfiles.Select(p => Path.Combine("profiles", p) + "\\").ToList();
}

View File

@ -8,11 +8,11 @@ namespace Wabbajack.Lib.CompilationSteps
{
public class PatchStockESMs : ACompilationStep
{
private readonly Compiler _mo2Compiler;
private readonly MO2Compiler _mo2Compiler;
public PatchStockESMs(ACompiler compiler) : base(compiler)
{
_mo2Compiler = (Compiler) compiler;
_mo2Compiler = (MO2Compiler) compiler;
}
public override Directive Run(RawSourceFile source)

View File

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wabbajack.Common;
namespace Wabbajack.Lib
{
/// <summary>
/// Wabbajack runs mostly as a batch processor of sorts, we have a list of tasks we need to perform
/// and the Compilers/Installers run throught those tasks one at a time. At any given moment the processor
/// will be using multiple threads to complete that task. This interface defines a common implementation of
/// all reporting functionality of both the compilers and installers.
///
/// These processors are disposible because they contain WorkQueues which must be properly shutdown to keep
/// from leaking threads.
/// </summary>
public interface IBatchProcessor : IDisposable
{
/// <summary>
/// The current progress of the entire processing system on a scale of 0.0 to 1.0
/// </summary>
IObservable<float> PercentCompleted { get; }
/// <summary>
/// The current status of the processor as a text string
/// </summary>
IObservable<string> TextStatus { get; }
/// <summary>
/// The status of the processor's work queue
/// </summary>
IObservable<CPUStatus> QueueStatus { get; }
IObservable<bool> IsRunning { get; }
/// <summary>
/// Begin processing
/// </summary>
Task<bool> Begin();
/// <summary>
/// Terminate any processing currently in progress by the processor. The processor should be disposed of
/// after calling this function as processing cannot be resumed and the tasks may be half completed.
/// Should only be called while IsRunning = true;
/// </summary>
void Terminate();
}
}

View File

@ -16,21 +16,17 @@ using Path = Alphaleonis.Win32.Filesystem.Path;
namespace Wabbajack.Lib
{
public class Compiler : ACompiler
public class MO2Compiler : ACompiler
{
private string _mo2DownloadsFolder;
public Dictionary<string, IEnumerable<IndexedFileMatch>> DirectMatchIndex;
public string MO2Folder;
public string MO2Profile;
public Compiler(string mo2_folder)
public MO2Compiler(string mo2_folder)
{
UpdateTracker = new StatusUpdateTracker(10);
VFS = new Context(Queue) {UpdateTracker = UpdateTracker};
ModManager = ModManager.MO2;
MO2Folder = mo2_folder;
@ -39,14 +35,10 @@ namespace Wabbajack.Lib
ModListOutputFolder = "output_folder";
ModListOutputFile = MO2Profile + ExtensionManager.Extension;
VFS.ProgressUpdates.Debounce(new TimeSpan(0, 0, 0, 0, 100))
.Subscribe(itm => _progressUpdates.OnNext(itm));
}
public dynamic MO2Ini { get; }
public bool ShowReportWhenFinished { get; set; } = true;
public bool IgnoreMissingFiles { get; set; }
public string MO2DownloadsFolder
@ -71,8 +63,9 @@ namespace Wabbajack.Lib
public HashSet<string> SelectedProfiles { get; set; } = new HashSet<string>();
public override bool Compile()
protected override bool _Begin()
{
ConfigureProcessor(10);
UpdateTracker.Reset();
UpdateTracker.NextStep("Gathering information");
Info("Looking for other profiles");

View File

@ -15,12 +15,10 @@ using Path = Alphaleonis.Win32.Filesystem.Path;
namespace Wabbajack.Lib
{
public class Installer : AInstaller
public class MO2Installer : AInstaller
{
public Installer(string archive, ModList mod_list, string output_folder)
public MO2Installer(string archive, ModList mod_list, string output_folder)
{
UpdateTracker = new StatusUpdateTracker(10);
VFS = new Context(Queue) {UpdateTracker = UpdateTracker};
ModManager = ModManager.MO2;
ModListArchive = archive;
OutputFolder = output_folder;
@ -30,8 +28,9 @@ namespace Wabbajack.Lib
public string GameFolder { get; set; }
public override void Install()
protected override bool _Begin()
{
ConfigureProcessor(10);
var game = GameRegistry.Games[ModList.GameType];
if (GameFolder == null)
@ -44,7 +43,7 @@ namespace Wabbajack.Lib
"game location up in the windows registry but were unable to find it, please make sure you launch the game once before running this installer. ",
"Could not find game location", MessageBoxButton.OK);
Utils.Log("Exiting because we couldn't find the game folder.");
return;
return false;
}
ValidateGameESMs();
@ -63,7 +62,7 @@ namespace Wabbajack.Lib
MessageBoxImage.Exclamation) == MessageBoxResult.No)
{
Utils.Log("Existing installation at the request of the user, existing mods folder found.");
return;
return false;
}
}
@ -97,6 +96,7 @@ namespace Wabbajack.Lib
// Removed until we decide if we want this functionality
// Nexus devs weren't sure this was a good idea, I (halgari) agree.
//AskToEndorse();
return true;
}
private void InstallIncludedDownloadMetas()

View File

@ -46,9 +46,9 @@ namespace Wabbajack.Lib
public void Build(ACompiler c, ModList lst)
{
Compiler compiler = null;
MO2Compiler compiler = null;
if (lst.ModManager == ModManager.MO2)
compiler = (Compiler) c;
compiler = (MO2Compiler) c;
Text($"### {lst.Name} by {lst.Author} - Installation Summary");
Text($"Build with Wabbajack Version {lst.WabbajackVersion}");

View File

@ -38,9 +38,6 @@ namespace Wabbajack.Lib
public VortexCompiler(Game game, string gamePath, string vortexFolder, string downloadsFolder, string stagingFolder)
{
UpdateTracker = new StatusUpdateTracker(10);
VFS = new Context(Queue) {UpdateTracker = UpdateTracker};
ModManager = ModManager.Vortex;
Game = game;
@ -54,8 +51,9 @@ namespace Wabbajack.Lib
ActiveArchives = new List<string>();
}
public override bool Compile()
protected override bool _Begin()
{
ConfigureProcessor(10);
if (string.IsNullOrEmpty(ModListName))
ModListName = $"Vortex ModList for {Game.ToString()}";
ModListOutputFile = $"{ModListName}{ExtensionManager.Extension}";

View File

@ -13,8 +13,6 @@ namespace Wabbajack.Lib
public VortexInstaller(string archive, ModList modList)
{
UpdateTracker = new StatusUpdateTracker(10);
VFS = new Context(Queue) {UpdateTracker = UpdateTracker};
ModManager = ModManager.Vortex;
ModListArchive = archive;
ModList = modList;
@ -25,8 +23,9 @@ namespace Wabbajack.Lib
GameInfo = GameRegistry.Games[ModList.GameType];
}
public override void Install()
protected override bool _Begin()
{
ConfigureProcessor(10);
Directory.CreateDirectory(DownloadFolder);
HashArchives();
@ -52,6 +51,7 @@ namespace Wabbajack.Lib
//InstallIncludedDownloadMetas();
Info("Installation complete! You may exit the program.");
return true;
}
private void InstallIncludedFiles()

View File

@ -78,6 +78,7 @@
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="ABatchProcessor.cs" />
<Compile Include="ACompiler.cs" />
<Compile Include="AInstaller.cs" />
<Compile Include="CerasConfig.cs" />
@ -110,7 +111,7 @@
<Compile Include="CompilationSteps\IStackStep.cs" />
<Compile Include="CompilationSteps\PatchStockESMs.cs" />
<Compile Include="CompilationSteps\Serialization.cs" />
<Compile Include="Compiler.cs" />
<Compile Include="MO2Compiler.cs" />
<Compile Include="Data.cs" />
<Compile Include="Downloaders\AbstractDownloadState.cs" />
<Compile Include="Downloaders\DownloadDispatcher.cs" />
@ -125,7 +126,8 @@
<Compile Include="Downloaders\MEGADownloader.cs" />
<Compile Include="Downloaders\ModDBDownloader.cs" />
<Compile Include="Downloaders\NexusDownloader.cs" />
<Compile Include="Installer.cs" />
<Compile Include="IBatchProcessor.cs" />
<Compile Include="MO2Installer.cs" />
<Compile Include="ModListRegistry\ModListMetadata.cs" />
<Compile Include="NexusApi\Dtos.cs" />
<Compile Include="NexusApi\NexusApi.cs" />

View File

@ -14,11 +14,11 @@ namespace Wabbajack.Lib
{
public class zEditIntegration
{
private static Compiler _mo2Compiler;
private static MO2Compiler _mo2Compiler;
public static string FindzEditPath(ACompiler compiler)
{
_mo2Compiler = (Compiler) compiler;
_mo2Compiler = (MO2Compiler) compiler;
var executables = _mo2Compiler.MO2Ini.customExecutables;
if (executables.size == null) return null;
@ -141,7 +141,7 @@ namespace Wabbajack.Lib
public string dataFolder;
}
public static void VerifyMerges(Compiler compiler)
public static void VerifyMerges(MO2Compiler compiler)
{
var by_name = compiler.InstallDirectives.ToDictionary(f => f.To);
@ -160,7 +160,7 @@ namespace Wabbajack.Lib
}
}
public static void GenerateMerges(Installer installer)
public static void GenerateMerges(MO2Installer installer)
{
installer.ModList
.Directives

View File

@ -64,7 +64,7 @@ namespace Wabbajack.Test.ListValidation
Log($"Loading {modlist_path}");
var installer = Installer.LoadFromFile(modlist_path);
var installer = MO2Installer.LoadFromFile(modlist_path);
Log($"{installer.Archives.Count} archives to validate");

View File

@ -32,18 +32,18 @@ namespace Wabbajack.Test
utils.Dispose();
}
protected Compiler ConfigureAndRunCompiler(string profile)
protected MO2Compiler ConfigureAndRunCompiler(string profile)
{
var compiler = MakeCompiler();
compiler.MO2Profile = profile;
compiler.ShowReportWhenFinished = false;
Assert.IsTrue(compiler.Compile());
Assert.IsTrue(compiler.Begin().Result);
return compiler;
}
protected Compiler MakeCompiler()
protected MO2Compiler MakeCompiler()
{
var compiler = new Compiler(utils.MO2Folder);
var compiler = new MO2Compiler(utils.MO2Folder);
return compiler;
}
protected ModList CompileAndInstall(string profile)
@ -53,13 +53,13 @@ namespace Wabbajack.Test
return compiler.ModList;
}
protected void Install(Compiler compiler)
protected void Install(MO2Compiler compiler)
{
var modlist = Installer.LoadFromFile(compiler.ModListOutputFile);
var installer = new Installer(compiler.ModListOutputFile, modlist, utils.InstallFolder);
var modlist = MO2Installer.LoadFromFile(compiler.ModListOutputFile);
var installer = new MO2Installer(compiler.ModListOutputFile, modlist, utils.InstallFolder);
installer.DownloadFolder = utils.DownloadsFolder;
installer.GameFolder = utils.GameFolder;
installer.Install();
installer.Begin().Wait();
}
}
}

View File

@ -37,7 +37,7 @@ namespace Wabbajack.Test
vortexCompiler.DownloadsFolder = utils.DownloadsFolder;
vortexCompiler.StagingFolder = utils.InstallFolder;
Directory.CreateDirectory(utils.InstallFolder);
Assert.IsTrue(vortexCompiler.Compile());
Assert.IsTrue(vortexCompiler.Begin().Result);
return vortexCompiler;
}
@ -60,13 +60,13 @@ namespace Wabbajack.Test
protected void Install(VortexCompiler vortexCompiler)
{
var modList = Installer.LoadFromFile(vortexCompiler.ModListOutputFile);
var installer = new Installer(vortexCompiler.ModListOutputFile, modList, utils.InstallFolder)
var modList = MO2Installer.LoadFromFile(vortexCompiler.ModListOutputFile);
var installer = new MO2Installer(vortexCompiler.ModListOutputFile, modList, utils.InstallFolder)
{
DownloadFolder = utils.DownloadsFolder,
GameFolder = utils.GameFolder,
};
installer.Install();
installer.Begin().Wait();
}
}
}

View File

@ -73,11 +73,11 @@ namespace Wabbajack.Test
if (Directory.Exists(loot_folder))
Directory.Delete(loot_folder, true);
var compiler = new Compiler(utils.InstallFolder);
var compiler = new MO2Compiler(utils.InstallFolder);
compiler.MO2DownloadsFolder = Path.Combine(utils.DownloadsFolder);
compiler.MO2Profile = profile;
compiler.ShowReportWhenFinished = false;
Assert.IsTrue(compiler.Compile());
Assert.IsTrue(compiler.Begin().Result);
}
@ -144,21 +144,21 @@ namespace Wabbajack.Test
return compiler.ModList;
}
private void Install(Compiler compiler)
private void Install(MO2Compiler compiler)
{
var modlist = Installer.LoadFromFile(compiler.ModListOutputFile);
var installer = new Installer(compiler.ModListOutputFile, modlist, utils.InstallFolder);
var modlist = MO2Installer.LoadFromFile(compiler.ModListOutputFile);
var installer = new MO2Installer(compiler.ModListOutputFile, modlist, utils.InstallFolder);
installer.DownloadFolder = utils.DownloadsFolder;
installer.GameFolder = utils.GameFolder;
installer.Install();
installer.Begin().Wait();
}
private Compiler ConfigureAndRunCompiler(string profile)
private MO2Compiler ConfigureAndRunCompiler(string profile)
{
var compiler = new Compiler(utils.MO2Folder);
var compiler = new MO2Compiler(utils.MO2Folder);
compiler.MO2Profile = profile;
compiler.ShowReportWhenFinished = false;
Assert.IsTrue(compiler.Compile());
Assert.IsTrue(compiler.Begin().Result);
return compiler;
}
}

View File

@ -77,8 +77,8 @@ namespace Wabbajack.Test
// Update the file and verify that it throws an error.
utils.GenerateRandomFileData(game_file, 20);
var exception = Assert.ThrowsException<Exception>(() => Install(compiler));
Assert.AreEqual(exception.Message, "Game ESM hash doesn't match, is the ESM already cleaned? Please verify your local game files.");
var exception = Assert.ThrowsException<AggregateException>(() => Install(compiler));
Assert.AreEqual(exception.InnerExceptions.First().Message, "Game ESM hash doesn't match, is the ESM already cleaned? Please verify your local game files.");
}

View File

@ -13,6 +13,7 @@ namespace Wabbajack
{
IReactiveCommand BeginCommand { get; }
bool Compiling { get; }
ModlistSettingsEditorVM ModlistSettings { get; }
StatusUpdateTracker StatusTracker { get;}
void Unload();

View File

@ -7,6 +7,7 @@ using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading.Tasks;
using Wabbajack.Common;
@ -100,10 +101,10 @@ namespace Wabbajack
.ObserveOnGuiThread(),
execute: async () =>
{
Compiler compiler;
MO2Compiler compiler;
try
{
compiler = new Compiler(this.Mo2Folder)
compiler = new MO2Compiler(this.Mo2Folder)
{
MO2Profile = this.MOProfile,
ModListName = this.ModlistSettings.ModListName,
@ -113,6 +114,10 @@ namespace Wabbajack
ModListWebsite = this.ModlistSettings.Website,
ModListReadme = this.ModlistSettings.ReadMeText.TargetPath,
};
// TODO: USE RX HERE
compiler.TextStatus.Subscribe(Utils.Log);
// TODO: Where do we bind this?
//compiler.QueueStatus.Subscribe(_cpuStatus);
}
catch (Exception ex)
{
@ -120,23 +125,22 @@ namespace Wabbajack
Utils.Log($"Compiler error: {ex.ExceptionToString()}");
return;
}
await Task.Run(() =>
try
{
try
{
this.StatusTracker = compiler.UpdateTracker;
compiler.Compile();
}
catch (Exception ex)
{
while (ex.InnerException != null) ex = ex.InnerException;
Utils.Log($"Compiler error: {ex.ExceptionToString()}");
}
finally
{
this.StatusTracker = null;
}
});
await compiler.Begin();
}
catch (Exception ex)
{
while (ex.InnerException != null) ex = ex.InnerException;
Utils.Log($"Compiler error: {ex.ExceptionToString()}");
}
finally
{
this.StatusTracker = null;
compiler.Dispose();
}
});
this._Compiling = this.BeginCommand.IsExecuting
.ToProperty(this, nameof(this.Compiling));
@ -191,7 +195,7 @@ namespace Wabbajack
{
try
{
var tmp_compiler = new Compiler(this.Mo2Folder);
var tmp_compiler = new MO2Compiler(this.Mo2Folder);
this.DownloadLocation.TargetPath = tmp_compiler.MO2DownloadsFolder;
}
catch (Exception ex)

View File

@ -106,12 +106,11 @@ namespace Wabbajack
Utils.Log($"Compiler error: {ex.ExceptionToString()}");
return;
}
await Task.Run(() =>
await Task.Run(async () =>
{
try
{
this.StatusTracker = compiler.UpdateTracker;
compiler.Compile();
await compiler.Begin();
}
catch (Exception ex)
{

View File

@ -9,6 +9,7 @@ using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using Wabbajack.Common;
@ -131,7 +132,7 @@ namespace Wabbajack
.Select(modListPath =>
{
if (modListPath == null) return default(ModListVM);
var modList = Installer.LoadFromFile(modListPath);
var modList = MO2Installer.LoadFromFile(modListPath);
if (modList == null)
{
MessageBox.Show("Invalid Modlist, or file not found.", "Invalid Modlist", MessageBoxButton.OK,
@ -291,15 +292,15 @@ namespace Wabbajack
{
this.Installing = true;
this.InstallingMode = true;
var installer = new Installer(this.ModListPath, this.ModList.SourceModList, Location.TargetPath)
var installer = new MO2Installer(this.ModListPath, this.ModList.SourceModList, Location.TargetPath)
{
DownloadFolder = DownloadLocation.TargetPath
};
var th = new Thread(() =>
Task.Run(async () =>
{
try
{
installer.Install();
await installer.Begin();
}
catch (Exception ex)
{
@ -313,11 +314,7 @@ namespace Wabbajack
this.Installing = false;
}
})
{
Priority = ThreadPriority.BelowNormal
};
th.Start();
});
}
}
}

View File

@ -83,9 +83,10 @@ namespace Wabbajack
// Compile progress updates and populate ObservableCollection
/*
WorkQueue.Status
_Compiler.WhenAny(c => c.Value.Compiler.)
.ObserveOn(RxApp.TaskpoolScheduler)
.ToObservableChangeSet(x => x.ID)
.ToObservableChangeSet(x => x.)
/*
.Batch(TimeSpan.FromMilliseconds(250), RxApp.TaskpoolScheduler)
.EnsureUniqueChanges()
.ObserveOn(RxApp.MainThreadScheduler)