diff --git a/Wabbajack.Common/Utils.cs b/Wabbajack.Common/Utils.cs index 697bc6b3..937f932a 100644 --- a/Wabbajack.Common/Utils.cs +++ b/Wabbajack.Common/Utils.cs @@ -129,5 +129,59 @@ namespace Wabbajack.Common } } + public static List PMap(this IEnumerable coll, Func f) + { + var tasks = coll.Select(i => + { + TaskCompletionSource tc = new TaskCompletionSource(); + WorkQueue.QueueTask(() => + { + try + { + tc.SetResult(f(i)); + } + catch (Exception ex) + { + tc.SetException(ex); + } + }); + return tc.Task; + }).ToList(); + + return tasks.Select(t => + { + t.Wait(); + return t.Result; + }).ToList(); + } + + public static void PMap(this IEnumerable coll, Action f) + { + var tasks = coll.Select(i => + { + TaskCompletionSource tc = new TaskCompletionSource(); + WorkQueue.QueueTask(() => + { + try + { + f(i); + tc.SetResult(true); + } + catch (Exception ex) + { + tc.SetException(ex); + } + }); + return tc.Task; + }).ToList(); + + tasks.Select(t => + { + t.Wait(); + return t.Result; + }).ToList(); + return; + } + } } diff --git a/Wabbajack.Common/Wabbajack.Common.csproj b/Wabbajack.Common/Wabbajack.Common.csproj index 095b9fc2..86d1b20f 100644 --- a/Wabbajack.Common/Wabbajack.Common.csproj +++ b/Wabbajack.Common/Wabbajack.Common.csproj @@ -60,6 +60,7 @@ + diff --git a/Wabbajack.Common/WorkQueue.cs b/Wabbajack.Common/WorkQueue.cs new file mode 100644 index 00000000..3ed1155d --- /dev/null +++ b/Wabbajack.Common/WorkQueue.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Wabbajack.Common +{ + public class WorkQueue + { + private static BlockingCollection Queue = new BlockingCollection(); + + [ThreadStatic] + private static int CpuId; + + public static void Init(Action report_function) + { + ReportFunction = report_function; + ThreadCount = Environment.ProcessorCount; + StartThreads(); + } + + private static void StartThreads() + { + Threads = Enumerable.Range(0, ThreadCount) + .Select(idx => + { + var thread = new Thread(() => ThreadBody(idx)); + thread.Priority = ThreadPriority.BelowNormal; + thread.IsBackground = true; + thread.Name = String.Format("Wabbajack_Worker_{0}", idx); + thread.Start(); + return thread; + }).ToList(); + } + + private static void ThreadBody(int idx) + { + CpuId = idx; + + while(true) + { + Report("Waiting", 0); + var f = Queue.Take(); + f(); + } + + } + public static void Report(string msg, int progress) + { + ReportFunction(CpuId, msg, progress); + } + + public static void QueueTask(Action a) + { + Queue.Add(a); + } + + public static Action ReportFunction { get; private set; } + public static int ThreadCount { get; private set; } + public static List Threads { get; private set; } + } +} diff --git a/Wabbajack.sln b/Wabbajack.sln index ddc035ba..97d8040c 100644 --- a/Wabbajack.sln +++ b/Wabbajack.sln @@ -3,24 +3,20 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29102.190 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack", "Wabbajack\Wabbajack.csproj", "{1649CAB3-6F8E-4F2E-844C-931BD4B61233}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Common", "Wabbajack.Common\Wabbajack.Common.csproj", "{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BSA.Tools", "BSA.Tools\BSA.Tools.csproj", "{B6389807-EA59-4633-B42B-A85F52FEC135}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SevenZipExtractor", "SevenZipExtractor\SevenZipExtractor.csproj", "{8AA97F58-5044-4BBA-B8D9-A74B6947A660}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack", "Wabbajack\Wabbajack.csproj", "{33602679-8484-40C7-A10C-774DFF5D8314}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1649CAB3-6F8E-4F2E-844C-931BD4B61233}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1649CAB3-6F8E-4F2E-844C-931BD4B61233}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1649CAB3-6F8E-4F2E-844C-931BD4B61233}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1649CAB3-6F8E-4F2E-844C-931BD4B61233}.Release|Any CPU.Build.0 = Release|Any CPU {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug|Any CPU.Build.0 = Debug|Any CPU {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -33,6 +29,10 @@ Global {8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug|Any CPU.Build.0 = Debug|Any CPU {8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Release|Any CPU.ActiveCfg = Release|Any CPU {8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Release|Any CPU.Build.0 = Release|Any CPU + {33602679-8484-40C7-A10C-774DFF5D8314}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {33602679-8484-40C7-A10C-774DFF5D8314}.Debug|Any CPU.Build.0 = Debug|Any CPU + {33602679-8484-40C7-A10C-774DFF5D8314}.Release|Any CPU.ActiveCfg = Release|Any CPU + {33602679-8484-40C7-A10C-774DFF5D8314}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Wabbajack/App.xaml b/Wabbajack/App.xaml new file mode 100644 index 00000000..9f16f10f --- /dev/null +++ b/Wabbajack/App.xaml @@ -0,0 +1,8 @@ + + + + diff --git a/Wabbajack/App.xaml.cs b/Wabbajack/App.xaml.cs new file mode 100644 index 00000000..90cf0503 --- /dev/null +++ b/Wabbajack/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace Wabbajack +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/Wabbajack/AppState.cs b/Wabbajack/AppState.cs new file mode 100644 index 00000000..f99e4510 --- /dev/null +++ b/Wabbajack/AppState.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Reflection; +using System.Threading; +using System.Windows.Threading; +using Wabbajack.Common; + +namespace Wabbajack +{ + internal class AppState + { + public class CPUStatus + { + public int Progress { get; internal set; } + public string Msg { get; internal set; } + public int ID { get; internal set; } + } + + public volatile bool Dirty; + + private Dispatcher dispatcher; + + public ObservableCollection Log { get; } + public ObservableCollection Status { get; } + + + public String Mode { get; set; } + + private List InternalStatus { get; } + public string LogFile { get; private set; } + + public AppState(Dispatcher d, String mode) + { + LogFile = Assembly.GetExecutingAssembly().Location + ".log"; + + if (LogFile.FileExists()) + File.Delete(LogFile); + + Mode = mode; + Dirty = false; + dispatcher = d; + Log = new ObservableCollection(); + Status = new ObservableCollection(); + InternalStatus = new List(); + + var th = new Thread(() => UpdateLoop()); + th.Priority = ThreadPriority.BelowNormal; + th.IsBackground = true; + th.Start(); + } + + private void UpdateLoop() + { + while (true) + { + if (Dirty) + { + lock (InternalStatus) + { + var data = InternalStatus.ToArray(); + dispatcher.Invoke(() => + { + for (int idx = 0; idx < data.Length; idx += 1) + { + if (idx >= Status.Count) + Status.Add(data[idx]); + else if (Status[idx] != data[idx]) + Status[idx] = data[idx]; + } + }); + Dirty = false; + } + } + Thread.Sleep(250); + } + } + + public void LogMsg(string msg) + { + dispatcher.Invoke(() => Log.Add(msg)); + lock (dispatcher) { + File.AppendAllText(LogFile, msg + "\r\n"); + } + } + + public void SetProgress(int id, string msg, int progress) + { + lock (InternalStatus) + { + Dirty = true; + while (id >= InternalStatus.Count) + { + InternalStatus.Add(new CPUStatus()); + } + + InternalStatus[id] = new CPUStatus() { ID = id, Msg = msg, Progress = progress }; + } + } + } +} \ No newline at end of file diff --git a/Wabbajack/AutoScrollBehavior.cs b/Wabbajack/AutoScrollBehavior.cs new file mode 100644 index 00000000..1c46151f --- /dev/null +++ b/Wabbajack/AutoScrollBehavior.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; + +namespace Wabbajack +{ + class AutoScrollBehavior + { + static readonly Dictionary Associations = + new Dictionary(); + + public static bool GetScrollOnNewItem(DependencyObject obj) + { + return (bool)obj.GetValue(ScrollOnNewItemProperty); + } + + public static void SetScrollOnNewItem(DependencyObject obj, bool value) + { + obj.SetValue(ScrollOnNewItemProperty, value); + } + + public static readonly DependencyProperty ScrollOnNewItemProperty = + DependencyProperty.RegisterAttached( + "ScrollOnNewItem", + typeof(bool), + typeof(AutoScrollBehavior), + new UIPropertyMetadata(false, OnScrollOnNewItemChanged)); + + public static void OnScrollOnNewItemChanged( + DependencyObject d, + DependencyPropertyChangedEventArgs e) + { + var listBox = d as ListBox; + if (listBox == null) return; + bool oldValue = (bool)e.OldValue, newValue = (bool)e.NewValue; + if (newValue == oldValue) return; + if (newValue) + { + listBox.Loaded += ListBox_Loaded; + listBox.Unloaded += ListBox_Unloaded; + var itemsSourcePropertyDescriptor = TypeDescriptor.GetProperties(listBox)["ItemsSource"]; + itemsSourcePropertyDescriptor.AddValueChanged(listBox, ListBox_ItemsSourceChanged); + } + else + { + listBox.Loaded -= ListBox_Loaded; + listBox.Unloaded -= ListBox_Unloaded; + if (Associations.ContainsKey(listBox)) + Associations[listBox].Dispose(); + var itemsSourcePropertyDescriptor = TypeDescriptor.GetProperties(listBox)["ItemsSource"]; + itemsSourcePropertyDescriptor.RemoveValueChanged(listBox, ListBox_ItemsSourceChanged); + } + } + + private static void ListBox_ItemsSourceChanged(object sender, EventArgs e) + { + var listBox = (ListBox)sender; + if (Associations.ContainsKey(listBox)) + Associations[listBox].Dispose(); + Associations[listBox] = new Capture(listBox); + } + + static void ListBox_Unloaded(object sender, RoutedEventArgs e) + { + var listBox = (ListBox)sender; + if (Associations.ContainsKey(listBox)) + Associations[listBox].Dispose(); + listBox.Unloaded -= ListBox_Unloaded; + } + + static void ListBox_Loaded(object sender, RoutedEventArgs e) + { + var listBox = (ListBox)sender; + var incc = listBox.Items as INotifyCollectionChanged; + if (incc == null) return; + listBox.Loaded -= ListBox_Loaded; + Associations[listBox] = new Capture(listBox); + } + + class Capture : IDisposable + { + private readonly ListBox listBox; + private readonly INotifyCollectionChanged incc; + + public Capture(ListBox listBox) + { + this.listBox = listBox; + incc = listBox.ItemsSource as INotifyCollectionChanged; + if (incc != null) + { + incc.CollectionChanged += incc_CollectionChanged; + } + } + + void incc_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (e.Action == NotifyCollectionChangedAction.Add) + { + listBox.ScrollIntoView(e.NewItems[0]); + listBox.SelectedItem = e.NewItems[0]; + } + } + + public void Dispose() + { + if (incc != null) + incc.CollectionChanged -= incc_CollectionChanged; + } + } + } +} diff --git a/Wabbajack/Compiler.cs b/Wabbajack/Compiler.cs index 3c30c2d4..c22bf6c9 100644 --- a/Wabbajack/Compiler.cs +++ b/Wabbajack/Compiler.cs @@ -1,5 +1,4 @@ -using Murmur; -using Newtonsoft.Json; +using Newtonsoft.Json; using SevenZipExtractor; using System; using System.Collections.Generic; @@ -24,31 +23,15 @@ namespace Wabbajack public dynamic MO2Ini { get; } public string GamePath { get; } - public string MO2DownloadsFolder { + public string MO2DownloadsFolder + { get { return Path.Combine(MO2Folder, "downloads"); } } - internal void PatchExecutable() - { - var data = JsonConvert.SerializeObject(InstallDirectives).BZip2String(); - var executable = Assembly.GetExecutingAssembly().Location; - var out_path = Path.Combine(Path.GetDirectoryName(executable), "out.exe"); - File.Copy(executable, out_path, true); - using(var os = File.OpenWrite(out_path)) - using(var bw = new BinaryWriter(os)) - { - long orig_pos = os.Length; - os.Position = os.Length; - bw.Write(data.LongLength); - bw.Write(data); - bw.Write(orig_pos); - bw.Write(Encoding.ASCII.GetBytes(Consts.ModPackMagic)); - } - } public string MO2Profile; @@ -61,7 +44,6 @@ namespace Wabbajack } public Action Log_Fn { get; } - public Action Progress_Function { get; } public List InstallDirectives { get; private set; } public List SelectedArchives { get; private set; } public List AllFiles { get; private set; } @@ -75,6 +57,14 @@ namespace Wabbajack Log_Fn(msg); } + public void Status(string msg, params object[] args) + { + if (args.Length > 0) + msg = String.Format(msg, args); + WorkQueue.Report(msg, 0); + } + + private void Error(string msg, params object[] args) { if (args.Length > 0) @@ -83,24 +73,21 @@ namespace Wabbajack throw new Exception(msg); } - public Compiler(string mo2_folder, Action log_fn, Action progress_function) + public Compiler(string mo2_folder, Action log_fn) { MO2Folder = mo2_folder; Log_Fn = log_fn; - Progress_Function = progress_function; MO2Ini = Path.Combine(MO2Folder, "ModOrganizer.ini").LoadIniFile(); GamePath = ((string)MO2Ini.General.gamePath).Replace("\\\\", "\\"); } - + public void LoadArchives() { IndexedArchives = Directory.EnumerateFiles(MO2DownloadsFolder) .Where(file => SupportedArchives.Contains(Path.GetExtension(file))) - .AsParallel() - .Select(file => LoadArchive(file)) - .ToList(); + .PMap(file => LoadArchive(file)); } private IndexedArchive LoadArchive(string file) @@ -109,6 +96,7 @@ namespace Wabbajack if (metaname.FileExists() && new FileInfo(metaname).LastWriteTime >= new FileInfo(file).LastWriteTime) { + Status("Loading Archive Index for {0}", Path.GetFileName(file)); var info = metaname.FromJSON(); info.Name = Path.GetFileName(file); info.AbsolutePath = file; @@ -125,6 +113,7 @@ namespace Wabbajack using (var ar = new ArchiveFile(file)) { + Status("Indexing {0}", Path.GetFileName(file)); var streams = new Dictionary(); ar.Extract(entry => { if (entry.IsFolder) return null; @@ -170,7 +159,8 @@ namespace Wabbajack var stack = MakeStack(); - var results = AllFiles.AsParallel().Select(f => RunStack(stack, f)).ToList(); + Info("Running Compilation Stack"); + var results = AllFiles.PMap(f => RunStack(stack, f)).ToList(); var nomatch = results.OfType(); Info("No match for {0} files", nomatch.Count()); @@ -181,9 +171,9 @@ namespace Wabbajack GatherArchives(); BuildPatches(); - - results.ToJSON("out.json"); - + PatchExecutable(); + + Info("Done Building Modpack"); } @@ -198,13 +188,13 @@ namespace Wabbajack Info("Patching building patches from {0} archives", groups.Count); var absolute_paths = AllFiles.ToDictionary(e => e.Path, e => e.AbsolutePath); - Parallel.ForEach(groups, group => BuildArchivePatches(group.Key, group, absolute_paths)); + groups.PMap(group => BuildArchivePatches(group.Key, group, absolute_paths)); if (InstallDirectives.OfType().FirstOrDefault(f => f.Patch == null) != null) { Error("Missing patches after generation, this should not happen"); } - + } private void BuildArchivePatches(string archive_sha, IEnumerable group, Dictionary absolute_paths) @@ -212,22 +202,23 @@ namespace Wabbajack var archive = IndexedArchives.First(a => a.Hash == archive_sha); var paths = group.Select(g => g.From).ToHashSet(); var streams = new Dictionary(); - Info("Etracting Patch Files from {0}", archive.Name); + Status("Etracting Patch Files from {0}", archive.Name); // First we fetch the source files from the input archive using (var a = new ArchiveFile(archive.AbsolutePath)) { a.Extract(entry => { - if (!paths.Contains(entry.FileName)) return null; + if (!paths.Contains(entry.FileName)) return null; - var result = new MemoryStream(); - streams.Add(entry.FileName, result); - return result; + var result = new MemoryStream(); + streams.Add(entry.FileName, result); + return result; }, false); } var extracted = streams.ToDictionary(k => k.Key, v => v.Value.ToArray()); // Now Create the patches + Status("Building Patches for {0}", archive.Name); Parallel.ForEach(group, entry => { Info("Patching {0}", entry.To); @@ -259,7 +250,7 @@ namespace Wabbajack private Archive ResolveArchive(string sha, Dictionary archives) { - if(archives.TryGetValue(sha, out var found)) + if (archives.TryGetValue(sha, out var found)) { if (found.IniData == null) Error("No download metadata found for {0}, please use MO2 to query info or add a .meta file and try again.", found.Name); @@ -271,10 +262,12 @@ namespace Wabbajack if (general.modID != null && general.fileID != null && general.gameName != null) { - result = new NexusMod() { + result = new NexusMod() + { GameName = general.gameName, FileID = general.fileID, - ModID = general.modID}; + ModID = general.modID + }; } else if (general.directURL != null) { @@ -302,6 +295,7 @@ namespace Wabbajack private Directive RunStack(IEnumerable> stack, RawSourceFile source) { + Status("Compiling {0}", source.Path); return (from f in stack let result = f(source) where result != null @@ -475,7 +469,7 @@ namespace Wabbajack var result = source.EvolveTo(); result.Reason = "No Match in Stack"; return result; - }; + }; } private Func DirectMatch() @@ -488,7 +482,6 @@ namespace Wabbajack return source => { - Info("Hashing {0}", source.Path); if (indexed.TryGetValue(source.Hash, out var found)) { var result = source.EvolveTo(); @@ -518,5 +511,24 @@ namespace Wabbajack return null; }; } + + internal void PatchExecutable() + { + var data = JsonConvert.SerializeObject(InstallDirectives).BZip2String(); + var executable = Assembly.GetExecutingAssembly().Location; + var out_path = Path.Combine(Path.GetDirectoryName(executable), MO2Profile + ".exe"); + Info("Patching Executable {0}", Path.GetFileName(out_path)); + File.Copy(executable, out_path, true); + using (var os = File.OpenWrite(out_path)) + using (var bw = new BinaryWriter(os)) + { + long orig_pos = os.Length; + os.Position = os.Length; + bw.Write(data.LongLength); + bw.Write(data); + bw.Write(orig_pos); + bw.Write(Encoding.ASCII.GetBytes(Consts.ModPackMagic)); + } + } } } diff --git a/Wabbajack/MainWindow.xaml b/Wabbajack/MainWindow.xaml new file mode 100644 index 00000000..960a2936 --- /dev/null +++ b/Wabbajack/MainWindow.xaml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Wabbajack/MainWindow.xaml.cs b/Wabbajack/MainWindow.xaml.cs new file mode 100644 index 00000000..2a1e2153 --- /dev/null +++ b/Wabbajack/MainWindow.xaml.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +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 Wabbajack.Common; + +namespace Wabbajack +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + var context = new AppState(Dispatcher, "Building"); + WorkQueue.Init((id, msg, progress) => context.SetProgress(id, msg, progress)); + + var compiler = new Compiler("c:\\Mod Organizer 2", msg => context.LogMsg(msg)); + new Thread(() => + { + compiler.LoadArchives(); + compiler.MO2Profile = "Lexy's Legacy of The Dragonborn Special Edition"; + compiler.Compile(); + }).Start(); + + + this.DataContext = context; + + } + } +} diff --git a/Wabbajack/Program.cs b/Wabbajack/Program.cs deleted file mode 100644 index 06f2e4f4..00000000 --- a/Wabbajack/Program.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Wabbajack.Common; - -namespace Wabbajack -{ - class Program - { - static void Main(string[] args) - { - var modpack = CheckForModPack(); - if (modpack != null) - { - Console.WriteLine(modpack); - Thread.Sleep(10000); - return; - } - - var compiler = new Compiler("c:\\Mod Organizer 2", msg => Console.WriteLine(msg), (msg, id, prog) => Console.WriteLine(msg)); - compiler.LoadArchives(); - compiler.MO2Profile = "Lexy's Legacy of The Dragonborn Special Edition"; - compiler.Compile(); - compiler.PatchExecutable(); - - } - - private static string CheckForModPack() - { - using (var s = File.OpenRead(Assembly.GetExecutingAssembly().Location)) - { - var magic_bytes = Encoding.ASCII.GetBytes(Consts.ModPackMagic); - s.Position = s.Length - magic_bytes.Length; - using (var br = new BinaryReader(s)) - { - var bytes = br.ReadBytes(magic_bytes.Length); - var magic = Encoding.ASCII.GetString(bytes); - if (magic != Consts.ModPackMagic) - { - return null; - } - - s.Position = s.Length - magic_bytes.Length - 8; - var start_pos = br.ReadInt64(); - s.Position = start_pos; - long length = br.ReadInt64(); - - return br.ReadBytes((int)length).BZip2String(); - - } - } - } - } -} diff --git a/Wabbajack/Properties/AssemblyInfo.cs b/Wabbajack/Properties/AssemblyInfo.cs index 702339de..72bb216a 100644 --- a/Wabbajack/Properties/AssemblyInfo.cs +++ b/Wabbajack/Properties/AssemblyInfo.cs @@ -1,6 +1,8 @@ using System.Reflection; +using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Windows; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information @@ -19,8 +21,25 @@ using System.Runtime.InteropServices; // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("1649cab3-6f8e-4f2e-844c-931bd4b61233")] +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + // Version information for an assembly consists of the following four values: // diff --git a/Wabbajack/Properties/Resources.Designer.cs b/Wabbajack/Properties/Resources.Designer.cs index ab5f14c9..0827b61c 100644 --- a/Wabbajack/Properties/Resources.Designer.cs +++ b/Wabbajack/Properties/Resources.Designer.cs @@ -8,10 +8,10 @@ // //------------------------------------------------------------------------------ -namespace Wabbajack.Properties { - using System; - - +namespace Wabbajack.Properties +{ + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -19,54 +19,53 @@ namespace Wabbajack.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - + internal class Resources + { + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { + internal Resources() + { } - + /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Wabbajack.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { + internal static global::System.Globalization.CultureInfo Culture + { + get + { return resourceCulture; } - set { + set + { resourceCulture = value; } } - - /// - /// Looks up a localized string similar to . - /// - internal static string ModPack { - get { - return ResourceManager.GetString("ModPack", resourceCulture); - } - } } } diff --git a/Wabbajack/Properties/Resources.resx b/Wabbajack/Properties/Resources.resx index c1567b33..af7dbebb 100644 --- a/Wabbajack/Properties/Resources.resx +++ b/Wabbajack/Properties/Resources.resx @@ -46,7 +46,7 @@ mimetype: application/x-microsoft.net.object.binary.base64 value : The object must be serialized with - : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : System.Serialization.Formatters.Binary.BinaryFormatter : and then encoded with base64 encoding. mimetype: application/x-microsoft.net.object.soap.base64 @@ -60,7 +60,6 @@ : and then encoded with base64 encoding. --> - @@ -69,10 +68,9 @@ - + - @@ -87,10 +85,9 @@ - + - @@ -112,12 +109,9 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - \ No newline at end of file diff --git a/Wabbajack/Properties/Settings.Designer.cs b/Wabbajack/Properties/Settings.Designer.cs new file mode 100644 index 00000000..776cd400 --- /dev/null +++ b/Wabbajack/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Wabbajack.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Wabbajack/Properties/Settings.settings b/Wabbajack/Properties/Settings.settings new file mode 100644 index 00000000..033d7a5e --- /dev/null +++ b/Wabbajack/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Wabbajack/Wabbajack.csproj b/Wabbajack/Wabbajack.csproj index 5a4f2e42..8da3b5f9 100644 --- a/Wabbajack/Wabbajack.csproj +++ b/Wabbajack/Wabbajack.csproj @@ -5,12 +5,14 @@ Debug AnyCPU - {1649CAB3-6F8E-4F2E-844C-931BD4B61233} - Exe + {33602679-8484-40C7-A10C-774DFF5D8314} + WinExe Wabbajack Wabbajack v4.7.2 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 true true @@ -39,39 +41,77 @@ ..\packages\Costura.Fody.4.0.0\lib\net40\Costura.dll - - ..\packages\murmurhash.1.0.3\lib\net45\MurmurHash.dll - ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll + + + - - - + + 4.0 + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + - - + + MainWindow.xaml + Code + + + + + Code + True True Resources.resx + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + - - - - + + {b6389807-ea59-4633-b42b-a85f52fec135} + BSA.Tools + {8aa97f58-5044-4bba-b8d9-a74b6947a660} SevenZipExtractor @@ -81,19 +121,13 @@ Wabbajack.Common - - - ResXFileCodeGenerator - Resources.Designer.cs - - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + - \ No newline at end of file diff --git a/Wabbajack/packages.config b/Wabbajack/packages.config index b65cc07a..d3422849 100644 --- a/Wabbajack/packages.config +++ b/Wabbajack/packages.config @@ -2,6 +2,5 @@ - \ No newline at end of file