mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Compiler views and logger view controls
This commit is contained in:
parent
6a0ff5f29d
commit
6e52318dbb
17
Wabbajack.App/Controls/LogView.axaml
Normal file
17
Wabbajack.App/Controls/LogView.axaml
Normal file
@ -0,0 +1,17 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:Wabbajack.App.Controls"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Wabbajack.App.Controls.LogView">
|
||||
<Border>
|
||||
<ListBox x:Name="Messages">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:LogViewItem></controls:LogViewItem>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Border>
|
||||
</UserControl>
|
22
Wabbajack.App/Controls/LogView.axaml.cs
Normal file
22
Wabbajack.App/Controls/LogView.axaml.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using Avalonia.Controls.Mixins;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ReactiveUI;
|
||||
using Wabbajack.App.Utilities;
|
||||
|
||||
namespace Wabbajack.App.Controls;
|
||||
|
||||
public partial class LogView : ReactiveUserControl<LogViewModel>
|
||||
{
|
||||
public LogView()
|
||||
{
|
||||
DataContext = App.Services.GetService<LogViewModel>()!;
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.OneWayBind(ViewModel, vm => vm.Messages, view => view.Messages.Items)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
8
Wabbajack.App/Controls/LogViewItem.axaml
Normal file
8
Wabbajack.App/Controls/LogViewItem.axaml
Normal file
@ -0,0 +1,8 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Wabbajack.App.Controls.LogViewItem">
|
||||
<TextBlock x:Name="Message"></TextBlock>
|
||||
</UserControl>
|
20
Wabbajack.App/Controls/LogViewItem.axaml.cs
Normal file
20
Wabbajack.App/Controls/LogViewItem.axaml.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using Avalonia.Controls.Mixins;
|
||||
using Avalonia.ReactiveUI;
|
||||
using ReactiveUI;
|
||||
using Wabbajack.App.Utilities;
|
||||
|
||||
namespace Wabbajack.App.Controls;
|
||||
|
||||
public partial class LogViewItem : ReactiveUserControl<LoggerProvider.ILogMessage>, IActivatableView
|
||||
{
|
||||
public LogViewItem()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.OneWayBind(ViewModel, vm => vm.ShortMessage, view => view.Message.Text)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
43
Wabbajack.App/Controls/LogViewModel.cs
Normal file
43
Wabbajack.App/Controls/LogViewModel.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using Avalonia.Controls.Mixins;
|
||||
using DynamicData;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ReactiveUI;
|
||||
using Wabbajack.App.Utilities;
|
||||
using Wabbajack.App.ViewModels;
|
||||
|
||||
namespace Wabbajack.App.Controls;
|
||||
|
||||
public class LogViewModel : ViewModelBase, IActivatableViewModel
|
||||
{
|
||||
private readonly LoggerProvider _provider;
|
||||
|
||||
private readonly SourceCache<LoggerProvider.ILogMessage, long> _messages;
|
||||
|
||||
public readonly ReadOnlyObservableCollection<LoggerProvider.ILogMessage> _messagesFiltered;
|
||||
public ReadOnlyObservableCollection<LoggerProvider.ILogMessage> Messages => _messagesFiltered;
|
||||
|
||||
public LogViewModel(LoggerProvider provider)
|
||||
{
|
||||
_messages = new SourceCache<LoggerProvider.ILogMessage, long>(m => m.MessageId);
|
||||
_messages.LimitSizeTo(100);
|
||||
|
||||
Activator = new ViewModelActivator();
|
||||
_provider = provider;
|
||||
|
||||
_messages.Connect()
|
||||
.Bind(out _messagesFiltered)
|
||||
.Subscribe();
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
_provider.Messages
|
||||
.Subscribe(m => _messages.AddOrUpdate(m))
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
8
Wabbajack.App/Messages/StartCompilation.cs
Normal file
8
Wabbajack.App/Messages/StartCompilation.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using Wabbajack.Compiler;
|
||||
|
||||
namespace Wabbajack.App.Messages;
|
||||
|
||||
public record StartCompilation(CompilerSettings Settings)
|
||||
{
|
||||
|
||||
}
|
@ -46,7 +46,6 @@ namespace Wabbajack.App.Screens
|
||||
|
||||
private SourceCache<BrowseItemViewModel, string> _modLists = new(x => x.MachineURL);
|
||||
|
||||
|
||||
public readonly ReadOnlyObservableCollection<BrowseItemViewModel> _filteredModLists;
|
||||
public ReadOnlyObservableCollection<BrowseItemViewModel> ModLists => _filteredModLists;
|
||||
|
||||
|
15
Wabbajack.App/Screens/CompilationView.axaml
Normal file
15
Wabbajack.App/Screens/CompilationView.axaml
Normal file
@ -0,0 +1,15 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
xmlns:i="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:controls="clr-namespace:Wabbajack.App.Controls"
|
||||
x:Class="Wabbajack.App.Screens.CompilationView">
|
||||
<Grid RowDefinitions="40, 5, 5, *, 40">
|
||||
<TextBlock Grid.Row="0" x:Name="StatusText" FontSize="20" FontWeight="Bold">[20/30] Installing Files</TextBlock>
|
||||
<ProgressBar Grid.Row="1" x:Name="StepsProgress" Maximum="1000" Value="40"></ProgressBar>
|
||||
<ProgressBar Grid.Row="2" x:Name="StepProgress" Maximum="10000" Value="30"></ProgressBar>
|
||||
<controls:LogView Grid.Row="3" x:Name="LogView"></controls:LogView>
|
||||
</Grid>
|
||||
</UserControl>
|
12
Wabbajack.App/Screens/CompilationView.axaml.cs
Normal file
12
Wabbajack.App/Screens/CompilationView.axaml.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Wabbajack.App.ViewModels;
|
||||
using Wabbajack.App.Views;
|
||||
|
||||
namespace Wabbajack.App.Screens;
|
||||
|
||||
public partial class CompilationView : ScreenBase<CompilationViewModel>
|
||||
{
|
||||
public CompilationView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
35
Wabbajack.App/Screens/CompilationViewModel.cs
Normal file
35
Wabbajack.App/Screens/CompilationViewModel.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ReactiveUI;
|
||||
using Wabbajack.App.Messages;
|
||||
using Wabbajack.App.ViewModels;
|
||||
using Wabbajack.Compiler;
|
||||
|
||||
namespace Wabbajack.App.Screens;
|
||||
|
||||
public class CompilationViewModel : ViewModelBase, IReceiverMarker, IReceiver<StartCompilation>
|
||||
{
|
||||
private readonly IServiceProvider _provider;
|
||||
private ACompiler _compiler;
|
||||
|
||||
public CompilationViewModel(IServiceProvider provider)
|
||||
{
|
||||
_provider = provider;
|
||||
Activator = new ViewModelActivator();
|
||||
|
||||
}
|
||||
|
||||
public void Receive(StartCompilation val)
|
||||
{
|
||||
if (val.Settings is MO2CompilerSettings mo2)
|
||||
{
|
||||
var compiler = _provider.GetService<MO2Compiler>()!;
|
||||
compiler.Settings = mo2;
|
||||
_compiler = compiler;
|
||||
|
||||
}
|
||||
|
||||
_compiler.Begin(CancellationToken.None);
|
||||
}
|
||||
}
|
@ -4,8 +4,34 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
xmlns:i="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:controls="clr-namespace:Wabbajack.App.Controls"
|
||||
x:Class="Wabbajack.App.Screens.CompilerConfigurationView">
|
||||
<Grid RowDefinitions="40, 5, 5, *, 40">
|
||||
<Grid RowDefinitions="40, *, 40">
|
||||
<TextBlock Grid.Row="0" x:Name="StatusText" FontSize="20" FontWeight="Bold">Compiler Configuration</TextBlock>
|
||||
<Grid Grid.Row="1" ColumnDefinitions="Auto, *" RowDefinitions="Auto, Auto, Auto, Auto, Auto" Margin="4">
|
||||
<Label Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right">Title:</Label>
|
||||
<TextBox Grid.Column="1" Grid.Row="0" x:Name="Title"></TextBox>
|
||||
<Label Grid.Column="0" Grid.Row="1" HorizontalAlignment="Right">Settings File:</Label>
|
||||
<controls:FileSelectionBox Grid.Column="1" Grid.Row="1" x:Name="SettingsFile"
|
||||
AllowedExtensions=".txt|.json">
|
||||
</controls:FileSelectionBox>
|
||||
<Label Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right">Mod List Folder:</Label>
|
||||
<controls:FileSelectionBox Grid.Column="1" Grid.Row="2" x:Name="BaseFolder" SelectFolder="True"></controls:FileSelectionBox>
|
||||
<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>
|
||||
<Label Grid.Column="0" Grid.Row="4" HorizontalAlignment="Right">Base Game:</Label>
|
||||
<ComboBox Grid.Column="1" Grid.Row="4" x:Name="BaseGame">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Path=HumanFriendlyGameName}"></TextBlock>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
<Grid ColumnDefinitions="*, Auto" Grid.Row="2">
|
||||
<Button Grid.Column="1" x:Name="StartCompilation">
|
||||
<TextBlock>Start Compilation</TextBlock>
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
@ -1,5 +1,8 @@
|
||||
|
||||
|
||||
using System.Reactive.Disposables;
|
||||
using Avalonia;
|
||||
using ReactiveUI;
|
||||
using Wabbajack.App.Views;
|
||||
|
||||
namespace Wabbajack.App.Screens
|
||||
@ -9,6 +12,29 @@ namespace Wabbajack.App.Screens
|
||||
public CompilerConfigurationView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
|
||||
this.Bind(ViewModel, vm => vm.BasePath, view => view.BaseFolder.SelectedPath)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.SettingsFile, view => view.SettingsFile.SelectedPath)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.Downloads, view => view.DownloadsFolder.SelectedPath)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.OneWayBind(ViewModel, vm => vm.AllGames, view => view.BaseGame.Items)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.BaseGame, view => view.BaseGame.SelectedItem)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.StartCompilation, view => view.StartCompilation)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +1,128 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls.Mixins;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Wabbajack.App.Extensions;
|
||||
using Wabbajack.App.Messages;
|
||||
using Wabbajack.App.ViewModels;
|
||||
using Wabbajack.Compiler;
|
||||
using Wabbajack.DTOs;
|
||||
using Wabbajack.Installer;
|
||||
using Wabbajack.Paths;
|
||||
using Wabbajack.Paths.IO;
|
||||
using Consts = Wabbajack.Compiler.Consts;
|
||||
|
||||
namespace Wabbajack.App.Screens;
|
||||
|
||||
public class CompilerConfigurationViewModel : ViewModelBase, IReceiverMarker
|
||||
{
|
||||
[Reactive]
|
||||
public AbsolutePath SettingsFile { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public AbsolutePath Downloads { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public GameMetaData BaseGame { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public AbsolutePath BasePath { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public AbsolutePath GamePath { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string SelectedProfile { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public IEnumerable<GameMetaData> AllGames { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public ReactiveCommand<Unit, Unit> StartCompilation { get; set; }
|
||||
|
||||
|
||||
public CompilerConfigurationViewModel()
|
||||
{
|
||||
Activator = new ViewModelActivator();
|
||||
|
||||
AllGames = GameRegistry.Games.Values.ToArray();
|
||||
|
||||
StartCompilation = ReactiveCommand.Create(() => BeginCompilation());
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
var tuples = this.WhenAnyValue(vm => vm.SettingsFile)
|
||||
.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()
|
||||
{
|
||||
var settings = new MO2CompilerSettings
|
||||
{
|
||||
Downloads = Downloads,
|
||||
Source = BasePath,
|
||||
Game = BaseGame.Game,
|
||||
Profile = SelectedProfile
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -6,6 +6,7 @@ using System.Threading.Tasks;
|
||||
using Avalonia.Threading;
|
||||
using CefNet;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Wabbajack.App.Controls;
|
||||
using Wabbajack.App.Interfaces;
|
||||
using Wabbajack.App.Messages;
|
||||
@ -31,12 +32,15 @@ namespace Wabbajack.App
|
||||
{
|
||||
public static IServiceCollection AddAppServices(this IServiceCollection services)
|
||||
{
|
||||
services.AddAllSingleton<ILoggerProvider, LoggerProvider>();
|
||||
services.AddSingleton<MessageBus>();
|
||||
services.AddSingleton<MainWindow>();
|
||||
services.AddSingleton<BrowseViewModel>();
|
||||
|
||||
services.AddTransient<BrowseItemViewModel>();
|
||||
|
||||
services.AddTransient<LogViewModel>();
|
||||
|
||||
services.AddDTOConverters();
|
||||
services.AddDTOSerializer();
|
||||
services.AddSingleton<ModeSelectionViewModel>();
|
||||
@ -45,6 +49,7 @@ namespace Wabbajack.App
|
||||
services.AddSingleton<IScreenView, InstallConfigurationView>();
|
||||
services.AddSingleton<IScreenView, CompilerConfigurationView>();
|
||||
services.AddSingleton<IScreenView, StandardInstallationView>();
|
||||
services.AddSingleton<IScreenView, CompilationView>();
|
||||
services.AddSingleton<IScreenView, SettingsView>();
|
||||
services.AddSingleton<IScreenView, BrowseView>();
|
||||
services.AddSingleton<IScreenView, LauncherView>();
|
||||
@ -60,6 +65,7 @@ namespace Wabbajack.App
|
||||
services.AddAllSingleton<IReceiverMarker, NexusLoginViewModel>();
|
||||
services.AddAllSingleton<IReceiverMarker, LoversLabOAuthLoginViewModel>();
|
||||
services.AddAllSingleton<IReceiverMarker, VectorPlexusOAuthLoginViewModel>();
|
||||
services.AddAllSingleton<IReceiverMarker, CompilationViewModel>();
|
||||
services.AddAllSingleton<IReceiverMarker, LauncherViewModel>();
|
||||
|
||||
// Services
|
||||
|
72
Wabbajack.App/Utilities/LoggerProvider.cs
Normal file
72
Wabbajack.App/Utilities/LoggerProvider.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Subjects;
|
||||
using System.Threading;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Wabbajack.App.Utilities;
|
||||
|
||||
public class LoggerProvider : ILoggerProvider
|
||||
{
|
||||
private Subject<ILogMessage> _messages = new();
|
||||
public IObservable<ILogMessage> Messages => _messages;
|
||||
|
||||
private long _messageID = 0;
|
||||
|
||||
public long NextMessageId()
|
||||
{
|
||||
return Interlocked.Increment(ref _messageID);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_messages.Dispose();
|
||||
}
|
||||
|
||||
public ILogger CreateLogger(string categoryName)
|
||||
{
|
||||
return new Logger(this, categoryName);
|
||||
}
|
||||
|
||||
public class Logger : ILogger
|
||||
{
|
||||
private readonly LoggerProvider _provider;
|
||||
private ImmutableList<object> Scopes = ImmutableList<object>.Empty;
|
||||
private readonly string _categoryName;
|
||||
|
||||
public Logger(LoggerProvider provider, string categoryName)
|
||||
{
|
||||
_categoryName = categoryName;
|
||||
_provider = provider;
|
||||
}
|
||||
|
||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
|
||||
{
|
||||
_provider._messages.OnNext(new LogMessage<TState>(_provider.NextMessageId(), logLevel, eventId, state, exception, formatter));
|
||||
}
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public IDisposable BeginScope<TState>(TState state)
|
||||
{
|
||||
Scopes = Scopes.Add(state);
|
||||
return Disposable.Create(() => Scopes = Scopes.Remove(state));
|
||||
}
|
||||
}
|
||||
|
||||
public interface ILogMessage
|
||||
{
|
||||
long MessageId { get; }
|
||||
|
||||
string ShortMessage { get; }
|
||||
}
|
||||
|
||||
record LogMessage<TState>(long MessageId, LogLevel LogLevel, EventId EventId, TState State, Exception? Exception, Func<TState, Exception?, string> Formatter) : ILogMessage
|
||||
{
|
||||
public string ShortMessage => Formatter(State, Exception);
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ namespace Wabbajack.Compiler
|
||||
private readonly FileHashCache _hashCache;
|
||||
protected readonly Context _vfs;
|
||||
private readonly TemporaryFileManager _manager;
|
||||
public readonly CompilerSettings _settings;
|
||||
public CompilerSettings _settings;
|
||||
private readonly AbsolutePath _stagingFolder;
|
||||
public readonly ParallelOptions _parallelOptions;
|
||||
|
||||
@ -72,7 +72,13 @@ namespace Wabbajack.Compiler
|
||||
|
||||
}
|
||||
|
||||
public CompilerSettings Settings { get; set; }
|
||||
public abstract Task<bool> Begin(CancellationToken token);
|
||||
|
||||
public CompilerSettings Settings
|
||||
{
|
||||
get => _settings;
|
||||
set => _settings = value;
|
||||
}
|
||||
|
||||
public Dictionary<Game, HashSet<Hash>> GameHashes { get; set; } = new Dictionary<Game, HashSet<Hash>>();
|
||||
public Dictionary<Hash, Game[]> GamesWithHashes { get; set; } = new Dictionary<Hash, Game[]>();
|
||||
|
@ -50,7 +50,7 @@ namespace Wabbajack.Compiler
|
||||
public static string DOWNLOAD_PATH_MAGIC_BACK = "{--||DOWNLOAD_PATH_MAGIC_BACK||--}";
|
||||
public static string DOWNLOAD_PATH_MAGIC_DOUBLE_BACK = "{--||DOWNLOAD_PATH_MAGIC_DOUBLE_BACK||--}";
|
||||
public static string DOWNLOAD_PATH_MAGIC_FORWARD = "{--||DOWNLOAD_PATH_MAGIC_FORWARD||--}";
|
||||
|
||||
|
||||
public static RelativePath MO2IniName => "ModOrganizer.ini".ToRelativePath();
|
||||
public static object CompilerSettings => "compiler_settings.json".ToRelativePath();
|
||||
}
|
||||
}
|
@ -21,14 +21,13 @@ namespace Wabbajack.Compiler
|
||||
{
|
||||
public class MO2Compiler : ACompiler
|
||||
{
|
||||
private readonly MO2CompilerSettings _mo2Settings;
|
||||
private MO2CompilerSettings _mo2Settings => (MO2CompilerSettings)Settings;
|
||||
|
||||
public MO2Compiler(ILogger<MO2Compiler> logger, FileExtractor.FileExtractor extractor, FileHashCache hashCache, Context vfs,
|
||||
TemporaryFileManager manager, MO2CompilerSettings settings, ParallelOptions parallelOptions, DownloadDispatcher dispatcher,
|
||||
Client wjClient, IGameLocator locator, DTOSerializer dtos, IBinaryPatchCache patchCache) :
|
||||
base(logger, extractor, hashCache, vfs, manager, settings, parallelOptions, dispatcher, wjClient, locator, dtos, patchCache)
|
||||
{
|
||||
_mo2Settings = settings;
|
||||
}
|
||||
|
||||
public AbsolutePath MO2ModsFolder => _settings.Source.Combine(Consts.MO2ModFolderName);
|
||||
@ -45,7 +44,7 @@ namespace Wabbajack.Compiler
|
||||
return mo2Folder.Combine("downloads");
|
||||
}
|
||||
|
||||
public async Task<bool> Begin(CancellationToken token)
|
||||
public override async Task<bool> Begin(CancellationToken token)
|
||||
{
|
||||
await _wjClient.SendMetric("begin_compiling", _mo2Settings.Profile);
|
||||
|
||||
|
@ -1,6 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using IniParser;
|
||||
using IniParser.Exceptions;
|
||||
using IniParser.Model;
|
||||
using IniParser.Model.Configuration;
|
||||
using IniParser.Parser;
|
||||
@ -39,5 +43,60 @@ namespace Wabbajack.Installer
|
||||
return new FileIniDataParser(IniParser()).ReadData(
|
||||
new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(file))));
|
||||
}
|
||||
|
||||
public static string FromMO2Ini(this string s)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s))
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
if (s.StartsWith("@ByteArray(") && s.EndsWith(")"))
|
||||
{
|
||||
return UnescapeUTF8(s.Substring("@ByteArray(".Length, s.Length - "@ByteArray(".Length - ")".Length));
|
||||
}
|
||||
|
||||
return UnescapeString(s);
|
||||
}
|
||||
|
||||
private static string UnescapeString(string s)
|
||||
{
|
||||
if (s.Trim().StartsWith("\"") || s.Contains("\\\\"))
|
||||
return Regex.Unescape(s.Trim('"'));
|
||||
return s;
|
||||
}
|
||||
|
||||
private static string UnescapeUTF8(string s)
|
||||
{
|
||||
var acc = new List<byte>();
|
||||
for (var i = 0; i < s.Length; i++)
|
||||
{
|
||||
var c = s[i];
|
||||
switch (c)
|
||||
{
|
||||
case '\\':
|
||||
i++;
|
||||
var nc = s[i];
|
||||
switch (nc)
|
||||
{
|
||||
case '\\':
|
||||
acc.Add((byte)'\\');
|
||||
break;
|
||||
case 'x':
|
||||
var chrs = s[i + 1] + s[i + 2].ToString();
|
||||
i += 2;
|
||||
acc.Add(Convert.ToByte(chrs, 16));
|
||||
break;
|
||||
default:
|
||||
throw new ParsingException($"Not a valid escape characer {nc}");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
acc.Add((byte)c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Encoding.UTF8.GetString(acc.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
@ -66,6 +66,8 @@ namespace Wabbajack.Paths
|
||||
}
|
||||
}
|
||||
|
||||
public int Depth => Parts.Length;
|
||||
|
||||
public AbsolutePath ReplaceExtension(Extension newExtension)
|
||||
{
|
||||
var paths = new string[Parts.Length];
|
||||
|
Loading…
Reference in New Issue
Block a user