diff --git a/src/MaaWpfGui/Main/AsstProxy.cs b/src/MaaWpfGui/Main/AsstProxy.cs index 00954cf46c..73eb9d5312 100644 --- a/src/MaaWpfGui/Main/AsstProxy.cs +++ b/src/MaaWpfGui/Main/AsstProxy.cs @@ -2623,50 +2623,6 @@ namespace MaaWpfGui.Main return id != 0 && AsstStart(); } - /// - /// 自动抄作业。 - /// - /// 作业 JSON 的文件路径,绝对、相对路径均可。 - /// 是否进行 “快捷编队”。 - /// 是否追加信赖干员 - /// 是否追加自定干员 - /// 自定干员列表 - /// 是否导航至关卡(启用自动战斗序列) - /// 关卡名 - /// 是不是突袭 - /// 任务类型 - /// 任务重复执行次数 - /// 是否使用理智药 - /// 是否启动战斗 - /// 是否成功。 - public bool AsstStartCopilot(string filename, bool formation, bool addTrust, bool addUserAdditional, JArray userAdditional, bool needNavigate, string navigateName, bool isRaid, AsstTaskType type, int loopTimes, bool useSanityPotion, bool asstStart = true) - { - var taskParams = new JObject - { - ["filename"] = filename, - ["formation"] = formation, - ["add_trust"] = addTrust, - ["need_navigate"] = needNavigate, - ["is_raid"] = isRaid, - ["loop_times"] = loopTimes, - ["use_sanity_potion"] = useSanityPotion, - }; - - if (addUserAdditional) - { - taskParams["user_additional"] = userAdditional; - } - - if (needNavigate) - { - taskParams["navigate_name"] = navigateName; - } - - AsstTaskId id = AsstAppendTaskWithEncoding(type, taskParams); - _taskStatus.Add(id, TaskType.Copilot); - return id != 0 && (!asstStart || AsstStart()); - } - public bool AsstStartVideoRec(string filename) { var taskParams = new JObject diff --git a/src/MaaWpfGui/Models/AsstTasks/AsstBaseTask.cs b/src/MaaWpfGui/Models/AsstTasks/AsstBaseTask.cs new file mode 100644 index 0000000000..351cf4a8cf --- /dev/null +++ b/src/MaaWpfGui/Models/AsstTasks/AsstBaseTask.cs @@ -0,0 +1,30 @@ +// +// MaaWpfGui - A part of the MaaCoreArknights project +// Copyright (C) 2021 MistEO and Contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License v3.0 only as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY +// +#nullable enable +using System; +using MaaWpfGui.Services; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace MaaWpfGui.Models.AsstTasks; + +[JsonObject(MemberSerialization.OptIn)] +public class AsstBaseTask +{ + public virtual AsstTaskType TaskType { get; private set; } + + public virtual (AsstTaskType TaskType, JObject Params) Serialize() + { + throw new NotImplementedException(); + } +} diff --git a/src/MaaWpfGui/Models/AsstTasks/AsstCopilotTask.cs b/src/MaaWpfGui/Models/AsstTasks/AsstCopilotTask.cs new file mode 100644 index 0000000000..aa88294f84 --- /dev/null +++ b/src/MaaWpfGui/Models/AsstTasks/AsstCopilotTask.cs @@ -0,0 +1,110 @@ +// +// MaaWpfGui - A part of the MaaCoreArknights project +// Copyright (C) 2021 MistEO and Contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License v3.0 only as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY +// +#nullable enable +using System.Collections.Generic; +using MaaWpfGui.Services; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace MaaWpfGui.Models.AsstTasks; + +/// +/// 自动抄作业。 +/// +public class AsstCopilotTask : AsstBaseTask +{ + public override AsstTaskType TaskType => AsstTaskType.Copilot; + + /// + /// Gets or sets 作业 JSON 的文件路径,绝对、相对路径均可 + /// + public string FileName { get; set; } = string.Empty; + + /// + /// Gets or sets a value indicating whether 自动编队 + /// + public bool Formation { get; set; } + + /// + /// Gets or sets a value indicating whether 追加信赖干员 + /// + public bool AddTrust { get; set; } + + /// + /// Gets or sets a value indicating whether 导航至关卡(启用自动战斗序列、取消代理) + /// + public bool NeedNavigate { get; set; } + + /// + /// Gets or sets 关卡名,仅导航用,Wpf会自动读取地图对应的关卡名 + /// + public string? StageName { get; set; } + + /// + /// Gets or sets a value indicating whether 突袭难度 + /// + public bool IsRaid { get; set; } + + /// + /// Gets or sets 重复次数 + /// + public int LoopTimes { get; set; } + + /// + /// Gets or sets a value indicating whether 使用理智药 + /// + public bool UseSanityPotion { get; set; } + + /// + /// Gets or sets 自定干员列表 + /// + public List? UserAdditionals { get; set; } + + public override (AsstTaskType TaskType, JObject Params) Serialize() + { + var taskParams = new JObject + { + ["filename"] = FileName, + ["formation"] = Formation, + ["add_trust"] = AddTrust, + ["need_navigate"] = NeedNavigate, + ["is_raid"] = IsRaid, + ["loop_times"] = LoopTimes, + ["use_sanity_potion"] = UseSanityPotion, + }; + + if (UserAdditionals?.Count > 0) + { + taskParams["user_additional"] = JsonConvert.SerializeObject(UserAdditionals); + } + + if (NeedNavigate) + { + taskParams["navigate_name"] = StageName; + } + + return (TaskType, taskParams); + } + + public class UserAdditional + { + /// + /// Gets or sets 干员名,ocr文本,跟随客户端语言 + /// + [JsonProperty("name")] + public string Name { get; set; } = string.Empty; + + [JsonProperty("skill")] + public int Skill { get; set; } + } +} diff --git a/src/MaaWpfGui/ViewModels/UI/CopilotViewModel.cs b/src/MaaWpfGui/ViewModels/UI/CopilotViewModel.cs index 9b4d38e912..b26b391c0c 100644 --- a/src/MaaWpfGui/ViewModels/UI/CopilotViewModel.cs +++ b/src/MaaWpfGui/ViewModels/UI/CopilotViewModel.cs @@ -25,15 +25,17 @@ using System.Windows.Controls; using System.Windows.Input; using MaaWpfGui.Constants; using MaaWpfGui.Helper; +using MaaWpfGui.Main; using MaaWpfGui.Models; +using MaaWpfGui.Models.AsstTasks; using MaaWpfGui.Services; using MaaWpfGui.States; using Microsoft.Win32; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Serilog; using Stylet; using static MaaWpfGui.Helper.CopilotHelper; +using static MaaWpfGui.Models.AsstTasks.AsstCopilotTask; using DataFormats = System.Windows.Forms.DataFormats; using Task = System.Threading.Tasks.Task; @@ -56,7 +58,7 @@ namespace MaaWpfGui.ViewModels.UI private const string TempCopilotFile = "cache/_temp_copilot.json"; private static readonly string[] _supportExt = [".json", ".mp4", ".m4s", ".mkv", ".flv", ".avi"]; private const string CopilotJsonDir = "config/copilot"; - private const string StageNameRegex = @"(?:[a-z]{0,3})(?:\d{0,2})-(?:(?:A|B|C|D|EX|S|TR|MO)-?)?(?:\d{1,2})(\(Raid\)(?=\.json))?"; + private const string StageNameRegex = @"(?:[a-z]{0,3})(?:\d{0,2})-(?:(?:A|B|C|D|EX|S|TR|MO)-?)?(?:\d{1,2})"; private const string InvalidStageNameChars = @"[:',\.\(\)\|\[\]\?,。【】{};:]"; // 无效字符 [GeneratedRegex(InvalidStageNameChars)] @@ -1151,27 +1153,39 @@ namespace MaaWpfGui.ViewModels.UI } Regex regex = new Regex(@"(?<=;)(?[^,;]+)(?:, *(?\d))?(?=;)", RegexOptions.Compiled); - JArray userAdditional = new(regex.Matches(";" + UserAdditional + ";").ToList().Select(match => new JObject + + var userAdditional = regex.Matches(";" + UserAdditional + ";").ToList().Select(match => new UserAdditional { - ["name"] = match.Groups[1].Value.Trim(), - ["skill"] = string.IsNullOrEmpty(match.Groups[2].Value) ? 0 : int.Parse(match.Groups[2].Value), - })); + Name = match.Groups[1].Value.Trim(), + Skill = string.IsNullOrEmpty(match.Groups[2].Value) ? 0 : int.Parse(match.Groups[2].Value), + }); bool ret = true; if (UseCopilotList) { _copilotIdList.Clear(); - bool startAny = false; - foreach (var model in CopilotItemViewModels.Where(i => i.IsChecked)) - { - _copilotIdList.Add(model.CopilotId); - ret &= Instances.AsstProxy.AsstStartCopilot(model.FilePath, Form, AddTrust, AddUserAdditional, userAdditional, UseCopilotList, model.Name, model.IsRaid, _taskType, Loop ? LoopTimes : 1, _useSanityPotion, false); - startAny = true; - } + var tasks = CopilotItemViewModels.Where(i => i.IsChecked).Select(model => + { + _copilotIdList.Add(model.CopilotId); + var task = new AsstCopilotTask() + { + FileName = model.FilePath, + Formation = _form, + AddTrust = _addTrust, + UserAdditionals = userAdditional.ToList(), + NeedNavigate = UseCopilotList, + StageName = model.Name, + IsRaid = model.IsRaid, + LoopTimes = Loop ? LoopTimes : 1, + UseSanityPotion = _useSanityPotion, + }; + var (type, param) = task.Serialize(); + return Instances.AsstProxy.AsstAppendTaskWithEncoding(AsstProxy.TaskType.Copilot, type, param); + }).ToList(); - if (startAny) + if (tasks.Count > 0) { - ret &= Instances.AsstProxy.AsstStart(); + ret = tasks.All(t => t) && Instances.AsstProxy.AsstStart(); } else {// 一个都没启动,怎会有如此无聊之人 @@ -1181,7 +1195,18 @@ namespace MaaWpfGui.ViewModels.UI } else { - ret &= Instances.AsstProxy.AsstStartCopilot(IsDataFromWeb ? TempCopilotFile : Filename, Form, AddTrust, AddUserAdditional, userAdditional, UseCopilotList, string.Empty, false, _taskType, Loop ? LoopTimes : 1, false); + var task = new AsstCopilotTask() + { + FileName = IsDataFromWeb ? TempCopilotFile : Filename, + Formation = _form, + AddTrust = _addTrust, + UserAdditionals = userAdditional.ToList(), + NeedNavigate = false, + LoopTimes = Loop ? LoopTimes : 1, + UseSanityPotion = _useSanityPotion, + }; + ret = Instances.AsstProxy.AsstAppendTaskWithEncoding(AsstProxy.TaskType.Copilot, _taskType, task.Serialize().Params); + ret &= Instances.AsstProxy.AsstStart(); } if (ret)