diff --git a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs index 3b72b5c5..c1c2bf34 100644 --- a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs +++ b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs @@ -42,8 +42,6 @@ public class AutoDomainTask private readonly AutoDomainConfig _config; - private bool IsRunning { get; set; } - public AutoDomainTask(AutoDomainParam taskParam) { _taskParam = taskParam; @@ -54,13 +52,20 @@ public class AutoDomainTask _clickOffset = new ClickOffset(captureArea.X, captureArea.Y, assetScale); _combatCommands = CombatScriptParser.Parse(_taskParam.CombatStrategyContent); _config = TaskContext.Instance().Config.AutoDomainConfig; - IsRunning = false; } public async void Start() { + var hasLock = false; try { + Monitor.TryEnter(TaskContext.TaskLocker, ref hasLock); + if (!hasLock) + { + Logger.LogError("启动自动秘境功能失败:当前存在正在运行中的独立任务,请不要重复执行任务!"); + return; + } + Init(); var combatScenes = new CombatScenes().InitializeTeam(GetContentFromDispatcher()); @@ -125,13 +130,16 @@ public class AutoDomainTask TaskTriggerDispatcher.Instance().SetCacheCaptureMode(DispatcherCaptureModeEnum.OnlyTrigger); TaskSettingsPageViewModel.SetSwitchAutoDomainButtonText(false); Logger.LogInformation("→ {Text}", "自动秘境结束"); - IsRunning = false; + + if (hasLock) + { + Monitor.Exit(TaskContext.TaskLocker); + } } } private void Init() { - IsRunning = true; LogScreenResolution(); if (_taskParam.DomainRoundNum == 9999) { @@ -374,7 +382,6 @@ public class AutoDomainTask return false; } - /// /// 旋转视角后寻找石化古树 /// @@ -665,10 +672,8 @@ public class AutoDomainTask Sleep(800, _taskParam.Cts); } - Sleep(1000, _taskParam.Cts); - var captureArea = TaskContext.Instance().SystemInfo.CaptureAreaRect; for (var i = 0; i < 30; i++) { @@ -757,4 +762,4 @@ public class AutoDomainTask Logger.LogInformation("剩余:浓缩树脂 {CondensedResinCount} 脆弱树脂 {FragileResinCount}", condensedResinCount, fragileResinCount); return (condensedResinCount, fragileResinCount); } -} \ No newline at end of file +} diff --git a/BetterGenshinImpact/GameTask/AutoFight/AutoFightTask.cs b/BetterGenshinImpact/GameTask/AutoFight/AutoFightTask.cs index 59bde555..dea23e5d 100644 --- a/BetterGenshinImpact/GameTask/AutoFight/AutoFightTask.cs +++ b/BetterGenshinImpact/GameTask/AutoFight/AutoFightTask.cs @@ -7,6 +7,7 @@ using BetterGenshinImpact.ViewModel.Pages; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using static BetterGenshinImpact.GameTask.Common.TaskControl; using static Vanara.PInvoke.Gdi32; @@ -27,8 +28,16 @@ public class AutoFightTask public async void Start() { + var hasLock = false; try { + Monitor.TryEnter(TaskContext.TaskLocker, ref hasLock); + if (!hasLock) + { + Logger.LogError("启动自动战斗功能失败:当前存在正在运行中的独立任务,请不要重复执行任务!"); + return; + } + Init(); var combatScenes = new CombatScenes().InitializeTeam(GetContentFromDispatcher()); if (!combatScenes.CheckTeamInitialized()) @@ -78,6 +87,11 @@ public class AutoFightTask TaskTriggerDispatcher.Instance().SetCacheCaptureMode(DispatcherCaptureModeEnum.OnlyTrigger); TaskSettingsPageViewModel.SetSwitchAutoFightButtonText(false); Logger.LogInformation("→ {Text}", "自动战斗结束"); + + if (hasLock) + { + Monitor.Exit(TaskContext.TaskLocker); + } } } @@ -98,4 +112,4 @@ public class AutoFightTask Logger.LogWarning("游戏窗口分辨率不是 1920x1080 !当前分辨率为 {Width}x{Height} , 非 1920x1080 分辨率的游戏可能无法正常使用自动战斗功能 !", gameScreenSize.Width, gameScreenSize.Height); } } -} \ No newline at end of file +} diff --git a/BetterGenshinImpact/GameTask/AutoGeniusInvokation/Model/Duel.cs b/BetterGenshinImpact/GameTask/AutoGeniusInvokation/Model/Duel.cs index 13b50ff2..9364c457 100644 --- a/BetterGenshinImpact/GameTask/AutoGeniusInvokation/Model/Duel.cs +++ b/BetterGenshinImpact/GameTask/AutoGeniusInvokation/Model/Duel.cs @@ -59,9 +59,17 @@ public class Duel public void Run(GeniusInvokationTaskParam taskParam) { + var hasLock = false; Cts = taskParam.Cts; try { + Monitor.TryEnter(TaskContext.TaskLocker, ref hasLock); + if (!hasLock) + { + _logger.LogError("启动自动七圣召唤功能失败:当前存在正在运行中的独立任务,请不要重复执行任务!"); + return; + } + LogScreenResolution(); _logger.LogInformation("========================================"); _logger.LogInformation("→ {Text}", "全自动七圣召唤,启动!"); @@ -312,6 +320,11 @@ public class Duel TaskSettingsPageViewModel.SetSwitchAutoGeniusInvokationButtonText(false); _logger.LogInformation("← {Text}", "退出全自动七圣召唤"); taskParam.Dispatcher.StartTimer(); + + if (hasLock) + { + Monitor.Exit(TaskContext.TaskLocker); + } } } diff --git a/BetterGenshinImpact/GameTask/AutoWood/AutoWoodTask.cs b/BetterGenshinImpact/GameTask/AutoWood/AutoWoodTask.cs index 99162131..4e2650db 100644 --- a/BetterGenshinImpact/GameTask/AutoWood/AutoWoodTask.cs +++ b/BetterGenshinImpact/GameTask/AutoWood/AutoWoodTask.cs @@ -11,6 +11,7 @@ using Microsoft.Extensions.Logging; using System; using System.Diagnostics; using System.Linq; +using System.Threading; using static BetterGenshinImpact.GameTask.Common.TaskControl; using static Vanara.PInvoke.User32; @@ -41,8 +42,16 @@ public class AutoWoodTask public void Start(WoodTaskParam taskParam) { + var hasLock = false; try { + Monitor.TryEnter(TaskContext.TaskLocker, ref hasLock); + if (!hasLock) + { + Logger.LogError("启动自动伐木功能失败:当前存在正在运行中的独立任务,请不要重复执行任务!"); + return; + } + TaskTriggerDispatcher.Instance().StopTimer(); Logger.LogInformation("→ {Text} 设置伐木总次数:{Cnt}", "自动伐木,启动!", taskParam.WoodRoundNum); @@ -97,6 +106,11 @@ public class AutoWoodTask TaskSettingsPageViewModel.SetSwitchAutoWoodButtonText(false); Logger.LogInformation("← {Text}", "退出自动伐木"); taskParam.Dispatcher.StartTimer(); + + if (hasLock) + { + Monitor.Exit(TaskContext.TaskLocker); + } } } diff --git a/BetterGenshinImpact/GameTask/TaskContext.cs b/BetterGenshinImpact/GameTask/TaskContext.cs index e639f680..6f6ed060 100644 --- a/BetterGenshinImpact/GameTask/TaskContext.cs +++ b/BetterGenshinImpact/GameTask/TaskContext.cs @@ -13,7 +13,7 @@ namespace BetterGenshinImpact.GameTask public class TaskContext { private static TaskContext? _uniqueInstance; - private static readonly object Locker = new(); + private static readonly object InstanceLocker = new(); private TaskContext() { @@ -23,7 +23,7 @@ namespace BetterGenshinImpact.GameTask { if (_uniqueInstance == null) { - lock (Locker) + lock (InstanceLocker) { _uniqueInstance ??= new TaskContext(); } @@ -41,6 +41,8 @@ namespace BetterGenshinImpact.GameTask IsInitialized = true; } + public static readonly object TaskLocker = new(); + public bool IsInitialized { get; set; } public IntPtr GameHandle { get; set; } @@ -49,10 +51,8 @@ namespace BetterGenshinImpact.GameTask public float DpiScale { get; set; } - public SystemInfo SystemInfo { get; set; } - public AllConfig Config { get @@ -74,4 +74,4 @@ namespace BetterGenshinImpact.GameTask /// public DateTime LinkedStartGenshinTime { get; set; } = DateTime.MinValue; } -} \ No newline at end of file +} diff --git a/BetterGenshinImpact/GameTask/TaskTriggerDispatcher.cs b/BetterGenshinImpact/GameTask/TaskTriggerDispatcher.cs index 2e9db443..f3c389f9 100644 --- a/BetterGenshinImpact/GameTask/TaskTriggerDispatcher.cs +++ b/BetterGenshinImpact/GameTask/TaskTriggerDispatcher.cs @@ -1,4 +1,5 @@ -using BetterGenshinImpact.GameTask.AutoDomain; +using BetterGenshinImpact.Core.Config; +using BetterGenshinImpact.GameTask.AutoDomain; using BetterGenshinImpact.GameTask.AutoFight; using BetterGenshinImpact.GameTask.AutoGeniusInvokation; using BetterGenshinImpact.GameTask.AutoWood; @@ -9,21 +10,18 @@ using BetterGenshinImpact.Helpers; using BetterGenshinImpact.View; using Fischless.GameCapture; using Microsoft.Extensions.Logging; +using OpenCvSharp; +using OpenCvSharp.Extensions; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; +using System.Drawing.Imaging; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using BetterGenshinImpact.Core.Config; using Vanara.PInvoke; -using System.IO; -using System.Drawing.Imaging; -using OpenCvSharp; -using OpenCvSharp.Extensions; -using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrackBar; -using Point = OpenCvSharp.Point; namespace BetterGenshinImpact.GameTask { @@ -308,7 +306,6 @@ namespace BetterGenshinImpact.GameTask return; } - var speedTimer = new SpeedTimer(); // 捕获游戏画面 var bitmap = GameCapture.Capture(); @@ -484,4 +481,4 @@ namespace BetterGenshinImpact.GameTask } } } -} \ No newline at end of file +} diff --git a/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs index f4ddea8b..849f9280 100644 --- a/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs @@ -26,7 +26,7 @@ public partial class TaskSettingsPageViewModel : ObservableObject, INavigationAw private readonly TaskTriggerDispatcher _taskDispatcher; private CancellationTokenSource? _cts; - + private static readonly object _locker = new(); [ObservableProperty] private string[] _strategyList; [ObservableProperty] private string _switchAutoGeniusInvokationButtonText; @@ -34,13 +34,11 @@ public partial class TaskSettingsPageViewModel : ObservableObject, INavigationAw [ObservableProperty] private int _autoWoodRoundNum; [ObservableProperty] private string _switchAutoWoodButtonText; - [ObservableProperty] private string[] _combatStrategyList; [ObservableProperty] private int _autoDomainRoundNum; [ObservableProperty] private string _switchAutoDomainButtonText = "启动"; [ObservableProperty] private string _switchAutoFightButtonText = "启动"; - public TaskSettingsPageViewModel(IConfigService configService, INavigationService navigationService, TaskTriggerDispatcher taskTriggerDispatcher) { Config = configService.Get(); @@ -84,6 +82,7 @@ public partial class TaskSettingsPageViewModel : ObservableObject, INavigationAw case "Combat": CombatStrategyList = LoadCustomScript(Global.Absolute(@"User\AutoFight")); break; + case "GeniusInvocation": StrategyList = LoadCustomScript(Global.Absolute(@"User\AutoGeniusInvokation")); break; @@ -109,33 +108,36 @@ public partial class TaskSettingsPageViewModel : ObservableObject, INavigationAw { try { - if (SwitchAutoGeniusInvokationButtonText == "启动") + lock (_locker) { - if (string.IsNullOrEmpty(Config.AutoGeniusInvokationConfig.StrategyName)) + if (SwitchAutoGeniusInvokationButtonText == "启动") { - MessageBox.Show("请先选择策略"); - return; + if (string.IsNullOrEmpty(Config.AutoGeniusInvokationConfig.StrategyName)) + { + MessageBox.Show("请先选择策略"); + return; + } + + var path = Global.Absolute(@"User\AutoGeniusInvokation\" + Config.AutoGeniusInvokationConfig.StrategyName + ".txt"); + + if (!File.Exists(path)) + { + MessageBox.Show("策略文件不存在"); + return; + } + + var content = File.ReadAllText(path); + _cts?.Cancel(); + _cts = new CancellationTokenSource(); + var param = new GeniusInvokationTaskParam(_cts, _taskDispatcher, content); + _taskDispatcher.StartIndependentTask(IndependentTaskEnum.AutoGeniusInvokation, param); + SwitchAutoGeniusInvokationButtonText = "停止"; } - - var path = Global.Absolute(@"User\AutoGeniusInvokation\" + Config.AutoGeniusInvokationConfig.StrategyName + ".txt"); - - if (!File.Exists(path)) + else { - MessageBox.Show("策略文件不存在"); - return; + _cts?.Cancel(); + SwitchAutoGeniusInvokationButtonText = "启动"; } - - var content = File.ReadAllText(path); - _cts?.Cancel(); - _cts = new CancellationTokenSource(); - var param = new GeniusInvokationTaskParam(_cts, _taskDispatcher, content); - _taskDispatcher.StartIndependentTask(IndependentTaskEnum.AutoGeniusInvokation, param); - SwitchAutoGeniusInvokationButtonText = "停止"; - } - else - { - _cts?.Cancel(); - SwitchAutoGeniusInvokationButtonText = "启动"; } } catch (System.Exception ex) @@ -155,18 +157,21 @@ public partial class TaskSettingsPageViewModel : ObservableObject, INavigationAw { try { - if (SwitchAutoWoodButtonText == "启动") + lock (_locker) { - _cts?.Cancel(); - _cts = new CancellationTokenSource(); - var param = new WoodTaskParam(_cts, _taskDispatcher, AutoWoodRoundNum); - _taskDispatcher.StartIndependentTask(IndependentTaskEnum.AutoWood, param); - SwitchAutoWoodButtonText = "停止"; - } - else - { - _cts?.Cancel(); - SwitchAutoWoodButtonText = "启动"; + if (SwitchAutoWoodButtonText == "启动") + { + _cts?.Cancel(); + _cts = new CancellationTokenSource(); + var param = new WoodTaskParam(_cts, _taskDispatcher, AutoWoodRoundNum); + _taskDispatcher.StartIndependentTask(IndependentTaskEnum.AutoWood, param); + SwitchAutoWoodButtonText = "停止"; + } + else + { + _cts?.Cancel(); + SwitchAutoWoodButtonText = "启动"; + } } } catch (System.Exception ex) @@ -181,30 +186,32 @@ public partial class TaskSettingsPageViewModel : ObservableObject, INavigationAw Process.Start(new ProcessStartInfo("https://bgi.huiyadan.com/doc.html#%E8%87%AA%E5%8A%A8%E4%BC%90%E6%9C%A8") { UseShellExecute = true }); } - [RelayCommand] public void OnSwitchAutoFight() { try { - if (SwitchAutoFightButtonText == "启动") + lock (_locker) { - var content = ReadFightStrategy(Config.AutoFightConfig.StrategyName); - if (string.IsNullOrEmpty(content)) + if (SwitchAutoFightButtonText == "启动") { - return; - } + var content = ReadFightStrategy(Config.AutoFightConfig.StrategyName); + if (string.IsNullOrEmpty(content)) + { + return; + } - _cts?.Cancel(); - _cts = new CancellationTokenSource(); - var param = new AutoFightParam(_cts, content); - _taskDispatcher.StartIndependentTask(IndependentTaskEnum.AutoFight, param); - SwitchAutoFightButtonText = "停止"; - } - else - { - _cts?.Cancel(); - SwitchAutoFightButtonText = "启动"; + _cts?.Cancel(); + _cts = new CancellationTokenSource(); + var param = new AutoFightParam(_cts, content); + _taskDispatcher.StartIndependentTask(IndependentTaskEnum.AutoFight, param); + SwitchAutoFightButtonText = "停止"; + } + else + { + _cts?.Cancel(); + SwitchAutoFightButtonText = "启动"; + } } } catch (System.Exception ex) @@ -244,24 +251,27 @@ public partial class TaskSettingsPageViewModel : ObservableObject, INavigationAw { try { - if (SwitchAutoDomainButtonText == "启动") + lock (_locker) { - var content = ReadFightStrategy(Config.AutoFightConfig.StrategyName); - if (string.IsNullOrEmpty(content)) + if (SwitchAutoDomainButtonText == "启动") { - return; - } + var content = ReadFightStrategy(Config.AutoFightConfig.StrategyName); + if (string.IsNullOrEmpty(content)) + { + return; + } - _cts?.Cancel(); - _cts = new CancellationTokenSource(); - var param = new AutoDomainParam(_cts, AutoDomainRoundNum, content); - _taskDispatcher.StartIndependentTask(IndependentTaskEnum.AutoDomain, param); - SwitchAutoDomainButtonText = "停止"; - } - else - { - _cts?.Cancel(); - SwitchAutoDomainButtonText = "启动"; + _cts?.Cancel(); + _cts = new CancellationTokenSource(); + var param = new AutoDomainParam(_cts, AutoDomainRoundNum, content); + _taskDispatcher.StartIndependentTask(IndependentTaskEnum.AutoDomain, param); + SwitchAutoDomainButtonText = "停止"; + } + else + { + _cts?.Cancel(); + SwitchAutoDomainButtonText = "启动"; + } } } catch (System.Exception ex) @@ -276,7 +286,6 @@ public partial class TaskSettingsPageViewModel : ObservableObject, INavigationAw Process.Start(new ProcessStartInfo("https://bgi.huiyadan.com/feats/domain.html") { UseShellExecute = true }); } - public static void SetSwitchAutoGeniusInvokationButtonText(bool running) { var instance = App.GetService(); @@ -320,4 +329,4 @@ public partial class TaskSettingsPageViewModel : ObservableObject, INavigationAw instance.SwitchAutoFightButtonText = running ? "停止" : "启动"; } -} \ No newline at end of file +}