bump version to 1.0.4.0, add WeModConfig model for backward compatibility, add feature to enable/disable automatic patch updates

This commit is contained in:
kitbyte
2025-11-06 00:48:35 +02:00
parent 8f14ee2939
commit 54fe538ed9
14 changed files with 281 additions and 105 deletions
+2 -3
View File
@@ -8,11 +8,10 @@ namespace WeModPatcher
{ {
public const string RepoName = "Wemod-Patcher"; public const string RepoName = "Wemod-Patcher";
public const string Owner = "k1tbyte"; public const string Owner = "k1tbyte";
/*public const string PatchRegistryName = "patchRegistry.json";*/
public static readonly string RepositoryUrl = $"https://github.com/{Owner}/{RepoName}"; public static readonly string RepositoryUrl = $"https://github.com/{Owner}/{RepoName}";
public static readonly Version Version; public static readonly Version Version;
public static readonly string WeModBrandName = "Wand"; public static readonly string[] WeModBrandNames = { "Wand", "WeMod" };
public static readonly string WeModExeName = "Wand.exe";
public static readonly string[] WeModRootFolders = { "WeMod", "Wand" };
// cmp dword ptr [rdx], 0 // cmp dword ptr [rdx], 0
// jnz loc_XXXXXXXX // jnz loc_XXXXXXXX
+13 -42
View File
@@ -3,8 +3,6 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using WeModPatcher.Models; using WeModPatcher.Models;
using WeModPatcher.Utils; using WeModPatcher.Utils;
using WeModPatcher.Utils.Win32; using WeModPatcher.Utils.Win32;
@@ -15,24 +13,24 @@ namespace WeModPatcher.Core
public class RuntimePatcher public class RuntimePatcher
{ {
private readonly string _exePath; private readonly WeModConfig _config;
public RuntimePatcher(string exePath) public RuntimePatcher(WeModConfig config)
{ {
_exePath = exePath; _config = config;
} }
public void StartProcess() public void StartProcess()
{ {
if(string.IsNullOrEmpty(_exePath)) if(string.IsNullOrEmpty(_config?.ExecutablePath))
{ {
throw new Exception("Path is not specified"); throw new Exception("Path is not specified");
} }
KillWeMod(); Common.TryKillProcess(_config.BrandName);
var startupInfo = new Imports.StartupInfo { cb = Marshal.SizeOf(typeof(Imports.StartupInfo)) }; var startupInfo = new Imports.StartupInfo { cb = Marshal.SizeOf(typeof(Imports.StartupInfo)) };
if(!Imports.CreateProcessA(_exePath, if(!Imports.CreateProcessA(_config.ExecutablePath,
null, null,
IntPtr.Zero, IntPtr.Zero,
IntPtr.Zero, IntPtr.Zero,
@@ -118,56 +116,29 @@ namespace WeModPatcher.Core
public static void Patch(PatchConfig config, Action<string, ELogType> logger) public static void Patch(PatchConfig config, Action<string, ELogType> logger)
{ {
if (config.Path == null) if (config.AppProps == null)
{ {
throw new Exception("Path is not specified"); throw new Exception("Path is not specified");
} }
var parent = Directory.GetParent(config.Path)?.FullName ?? config.Path; var parent = Directory.GetParent(config.AppProps.RootDirectory)?.FullName ?? config.AppProps.RootDirectory;
var latestPath = Extensions.FindLatestWeMod(parent) ?? config.Path; var latestWeModConfig = config.AutoApplyPatches ? Extensions.FindLatestWeMod(parent) ?? config.AppProps : config.AppProps;
if (!Extensions.CheckWeModPath(latestPath)) if (Extensions.CheckWeModPath(latestWeModConfig.RootDirectory) == null)
{ {
throw new Exception("Invalid WeMod path"); throw new Exception("Invalid WeMod path");
} }
if(!File.Exists(Path.Combine(latestPath, "resources", "app.asar.backup"))) if(!File.Exists(Path.Combine(latestWeModConfig.RootDirectory, "resources", "app.asar.backup")))
{ {
config.PatchMethod = EPatchProcessMethod.None; config.PatchMethod = EPatchProcessMethod.None;
new StaticPatcher(latestPath, logger, config).Patch(); new StaticPatcher(latestWeModConfig, logger, config).Patch();
} }
new RuntimePatcher(Path.Combine(latestPath, Constants.WeModExeName)) new RuntimePatcher(latestWeModConfig)
.StartProcess(); .StartProcess();
} }
public static void KillWeMod()
{
Process[] processes = Process.GetProcessesByName(Constants.WeModBrandName);
for (int i = 0; processes.Length > i || i < 5; i++)
{
foreach (var process in processes)
{
try
{
process.Kill();
}
catch
{
// ignored
}
}
processes = Process.GetProcessesByName(Constants.WeModBrandName);
Thread.Sleep(250);
}
if (processes.Length > 0)
{
throw new Exception("Failed to kill WeMod");
}
}
} }
} }
+24 -17
View File
@@ -46,25 +46,23 @@ namespace WeModPatcher.Core
} }
}; };
private readonly string _weModRootFolder; private readonly WeModConfig _weModConfig;
private readonly Action<string, ELogType> _logger; private readonly Action<string, ELogType> _logger;
private readonly PatchConfig _config; private readonly PatchConfig _config;
private readonly string _asarPath; private readonly string _asarPath;
private readonly string _backupPath; private readonly string _backupPath;
private readonly string _unpackedPath; private readonly string _unpackedPath;
private int _sumOfPatches = 0; private int _sumOfPatches = 0;
private readonly string _exePath;
public StaticPatcher(string weModRootFolder, Action<string, ELogType> logger, PatchConfig config) public StaticPatcher(WeModConfig weModConfig, Action<string, ELogType> logger, PatchConfig config)
{ {
_weModRootFolder = weModRootFolder; _weModConfig = weModConfig;
_logger = logger; _logger = logger;
_config = config; _config = config;
_asarPath = Path.Combine(weModRootFolder, "resources", "app.asar"); _asarPath = Path.Combine(weModConfig.RootDirectory, "resources", "app.asar");
_unpackedPath = Path.Combine(weModRootFolder, "resources", "app.asar.unpacked"); _unpackedPath = Path.Combine(weModConfig.RootDirectory, "resources", "app.asar.unpacked");
_backupPath = Path.Combine(weModRootFolder, "resources", "app.asar.backup"); _backupPath = Path.Combine(weModConfig.RootDirectory, "resources", "app.asar.backup");
_exePath = Path.Combine(_weModRootFolder, Constants.WeModExeName);
} }
private static string GetFetchFieldName(string targetFunction) private static string GetFetchFieldName(string targetFunction)
@@ -143,7 +141,11 @@ namespace WeModPatcher.Core
private void PatchPe() private void PatchPe()
{ {
_logger("[PATCHER] Patching PE...", ELogType.Info); _logger("[PATCHER] Patching PE...", ELogType.Info);
var patchResult = MemoryUtils.PatchFile(_exePath,Constants.ExePatchSignature, Constants.ExePatchSignature.PatchBytes); var patchResult = MemoryUtils.PatchFile(
_weModConfig.ExecutablePath,
Constants.ExePatchSignature,
Constants.ExePatchSignature.PatchBytes
);
if(patchResult == -1) if(patchResult == -1)
{ {
_logger("[PATCHER] Failed to patch PE", ELogType.Error); _logger("[PATCHER] Failed to patch PE", ELogType.Error);
@@ -161,24 +163,29 @@ namespace WeModPatcher.Core
CheckPathExists = true, CheckPathExists = true,
AddExtension = true, AddExtension = true,
SupportMultiDottedExtensions = false, SupportMultiDottedExtensions = false,
FileName = Constants.WeModBrandName, FileName = _weModConfig.BrandName,
}; };
if(fileDialog.ShowDialog() != DialogResult.OK) if(fileDialog.ShowDialog() != DialogResult.OK)
{ {
return; return;
} }
_config.Path = _weModRootFolder; _config.Path = _weModConfig.RootDirectory;
var json = JsonConvert.SerializeObject(_config, new JsonSerializerSettings
var json = JsonConvert.SerializeObject(_config, Formatting.None); {
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore,
Formatting = Formatting.None
});
Utils.Win32.Shortcut.CreateShortcut( Utils.Win32.Shortcut.CreateShortcut(
fileName: fileDialog.FileName + ".lnk", fileName: fileDialog.FileName + ".lnk",
targetPath: Assembly.GetExecutingAssembly().Location, targetPath: Assembly.GetExecutingAssembly().Location,
arguments: Extensions.Base64Encode(json), arguments: Extensions.Base64Encode(json),
workingDirectory: Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), workingDirectory: Common.GetCurrentDir(),
description: null, description: null,
iconPath: _exePath iconPath: _weModConfig.ExecutablePath
); );
_logger("[PATCHER] The shortcut has been created, now you should only run WeMod through this shortcut", ELogType.Success); _logger("[PATCHER] The shortcut has been created, now you should only run WeMod through this shortcut", ELogType.Success);
@@ -186,7 +193,7 @@ namespace WeModPatcher.Core
public void Patch() public void Patch()
{ {
RuntimePatcher.KillWeMod(); Common.TryKillProcess(_weModConfig.BrandName);
if (!File.Exists(_backupPath)) if (!File.Exists(_backupPath))
{ {
_logger("[PATCHER] Creating backup...", ELogType.Info); _logger("[PATCHER] Creating backup...", ELogType.Info);
+102 -3
View File
@@ -1,4 +1,8 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using WeModPatcher.Utils;
namespace WeModPatcher.Models namespace WeModPatcher.Models
{ {
@@ -16,11 +20,106 @@ namespace WeModPatcher.Models
Runtime = 1, Runtime = 1,
Static = 2 Static = 2
} }
public sealed class PatchConfig /*public sealed class PatchConfigOld
{ {
public HashSet<EPatchType> PatchTypes { get; set; } public HashSet<EPatchType> PatchTypes { get; set; }
public EPatchProcessMethod PatchMethod { get; set; } public EPatchProcessMethod PatchMethod { get; set; }
public string Path { get; set; } public string Path { get; set; }
}*/
public sealed class PatchConfig
{
private string _path;
public HashSet<EPatchType> PatchTypes { get; set; }
public EPatchProcessMethod PatchMethod { get; set; }
[JsonProperty("u")]
public bool AutoApplyPatches { get; set; }
[JsonIgnore]
public WeModConfig AppProps { get; private set; }
public string Path
{
get => _path;
set
{
_path = value;
AppProps = Extensions.CheckWeModPath(_path) ?? throw new Exception("Invalid WeMod path");
}
}
/*public static void PushConfig(PatchConfig config)
{
var hash = GetConfigHash(config);
var registry = _getRegistry();
registry[hash] = config;
_stashRegistry(registry);
}
public static void ActualizeRegistry()
{
var registry = _getRegistry();
foreach (var entry in registry)
{
if(Extensions.CheckWeModPath(entry.Value.AppProps.RootDirectory) == null)
{
registry.Remove(entry.Key);
break;
}
}
_stashRegistry(registry);
}
public static PatchConfig GetConfig(string hash)
{
var registry = _getRegistry();
return registry.TryGetValue(hash, out var config) ? config : null;
}
public static string GetConfigHash(PatchConfig config)
{
return Common.ComputeSha256Hash(config.AppProps.ExecutablePath);
}
private static Dictionary<string, PatchConfig> _getRegistry()
{
var currentDir = Common.GetCurrentDir();
var registryPath = Path.Combine(currentDir, Constants.PatchRegistryName);
try
{
return JsonConvert.DeserializeObject<Dictionary<string, PatchConfig>>(
File.ReadAllText(registryPath)
);
}
catch
{
// ignored
}
return new Dictionary<string, PatchConfig>();
}
private static void _stashRegistry(Dictionary<string, PatchConfig> registry)
{
var currentDir = Common.GetCurrentDir();
var registryPath = Path.Combine(currentDir, Constants.PatchRegistryName);
if(registry.Count == 0)
{
if(File.Exists(registryPath))
{
File.Delete(registryPath);
}
return;
}
var json = JsonConvert.SerializeObject(registry, Formatting.Indented);
File.WriteAllText(registryPath, json);
}*/
} }
} }
+19
View File
@@ -0,0 +1,19 @@
using Newtonsoft.Json;
namespace WeModPatcher.Models
{
public class WeModConfig
{
public string BrandName { get; set; }
public string ExecutableName { get; set; }
public string RootDirectory { get; set; }
[JsonIgnore]
public string ExecutablePath => System.IO.Path.Combine(RootDirectory, ExecutableName);
public override string ToString()
{
return RootDirectory;
}
}
}
+2
View File
@@ -2,6 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using Newtonsoft.Json; using Newtonsoft.Json;
+2 -2
View File
@@ -51,5 +51,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.3.0")] [assembly: AssemblyVersion("1.0.4.0")]
[assembly: AssemblyFileVersion("1.0.3.0")] [assembly: AssemblyFileVersion("1.0.4.0")]
+54
View File
@@ -0,0 +1,54 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading;
namespace WeModPatcher.Utils
{
public static class Common
{
public static void TryKillProcess(string processName)
{
Process[] processes = Process.GetProcessesByName(processName);
for (int i = 0; processes.Length > i || i < 5; i++)
{
foreach (var process in processes)
{
try
{
process.Kill();
}
catch
{
// ignored
}
}
processes = Process.GetProcessesByName(processName);
Thread.Sleep(250);
}
if (processes.Length > 0)
{
throw new Exception("Failed to kill WeMod");
}
}
public static string GetCurrentDir()
{
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
return Path.GetDirectoryName(assemblyLocation) ?? throw new InvalidOperationException();
}
public static string ComputeSha256Hash(string input)
{
using (var sha256 = System.Security.Cryptography.SHA256.Create())
{
var bytes = System.Text.Encoding.UTF8.GetBytes(input);
var hashBytes = sha256.ComputeHash(bytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
}
}
}
}
+27 -13
View File
@@ -2,29 +2,45 @@
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using WeModPatcher.Models;
namespace WeModPatcher.Utils namespace WeModPatcher.Utils
{ {
public static class Extensions public static class Extensions
{ {
public static bool CheckWeModPath(string root) public static WeModConfig CheckWeModPath(string versionRoot)
{ {
try try
{ {
return File.Exists(Path.Combine(root, Constants.WeModExeName)) &&
File.Exists(Path.Combine(root, "resources", "app.asar")); foreach (var name in Constants.WeModBrandNames)
{
var exeName = $"{name}.exe";
var path = Path.Combine(versionRoot, exeName);
if (File.Exists(path) && File.Exists(Path.Combine(versionRoot, "resources", "app.asar")))
{
return new WeModConfig
{
BrandName = name,
ExecutableName = exeName,
RootDirectory = versionRoot
};
}
}
} }
catch catch
{ {
return false; // ignored
} }
return null;
} }
public static string FindWeModDirectory() public static WeModConfig FindWeMod()
{ {
string localAppDataPath = Environment.GetEnvironmentVariable("LOCALAPPDATA"); string localAppDataPath = Environment.GetEnvironmentVariable("LOCALAPPDATA");
foreach (var folder in Constants.WeModRootFolders) foreach (var folder in Constants.WeModBrandNames)
{ {
var weModDir = Path.Combine(localAppDataPath ?? "", folder); var weModDir = Path.Combine(localAppDataPath ?? "", folder);
if(Directory.Exists(weModDir)) if(Directory.Exists(weModDir))
@@ -48,7 +64,7 @@ namespace WeModPatcher.Utils
return System.Convert.ToBase64String(plainTextBytes); return System.Convert.ToBase64String(plainTextBytes);
} }
public static string FindLatestWeMod(string root) public static WeModConfig FindLatestWeMod(string root)
{ {
var appFolders = Directory.EnumerateDirectories(root) var appFolders = Directory.EnumerateDirectories(root)
.Select(folderPath => new DirectoryInfo(folderPath)) .Select(folderPath => new DirectoryInfo(folderPath))
@@ -61,13 +77,11 @@ namespace WeModPatcher.Utils
}) })
.OrderByDescending(item => item.LastModified) .OrderByDescending(item => item.LastModified)
.ToList(); .ToList();
return ( return appFolders
from folder .Select(folder => CheckWeModPath(folder.Path))
in appFolders .FirstOrDefault(config => config != null);
where CheckWeModPath(folder.Path)
select folder.Path
).FirstOrDefault();
} }
} }
} }
+1 -1
View File
@@ -90,7 +90,7 @@
<Grid Margin="10" Cursor="Hand" Background="Transparent"> <Grid Margin="10" Cursor="Hand" Background="Transparent">
<TextBox Style="{StaticResource TitledTextBox}" <TextBox Style="{StaticResource TitledTextBox}"
Uid="Folder path" IsReadOnly="True" Uid="Folder path" IsReadOnly="True"
Text="{Binding WeModPath}" Text="{Binding WeModInfo.RootDirectory, Mode=OneWay}"
VerticalAlignment="Center" Tag="Folder not found"> VerticalAlignment="Center" Tag="Folder not found">
</TextBox> </TextBox>
<Grid.InputBindings> <Grid.InputBindings>
+22 -22
View File
@@ -1,13 +1,8 @@
using System; using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Threading;
using AsarSharp;
using WeModPatcher.Core; using WeModPatcher.Core;
using WeModPatcher.Models; using WeModPatcher.Models;
using WeModPatcher.ReactiveUICore; using WeModPatcher.ReactiveUICore;
@@ -24,18 +19,18 @@ namespace WeModPatcher.View.MainWindow
public ObservableCollection<LogEntry> LogList { get; set; } = new ObservableCollection<LogEntry>(); public ObservableCollection<LogEntry> LogList { get; set; } = new ObservableCollection<LogEntry>();
private static Updater _updater = new Updater(); private static Updater _updater = new Updater();
private string _weModPath; private WeModConfig _weModConfig;
public string WeModPath public WeModConfig WeModInfo
{ {
get => _weModPath; get => _weModConfig;
set set
{ {
SetProperty(ref _weModPath, value); SetProperty(ref _weModConfig, value);
if (value == null) return; if (value == null) return;
Log($"WeMod directory found at '{_weModPath}'", ELogType.Success); Log($"WeMod directory found at '{_weModConfig}' ({_weModConfig.ExecutableName})", ELogType.Success);
if (File.Exists(Path.Combine(_weModPath, "resources", "app.asar.backup"))) if (File.Exists(Path.Combine(_weModConfig.RootDirectory, "resources", "app.asar.backup")))
{ {
Log("WeMod already patched. If you want to patch again, please restore the backup first.", ELogType.Warn); Log("WeMod already patched. If you want to patch again, please restore the backup first.", ELogType.Warn);
IsPatchEnabled = false; IsPatchEnabled = false;
@@ -85,10 +80,12 @@ namespace WeModPatcher.View.MainWindow
if (dialog.ShowDialog() != DialogResult.OK) return; if (dialog.ShowDialog() != DialogResult.OK) return;
string selectedPath = dialog.SelectedPath; string selectedPath = dialog.SelectedPath;
string fileName = Path.GetFileName(selectedPath); string fileName = Path.GetFileName(selectedPath);
var info = Extensions.CheckWeModPath(selectedPath);
if (Extensions.CheckWeModPath(selectedPath)) if (info != null)
{ {
WeModPath = selectedPath; WeModInfo = info;
return; return;
} }
@@ -103,7 +100,7 @@ namespace WeModPatcher.View.MainWindow
private void OnBackupRestoring(object param) private void OnBackupRestoring(object param)
{ {
var backupPath = Path.Combine(WeModPath, "resources", "app.asar.backup"); var backupPath = Path.Combine(WeModInfo.RootDirectory, "resources", "app.asar.backup");
if (!File.Exists(backupPath)) if (!File.Exists(backupPath))
{ {
Log("Backup not found. Please dont delete it manually", ELogType.Error); Log("Backup not found. Please dont delete it manually", ELogType.Error);
@@ -119,8 +116,11 @@ namespace WeModPatcher.View.MainWindow
// This shit doesn't look at the hash and verify() always returns true // This shit doesn't look at the hash and verify() always returns true
//using X509Certificate2 cert = new X509Certificate2(X509Certificate.CreateFromSignedFile(filePath)); //using X509Certificate2 cert = new X509Certificate2(X509Certificate.CreateFromSignedFile(filePath));
var restoreExeResult = MemoryUtils.PatchFile( Path.Combine( WeModPath, Constants.WeModExeName), var restoreExeResult = MemoryUtils.PatchFile(
Constants.ExePatchSignature, Constants.ExePatchSignature.OriginalBytes); WeModInfo.ExecutablePath,
Constants.ExePatchSignature,
Constants.ExePatchSignature.OriginalBytes
);
if (restoreExeResult == -1) if (restoreExeResult == -1)
{ {
Log("Failed to restore the backup. Please close the WeMod and try again.", ELogType.Error); Log("Failed to restore the backup. Please close the WeMod and try again.", ELogType.Error);
@@ -129,7 +129,7 @@ namespace WeModPatcher.View.MainWindow
{ {
Log(restoreExeResult == 0 ? Log(restoreExeResult == 0 ?
"Signature exe is original, does not require restoration" "Signature exe is original, does not require restoration"
: $"{Constants.WeModExeName} restored successfully", ELogType.Success); : $"{WeModInfo.ExecutableName} restored successfully", ELogType.Success);
} }
} }
catch catch
@@ -138,7 +138,7 @@ namespace WeModPatcher.View.MainWindow
return; return;
} }
File.Copy(backupPath, Path.Combine(WeModPath, "resources", "app.asar"), true); File.Copy(backupPath, Path.Combine(WeModInfo.RootDirectory, "resources", "app.asar"), true);
File.Delete(backupPath); File.Delete(backupPath);
Log("Backup restored successfully.", ELogType.Success); Log("Backup restored successfully.", ELogType.Success);
AlreadyPatched = false; AlreadyPatched = false;
@@ -147,7 +147,7 @@ namespace WeModPatcher.View.MainWindow
private void OnPatching(object param) private void OnPatching(object param)
{ {
if (WeModPath == null) if (WeModInfo == null)
{ {
Log("Can't be done. Please specify the directory first.", ELogType.Warn); Log("Can't be done. Please specify the directory first.", ELogType.Warn);
return; return;
@@ -161,7 +161,7 @@ namespace WeModPatcher.View.MainWindow
{ {
try try
{ {
new StaticPatcher(WeModPath, Log, config).Patch(); new StaticPatcher(WeModInfo, Log, config).Patch();
AlreadyPatched = true; AlreadyPatched = true;
} }
catch (Exception e) catch (Exception e)
@@ -217,8 +217,8 @@ namespace WeModPatcher.View.MainWindow
RestoreBackupCommand = new RelayCommand(OnBackupRestoring); RestoreBackupCommand = new RelayCommand(OnBackupRestoring);
UpdateCommand = new AsyncRelayCommand(OnUpdate); UpdateCommand = new AsyncRelayCommand(OnUpdate);
WeModPath = Extensions.FindWeModDirectory(); WeModInfo = Extensions.FindWeMod();
if (WeModPath == null) if (WeModInfo == null)
{ {
Log("WeMod directory not found.", ELogType.Error); Log("WeMod directory not found.", ELogType.Error);
} }
@@ -23,6 +23,7 @@
<RowDefinition Height="27"/> <RowDefinition Height="27"/>
<RowDefinition Height="27"/> <RowDefinition Height="27"/>
<RowDefinition Height="27"/> <RowDefinition Height="27"/>
<RowDefinition Height="37"/>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
@@ -34,8 +35,15 @@
<TextBlock Grid.Row="2" VerticalAlignment="Center" Text="Disable updates"/> <TextBlock Grid.Row="2" VerticalAlignment="Center" Text="Disable updates"/>
<CheckBox Grid.Row="2" x:Name="DisableUpdateBox" HorizontalAlignment="Right" VerticalAlignment="Center"/> <CheckBox Grid.Row="2" x:Name="DisableUpdateBox" HorizontalAlignment="Right" VerticalAlignment="Center"/>
<TextBlock ToolTip="Disable if you want to use older versions separately and manage versions manually via different shortcuts"
ToolTipService.InitialShowDelay="300"
Grid.Row="3" VerticalAlignment="Center">
Apply the patch to new versions <LineBreak/> automatically (hover to see more)
</TextBlock>
<CheckBox Grid.Row="3" x:Name="AutoUpdates" HorizontalAlignment="Right" VerticalAlignment="Center" IsChecked="True"/>
<Button Grid.Row="3" Padding="0 5 0 5" Margin="0 15 0 0" Content="Continue" <Button Grid.Row="4" Padding="0 5 0 5" Margin="0 15 0 0" Content="Continue"
Click="NextClicked"/> Click="NextClicked"/>
</Grid> </Grid>
@@ -57,7 +57,8 @@ namespace WeModPatcher.View.Popups
_onApply(new PatchConfig _onApply(new PatchConfig
{ {
PatchTypes = result, PatchTypes = result,
PatchMethod = method PatchMethod = method,
AutoApplyPatches = AutoUpdates.IsChecked == true
}); });
} }
+2
View File
@@ -67,12 +67,14 @@
<Compile Include="Converters\ToVisibilityConverter.cs" /> <Compile Include="Converters\ToVisibilityConverter.cs" />
<Compile Include="Core\RuntimePatcher.cs" /> <Compile Include="Core\RuntimePatcher.cs" />
<Compile Include="Core\StaticPatcher.cs" /> <Compile Include="Core\StaticPatcher.cs" />
<Compile Include="Models\WeModConfig.cs" />
<Compile Include="Models\PatchConfig.cs" /> <Compile Include="Models\PatchConfig.cs" />
<Compile Include="Models\Signature.cs" /> <Compile Include="Models\Signature.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="ReactiveUICore\AsyncRelayCommand.cs" /> <Compile Include="ReactiveUICore\AsyncRelayCommand.cs" />
<Compile Include="ReactiveUICore\ObservableObject.cs" /> <Compile Include="ReactiveUICore\ObservableObject.cs" />
<Compile Include="ReactiveUICore\RelayCommand.cs" /> <Compile Include="ReactiveUICore\RelayCommand.cs" />
<Compile Include="Utils\Common.cs" />
<Compile Include="Utils\Extensions.cs" /> <Compile Include="Utils\Extensions.cs" />
<Compile Include="Utils\MemoryUtils.cs" /> <Compile Include="Utils\MemoryUtils.cs" />
<Compile Include="Utils\Updater.cs" /> <Compile Include="Utils\Updater.cs" />