/** * Grasscutter Tools * Copyright (C) 2022 jie65535 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * **/ using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Forms; using GrasscutterTools.DispatchServer; using GrasscutterTools.Game; using GrasscutterTools.Game.Mail; using GrasscutterTools.GOOD; using GrasscutterTools.OpenCommand; using GrasscutterTools.Properties; using GrasscutterTools.Utils; using Newtonsoft.Json; namespace GrasscutterTools.Forms { public partial class FormMain : Form { #region - 初始化 Init - public FormMain() { InitializeComponent(); Icon = Resources.IconGrasscutter; if (DesignMode) return; // 加载版本信息 LoadVersion(); // 加载设置 LoadSettings(); } /// /// 窗体载入时触发(切换语言时会重新载入) /// private void FormMain_Load(object sender, EventArgs e) { Text += " - by jie65535 - v" + AppVersion.ToString(3); #if DEBUG Text += "-debug"; //Text += "-debug -攻击修改特供版"; #endif if (DesignMode) return; GameData.LoadResources(); //LoadCustomCommands(); //InitArtifactList(); InitGameItemList(); //InitWeapons(); InitAvatars(); //InitEntityList(); InitScenes(); InitStatList(); InitPermList(); InitQuestList(); InitMailPage(); //ChangeTPArtifact(); } /// /// 第一次显示窗体时触发 /// protected override void OnShown(EventArgs e) { base.OnShown(e); // 还原窗体位置 if (Settings.Default.MainFormLocation != default) Location = Settings.Default.MainFormLocation; // 还原窗体大小 if (Settings.Default.MainFormSize != default) Size = Settings.Default.MainFormSize; } /// /// 窗口关闭后触发 /// private void FormMain_FormClosed(object sender, FormClosedEventArgs e) { // 保存当前设置 SaveSettings(); } /// /// 应用版本 /// private Version AppVersion; /// /// 加载应用版本 /// private void LoadVersion() { AppVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; } /// /// 载入设置 /// private void LoadSettings() { try { // 恢复自动复制选项状态 ChkAutoCopy.Checked = Settings.Default.AutoCopy; // 初始化首页设置 //InitHomeSettings(); // 初始化获取物品记录 InitGiveItemRecord(); // 初始化生成记录 //InitSpawnRecord(); // 初始化开放命令 //InitOpenCommand(); // 初始化邮件列表 InitMailList(); } catch (Exception ex) { MessageBox.Show(Resources.SettingLoadError + ex.Message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); } } /// /// 保存设置 /// private void SaveSettings() { try { // 记录界面状态 Settings.Default.AutoCopy = ChkAutoCopy.Checked; Settings.Default.MainFormLocation = Location; // 如果命令窗口已经弹出了,则不要保存多余的高度 if (TxtCommandRunLog != null) Settings.Default.MainFormSize = new Size(Width, Height - TxtCommandRunLogMinHeight); else Settings.Default.MainFormSize = Size; // 保存自定义命令 //SaveCustomCommands(); // 保存开放命令设置 //SaveOpenCommand(); // 保存邮件设置 SaveMailSettings(); // 保存默认设置 Settings.Default.Save(); } catch (Exception ex) { MessageBox.Show(Resources.SettingSaveError + ex.Message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); } } #endregion - 初始化 Init - /// /// 命令版本 /// private CommandVersion CommandVersion => Common.CommandVersion; #region - 物品 Items - /// /// 初始化游戏物品列表 /// private void InitGameItemList() { ListGameItems.Items.Clear(); ListGameItems.Items.AddRange(GameData.Items.Lines); } /// /// 物品列表过滤器文本改变时触发 /// private void TxtGameItemFilter_TextChanged(object sender, EventArgs e) { UIUtil.ListBoxFilter(ListGameItems, GameData.Items.Lines, TxtGameItemFilter.Text); } /// /// 生成获取物品命令 /// /// 是否生成成功 private bool GenGiveItemCommand() { var name = ListGameItems.SelectedItem as string; if (!string.IsNullOrEmpty(name)) { var id = ItemMap.ToId(name); if (ChkDrop.Checked) { NUDGameItemLevel.Enabled = false; SetCommand("/drop", $"{id} {NUDGameItemAmout.Value}"); } else { NUDGameItemLevel.Enabled = true; if (CommandVersion.Check(CommandVersion.V1_2_2)) SetCommand("/give", $"{id} x{NUDGameItemAmout.Value} lv{NUDGameItemLevel.Value}"); else SetCommand("/give", $"{id} {NUDGameItemAmout.Value} {NUDGameItemLevel.Value}"); } return true; } return false; } /// /// 获取物品输入改变时触发 /// private void GiveItemsInputChanged(object sender, EventArgs e) { GenGiveItemCommand(); } #region -- 物品记录 -- /// /// 获取物品记录文件路径 /// private readonly string GiveItemCommandsRecordPath = Path.Combine(Application.LocalUserAppDataPath, "GiveItemCommands.txt"); /// /// 获取物品记录 /// private List GiveItemCommands; /// /// 初始化获取物品记录 /// private void InitGiveItemRecord() { if (File.Exists(GiveItemCommandsRecordPath)) { GiveItemCommands = GetCommands(File.ReadAllText(GiveItemCommandsRecordPath)); ListGiveItemLogs.Items.AddRange(GiveItemCommands.Select(c => c.Name).ToArray()); } else { GiveItemCommands = new List(); } } /// /// 保存获取物品记录 /// private void SaveGiveItemRecord() { File.WriteAllText(GiveItemCommandsRecordPath, GetCommandsText(GiveItemCommands)); } /// /// 获取物品记录列表选中项改变时触发 /// private void ListGiveItemLogs_SelectedIndexChanged(object sender, EventArgs e) { if (ListGiveItemLogs.SelectedIndex >= 0) { BtnRemoveGiveItemLog.Enabled = true; SetCommand(GiveItemCommands[ListGiveItemLogs.SelectedIndex].Command); } else { BtnRemoveGiveItemLog.Enabled = false; } } /// /// 点击保存记录按钮时触发 /// private void BtnSaveGiveItemLog_Click(object sender, EventArgs e) { if (GenGiveItemCommand()) { var cmd = new GameCommand($"{ListGameItems.SelectedItem} x{NUDGameItemAmout.Value}", CmbCommand.Text); GiveItemCommands.Add(cmd); ListGiveItemLogs.Items.Add(cmd.Name); SaveGiveItemRecord(); } } /// /// 点击移除获取物品记录时触发 /// private void BtnRemoveGiveItemLog_Click(object sender, EventArgs e) { if (ListGiveItemLogs.SelectedIndex >= 0) { GiveItemCommands.RemoveAt(ListGiveItemLogs.SelectedIndex); ListGiveItemLogs.Items.RemoveAt(ListGiveItemLogs.SelectedIndex); SaveGiveItemRecord(); } } /// /// 点击清空获取物品记录时触发 /// private void LblClearGiveItemLogs_Click(object sender, EventArgs e) { if (MessageBox.Show(Resources.AskConfirmDeletion, Resources.Tips, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { GiveItemCommands.Clear(); ListGiveItemLogs.Items.Clear(); SaveGiveItemRecord(); } } #endregion -- 物品记录 -- #endregion - 物品 Items - #region - 角色 Avatars - #region -- 获取角色 -- /// /// 初始化角色列表 /// private void InitAvatars() { CmbAvatar.Items.Clear(); CmbAvatar.Items.AddRange(GameData.Avatars.Names); } /// /// 角色下拉框选中项改变时触发 /// /// /// private void CmbAvatar_SelectedIndexChanged(object sender, EventArgs e) { // TODO: Load Avatar Image AvatarInputChanged(); } /// /// 角色等级输入框数值改变时触发 /// private void NUDAvatarLevel_ValueChanged(object sender, EventArgs e) { AvatarInputChanged(); } /// /// 角色命座输入框数值改变时触发 /// private void NUDAvatarConstellation_ValueChanged(object sender, EventArgs e) { AvatarInputChanged(); } /// /// 角色页面输入改变时触发 /// private void AvatarInputChanged() { if (CmbAvatar.SelectedIndex >= 0) GenAvatar((int)NUDAvatarLevel.Value, (int)NUDAvatarConstellation.Value, (int)NUDAvatarSkillLevel.Value); } /// /// 获取角色命令 /// /// 等级 private void GenAvatar(int level, int constellation, int skillLevel) { if (CommandVersion.Check(CommandVersion.V1_4_1)) { int avatarId = GameData.Avatars.Ids[CmbAvatar.SelectedIndex]; SetCommand("/give", $"{avatarId} lv{level} c{constellation} sl{skillLevel}"); } else if (CommandVersion.Check(CommandVersion.V1_2_2)) { int avatarId = GameData.Avatars.Ids[CmbAvatar.SelectedIndex]; SetCommand("/give", $"{avatarId} lv{level} c{constellation}"); } else { int avatarId = GameData.Avatars.Ids[CmbAvatar.SelectedIndex] - 1000 + 10000000; SetCommand("/givechar", $"{avatarId} {level}"); } } /// /// 点击获取所有角色按钮时触发 /// /// /// private void BtnGiveAllChar_Click(object sender, EventArgs e) { var level = NUDAvatarLevel.Value; var constellation = NUDAvatarConstellation.Value; var skillLevel = NUDAvatarSkillLevel.Value; if (CommandVersion.Check(CommandVersion.V1_4_1)) SetCommand("/give avatars", $"lv{level} c{constellation} sl{skillLevel}"); else SetCommand("/give avatars", $"lv{level} c{constellation}"); } #endregion #region -- 切换主角元素 -- /// /// 点击切换主角元素链接标签时触发 /// private void LnkSwitchElement_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { UIUtil.OpenURL("https://github.com/Penelopeep/SwitchElementTraveller"); } /// /// 元素参数 /// private readonly string[] Elements = { "white", "fire", "water", "wind", "ice", "rock", "electro", "grass" }; /// /// 切换元素下拉框选中项改变时触发 /// private void CmbSwitchElement_SelectedIndexChanged(object sender, EventArgs e) { if (CmbSwitchElement.SelectedIndex == -1 || CmbSwitchElement.SelectedIndex >= Elements.Length) return; SetCommand("/se", Elements[CmbSwitchElement.SelectedIndex]); } #endregion #region -- 设置角色属性 -- /// /// 初始化数据列表 /// private void InitStatList() { LblStatTip.Text = ""; SetStatsCommand.InitStats(); CmbStat.Items.Clear(); CmbStat.Items.AddRange(SetStatsCommand.Stats.Select(s => s.Name).ToArray()); } /// /// 数据页面输入改变时触发 /// private void SetStatsInputChanged(object sender, EventArgs e) { if (CmbStat.SelectedIndex < 0) return; else BtnLockStat.Enabled = BtnUnlockStat.Enabled = true; var stat = SetStatsCommand.Stats[CmbStat.SelectedIndex]; LblStatPercent.Visible = stat.Percent; LblStatTip.Text = stat.Tip; SetCommand("/setstats", $"{stat.ArgName} {NUDStat.Value}{(stat.Percent ? "%" : "")}"); } /// /// 点击锁定按钮时触发 /// private void BtnLockStat_Click(object sender, EventArgs e) { var stat = SetStatsCommand.Stats[CmbStat.SelectedIndex]; SetCommand("/setstats", $"lock {stat.ArgName} {NUDStat.Value}{(stat.Percent ? "%" : "")}"); } /// /// 点击解锁按钮时触发 /// private void BtnUnlockStat_Click(object sender, EventArgs e) { var stat = SetStatsCommand.Stats[CmbStat.SelectedIndex]; SetCommand("/setstats", $"unlock {stat.ArgName}"); } #endregion #region -- 设置技能等级 -- /// /// 点击设置技能按钮时触发 /// private void LnkSetTalentClicked(object sender, LinkLabelLinkClickedEventArgs e) { SetCommand("/talent", $"{(sender as LinkLabel).Tag} {NUDTalentLevel.Value}"); } #endregion #region -- 设置命座 -- /// /// 设置命座链接标签点击时触发 /// private void LnkSetConst_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { if (NUDSetConstellation.Value >= 0) SetCommand("/setConst", $"{NUDSetConstellation.Value}" + (sender == LnkSetAllConst ? " all" : string.Empty)); else SetCommand("/resetConst", (sender == LnkSetAllConst ? "all" : string.Empty)); } #endregion #endregion - 角色 Avatars - #region - 场景 Scenes - private string[] _scenes; private string[] Scenes { get => _scenes; set { if (_scenes == value) return; _scenes = value; ListScenes.Items.Clear(); ListScenes.Items.AddRange(value); } } /// /// 初始化场景列表 /// private void InitScenes() { Scenes = GameData.Scenes.Lines; CmbClimateType.Items.Clear(); CmbClimateType.Items.AddRange(Resources.ClimateType.Split(',')); } /// /// 选中场景时触发 /// private void RbListScene_CheckedChanged(object sender, EventArgs e) { if (RbListScene.Checked) Scenes = GameData.Scenes.Lines; } /// /// 选中秘境时触发 /// private void RbListDungeons_CheckedChanged(object sender, EventArgs e) { if (RbListDungeons.Checked) Scenes = GameData.Dungeons.Lines; } /// /// 场景列表过滤器输入项改变时触发 /// private void TxtSceneFilter_TextChanged(object sender, EventArgs e) { UIUtil.ListBoxFilter(ListScenes, Scenes, TxtSceneFilter.Text); } /// /// 场景列表选中项改变时触发 /// private void ListScenes_SelectedIndexChanged(object sender, EventArgs e) { if (ListScenes.SelectedIndex < 0) { ChkIncludeSceneId.Enabled = false; return; } ChkIncludeSceneId.Enabled = true; // 可以直接弃用 scene 命令 var name = ListScenes.SelectedItem as string; var id = ItemMap.ToId(name); if (RbListScene.Checked) { if (CommandVersion.Check(CommandVersion.V1_2_2)) { SetCommand("/scene", id.ToString()); } else { SetCommand("/tp ~ ~ ~", id.ToString()); } } else if (RbListDungeons.Checked) { SetCommand("/dungeon", id.ToString()); } } /// /// 气候类型列表 /// static readonly string[] climateTypes = { "none", "sunny", "cloudy", "rain", "thunderstorm", "snow", "mist" }; /// /// 气候类型下拉框选中项改变时触发 /// private void CmbClimateType_SelectedIndexChanged(object sender, EventArgs e) { if (CmbClimateType.SelectedIndex < 0) return; if (CommandVersion.Check(CommandVersion.V1_2_2)) SetCommand("/weather", CmbClimateType.SelectedIndex < climateTypes.Length ? climateTypes[CmbClimateType.SelectedIndex] : "none"); else SetCommand("/weather", $"0 {CmbClimateType.SelectedIndex}"); } /// /// 点击传送按钮时触发 /// private void BtnTeleport_Click(object sender, EventArgs e) { string args = $"{NUDTpX.Value} {NUDTpY.Value} {NUDTpZ.Value}"; if (ChkIncludeSceneId.Checked && RbListScene.Checked && ListScenes.SelectedIndex != -1) args += $" {GameData.Scenes.Ids[ListScenes.SelectedIndex]}"; SetCommand("/tp", args); } #endregion - 场景 Scenes - #region - 管理 Management - /// /// 初始化权限列表 /// private void InitPermList() { CmbPerm.Items.Clear(); CmbPerm.Items.AddRange(Resources.Permissions.Split('\n').Select(l => l.Trim()).ToArray()); } /// /// 点击授权按钮时触发 /// private void BtnPermClick(object sender, EventArgs e) { var uid = NUDPermUID.Value; var perm = CmbPerm.Text.Trim(); var act = (sender as Button).Tag.ToString(); if (act == "list" || act == "clear") { SetCommand($"/permission {act} @{uid}"); } else { if (string.IsNullOrEmpty(perm)) { MessageBox.Show(Resources.PermissionCannotBeEmpty, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } SetCommand($"/permission {act} @{uid} {perm}"); } } /// /// 账号相关按钮点击时触发,Tag包含子命令 /// private void AccountButtonClicked(object sender, EventArgs e) { var username = TxtAccountUserName.Text.Trim(); if (string.IsNullOrEmpty(username)) { MessageBox.Show(Resources.UsernameCannotBeEmpty, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } SetCommand($"/account {(sender as Button).Tag} {username} {(ChkAccountSetUid.Checked ? NUDAccountUid.Value.ToString() : "")}"); } /// /// 点击封禁按钮时触发 /// private void BtnBan_Click(object sender, EventArgs e) { var uid = NUDBanUID.Value; var endTime = DTPBanEndTime.Value; var command = $"/ban @{uid} {new DateTimeOffset(endTime).ToUnixTimeSeconds()}"; var reaseon = Regex.Replace(TxtBanReason.Text.Trim(), @"\s+", "-"); if (!string.IsNullOrEmpty(reaseon)) command += $" {reaseon}"; SetCommand(command); } /// /// 点击解封按钮时触发 /// private void BtnUnban_Click(object sender, EventArgs e) { SetCommand($"/unban @{NUDBanUID.Value}"); } #endregion - 管理 Management - #region - 邮件 Mail - /// /// 初始化邮件页面 /// private void InitMailPage() { TxtMailSender.Text = Settings.Default.DefaultMailSender; LoadMailSelectableItems(); } /// /// 保存邮件设置 /// private void SaveMailSettings() { Settings.Default.DefaultMailSender = TxtMailSender.Text; } /// /// 点击清空邮件内容时触发 /// private void LblClearMailContent_Click(object sender, EventArgs e) { TxtMailContent.Clear(); } /// /// 点击发送邮件时触发 /// private void BtnSendMail_Click(object sender, EventArgs e) { var mail = new Mail { Title = TxtMailTitle.Text.Trim(), Sender = TxtMailSender.Text.Trim(), Content = TxtMailContent.Text.Trim(), Recipient = RbMailSendToAll.Checked ? 0 : (int)NUDMailRecipient.Value, ItemList = new List(MailItems), SendTime = DateTime.Now, }; if (mail.Title == "" || mail.Sender == "" || mail.Content == "") { MessageBox.Show(Resources.EmptyInputTip, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (mail.SendToAll) { MessageBox.Show(Resources.MailSendToAllWarning, Resources.Warning, MessageBoxButtons.OK, MessageBoxIcon.Warning); } var cmd = $"/sendMail {(mail.SendToAll ? "all" : mail.Recipient.ToString())} |" + $"/sendMail {mail.Title} |" + $"/sendMail {mail.Content.Replace("\r", "\\r").Replace("\n", "\\n")} |" + $"/sendMail {mail.Sender} |"; foreach (var item in mail.ItemList) cmd += $"/sendMail {item.ItemId} {item.ItemCount} {item.ItemLevel} |"; cmd += "/sendMail finish"; SetCommand(cmd); AddMailToList(mail); } /// /// 展示邮件 /// /// private void ShowMail(Mail mail) { TxtMailTitle.Text = mail.Title; TxtMailSender.Text = mail.Sender; TxtMailContent.Text = mail.Content; NUDMailRecipient.Value = mail.Recipient; RbMailSendToAll.Checked = mail.SendToAll; RbMailSendToPlayer.Checked = !mail.SendToAll; ShowMailItems(mail.ItemList); } #region -- 邮件附件列表 Mail items -- /// /// 当前邮件附件列表 /// private readonly List MailItems = new List(); /// /// 展示邮件附件列表 /// /// private void ShowMailItems(List items) { MailItems.Clear(); MailItems.AddRange(items); ListMailItems.BeginUpdate(); ListMailItems.Items.Clear(); ListMailItems.Items.AddRange(items.Select(it => it.ToString()).ToArray()); ListMailItems.EndUpdate(); } /// /// 点击添加邮件附件项时触发 /// private void BtnAddMailItem_Click(object sender, EventArgs e) { if (ListMailSelectableItems.SelectedIndex == -1) return; var item = ListMailSelectableItems.SelectedItem as string; var itemId = ItemMap.ToId(item); var mailItem = new MailItem { ItemId = itemId, ItemCount = (int)NUDMailItemCount.Value, ItemLevel = (int)NUDMailItemLevel.Value, }; MailItems.Add(mailItem); ListMailItems.Items.Add(mailItem.ToString()); } /// /// 点击删除邮件附件项时触发 /// private void BtnDeleteMailItem_Click(object sender, EventArgs e) { if (ListMailItems.SelectedIndex == -1) return; MailItems.RemoveAt(ListMailItems.SelectedIndex); ListMailItems.Items.RemoveAt(ListMailItems.SelectedIndex); } #endregion #region -- 邮件附件可选列表 Mail item selectable list -- private string[] MailSelectableItems; /// /// 加载附件可选项列表 /// private void LoadMailSelectableItems() { MailSelectableItems = new string[GameData.Items.Count + GameData.Weapons.Count + GameData.Artifacts.Count]; int i = 0; GameData.Items.Lines.CopyTo(MailSelectableItems, i); i += GameData.Items.Count; GameData.Weapons.Lines.CopyTo(MailSelectableItems, i); i += GameData.Weapons.Count; GameData.Artifacts.Lines.CopyTo(MailSelectableItems, i); i += GameData.Artifacts.Count; Array.Sort(MailSelectableItems, (a, b) => ItemMap.ToId(a) - ItemMap.ToId(b)); ListMailSelectableItems.Items.Clear(); ListMailSelectableItems.Items.AddRange(MailSelectableItems); } /// /// 邮件页面物品列表过滤器文本改变时触发 /// private void TxtMailSelectableItemFilter_TextChanged(object sender, EventArgs e) { UIUtil.ListBoxFilter(ListMailSelectableItems, MailSelectableItems, TxtMailSelectableItemFilter.Text); } #endregion #region -- 邮件列表 Mail list -- /// /// 获取物品记录文件路径 /// private readonly string MailListPath = Path.Combine(Application.LocalUserAppDataPath, "MailList.json"); /// /// 邮件列表 /// private List MailList = new List(); /// /// 初始化邮件列表 /// private void InitMailList() { if (File.Exists(MailListPath)) { MailList = JsonConvert.DeserializeObject>(File.ReadAllText(MailListPath)); ListMailList.Items.AddRange(MailList.Select(it => it.ToString()).ToArray()); } else { MailList = new List(); } } /// /// 保存邮件列表 /// private void SaveMailList() { File.WriteAllText(MailListPath, JsonConvert.SerializeObject(MailList)); } /// /// 添加邮件到列表 /// /// 邮件 private void AddMailToList(Mail mail) { MailList.Add(mail); ListMailList.Items.Add(mail.ToString()); SaveMailList(); } /// /// 邮件列表选中项改变时发生 /// private void ListMailList_SelectedIndexChanged(object sender, EventArgs e) { if (ListMailList.SelectedIndex == -1) return; // 显示选中邮件 var mail = MailList[ListMailList.SelectedIndex]; ShowMail(mail); } /// /// 点击删除邮件按钮时触发 /// private void BtnRemoveMail_Click(object sender, EventArgs e) { if (ListMailList.SelectedIndex == -1) return; MailList.RemoveAt(ListMailList.SelectedIndex); ListMailList.Items.RemoveAt(ListMailList.SelectedIndex); SaveMailList(); } /// /// 点击清空邮件列表按钮时触发 /// private void BtnClearMail_Click(object sender, EventArgs e) { if (MailList.Count == 0) return; if (MessageBox.Show(Resources.AskConfirmDeletion, Resources.Tips, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { ListMailList.Items.Clear(); MailList.Clear(); SaveMailList(); } } #endregion #endregion #region - 关于 About - /// /// 点击Github链接时触发 /// private void LnkGithub_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { UIUtil.OpenURL("https://github.com/jie65535/GrasscutterCommandGenerator"); } #endregion - 关于 About - #region - 命令 Command - /// /// 设置命令 /// /// 命令 private void SetCommand(string command) { var oldCommand = CmbCommand.Text; CmbCommand.Text = (ModifierKeys == Keys.Shift) ? $"{oldCommand} | {command}" : command; if (ChkAutoCopy.Checked) CopyCommand(); AddCommandToList(command); if (ModifierKeys == Keys.Control) { OnOpenCommandInvoke(); } else if (ModifierKeys == Keys.Alt) { OnOpenCommandInvoke(); CmbCommand.Text = oldCommand; } } /// /// 添加命令到执行记录 /// private void AddCommandToList(string command = "") { if (string.IsNullOrEmpty(command)) command = CmbCommand.Text; if (!string.IsNullOrEmpty(command)) { if (CmbCommand.Items.Count > 19) CmbCommand.Items.RemoveAt(0); CmbCommand.Items.Add(command); } } /// /// 设置带参数的命令 /// /// 命令 /// 参数 private void SetCommand(string command, string args) { //if (ChkIncludeUID.Checked) // SetCommand($"{command} @{NUDUid.Value} {args.Trim()}"); //else SetCommand($"{command} {args.Trim()}"); } /// /// 点击复制按钮时触发 /// private async void BtnCopy_Click(object sender, EventArgs e) { CopyCommand(); await UIUtil.ButtonComplete(BtnCopy); } /// /// 复制命令 /// private void CopyCommand() { if (!string.IsNullOrEmpty(CmbCommand.Text)) Clipboard.SetText(CmbCommand.Text); } /// /// 在命令行内按下回车时直接执行 /// private void TxtCommand_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) OnOpenCommandInvoke(); } /// /// 开放命令执行时触发 /// private void OnOpenCommandInvoke() { BtnInvokeOpenCommand_Click(BtnInvokeOpenCommand, EventArgs.Empty); } /// /// 点击执行开放命令按钮时触发 /// private async void BtnInvokeOpenCommand_Click(object sender, EventArgs e) { if (!BtnInvokeOpenCommand.Enabled) return; var cmd = CmbCommand.Text; if (cmd.Length < 2) { ShowTip(Resources.CommandContentCannotBeEmpty, CmbCommand); return; } if (cmd.IndexOf('|') == -1) await RunCommands(FormatCommand(cmd)); else await RunCommands(cmd.Split('|').Select(it => FormatCommand(it)).ToArray()); } /// /// 格式化命令 /// (去除收尾空白,替换换行) /// /// 原始输入 /// 格式化后可执行命令 private string FormatCommand(string raw) { return raw.Trim().Replace("\\r", "\r").Replace("\\n", "\n"); } /// /// 运行命令 /// /// 命令列表 /// 是否执行成功 private async Task RunCommands(params string[] commands) { if (OC == null || !OC.CanInvoke) { ShowTip(Resources.RequireOpenCommandTip, BtnInvokeOpenCommand); TCMain.SelectedTab = TPRemoteCall; return false; } ExpandCommandRunLog(); try { BtnInvokeOpenCommand.Enabled = false; BtnInvokeOpenCommand.Cursor = Cursors.WaitCursor; int i = 0; foreach (var command in commands) { TxtCommandRunLog.AppendText(">"); TxtCommandRunLog.AppendText(command); if (commands.Length > 1) TxtCommandRunLog.AppendText($" ({++i}/{commands.Length})"); TxtCommandRunLog.AppendText(Environment.NewLine); var cmd = command.TrimStart('/'); try { var msg = await OC.Invoke(cmd); TxtCommandRunLog.AppendText(string.IsNullOrEmpty(msg) ? "OK" : msg); TxtCommandRunLog.AppendText(Environment.NewLine); } catch (Exception ex) { TxtCommandRunLog.AppendText("Error: "); TxtCommandRunLog.AppendText(ex.Message); TxtCommandRunLog.AppendText(Environment.NewLine); MessageBox.Show(ex.Message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } TxtCommandRunLog.ScrollToCaret(); } } finally { BtnInvokeOpenCommand.Cursor = Cursors.Default; BtnInvokeOpenCommand.Enabled = true; } return true; } /// /// 命令日志最小高度 /// private const int TxtCommandRunLogMinHeight = 150; /// /// 命令日志文本框 /// private TextBox TxtCommandRunLog; /// /// 展开命令记录(可重入) /// private void ExpandCommandRunLog() { if (GrpCommand.Height < TxtCommandRunLogMinHeight) { if (WindowState == FormWindowState.Maximized) WindowState = FormWindowState.Normal; TCMain.Anchor &= ~AnchorStyles.Bottom; GrpCommand.Anchor |= AnchorStyles.Top; Size = new Size(Width, Height + TxtCommandRunLogMinHeight); MinimumSize = new Size(MinimumSize.Width, MinimumSize.Height + TxtCommandRunLogMinHeight); TCMain.Anchor |= AnchorStyles.Bottom; GrpCommand.Anchor &= ~AnchorStyles.Top; } if (TxtCommandRunLog == null) { TxtCommandRunLog = new TextBox { Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom, Multiline = true, Font = new Font("Consolas", 9F), Location = new Point(BtnInvokeOpenCommand.Left, BtnInvokeOpenCommand.Bottom + 6), Size = new Size(GrpCommand.Width - BtnInvokeOpenCommand.Left * 2, TxtCommandRunLogMinHeight), ReadOnly = true, BackColor = Color.White, ScrollBars = ScrollBars.Vertical, }; GrpCommand.Controls.Add(TxtCommandRunLog); } } #endregion - 命令 Command - #region - 通用 General - /// /// 窗口按键按下时触发 /// private void FormMain_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.F5) { // F5 为执行命令 OnOpenCommandInvoke(); } } /// /// 提示气泡对象 /// private readonly ToolTip TTip = new ToolTip(); /// /// 在指定控件上显示提示气泡 /// /// 消息 /// 控件 private void ShowTip(string message, Control control) { TTip.Show(message, control, 0, control.Size.Height, 3000); } #endregion - 通用 General - #region - 命令记录 Command Logs - /// /// 获取命令记录 /// (反序列化) /// /// 命令记录文本(示例:"标签1\n命令1\n标签2\n命令2...") /// 命令列表 private List GetCommands(string commandsText) { var lines = commandsText.Split('\n'); List commands = new List(lines.Length / 2); for (int i = 0; i < lines.Length - 1; i += 2) commands.Add(new GameCommand(lines[i].Trim(), lines[i + 1].Trim())); return commands; } /// /// 获取命令记录文本 /// (序列化) /// /// 命令列表 /// 命令记录文本(示例:"标签1\n命令1\n标签2\n命令2...") private string GetCommandsText(List commands) { StringBuilder builder = new StringBuilder(); foreach (var cmd in commands) { builder.AppendLine(cmd.Name); builder.AppendLine(cmd.Command); } return builder.ToString(); } #endregion - 命令记录 Command Logs - /// /// 开放命令接口 /// private OpenCommandAPI OC => Common.OC; #region - 任务 Quests - /// /// 初始化任务列表 /// private void InitQuestList() { QuestFilterChanged(null, EventArgs.Empty); } /// /// 任务列表过滤器文本改变时触发 /// private void QuestFilterChanged(object sender, EventArgs e) { ListQuest.BeginUpdate(); ListQuest.Items.Clear(); ListQuest.Items.AddRange(GameData.Quests.Lines.Where(l => { if (!ChkQuestFilterHIDDEN.Checked && l.Contains((string)ChkQuestFilterHIDDEN.Tag)) return false; if (!ChkQuestFilterUNRELEASED.Checked && l.Contains((string)ChkQuestFilterUNRELEASED.Tag)) return false; if (!ChkQuestFilterTEST.Checked && l.Contains((string)ChkQuestFilterTEST.Tag)) return false; if (!string.IsNullOrEmpty(TxtQuestFilter.Text)) return l.Contains(TxtQuestFilter.Text); return true; }).ToArray()); ListQuest.EndUpdate(); } /// /// 任务相关按钮点击时触发(Tag带子命令) /// private void QuestButsClicked(object sender, EventArgs e) { if (ListQuest.SelectedIndex == -1) return; var item = ListQuest.SelectedItem as string; var id = ItemMap.ToId(item); SetCommand("/quest", $"{(sender as Button).Tag} {id}"); } #endregion - 任务 Quests - } }