diff --git a/Source/GrasscutterTools/App.config b/Source/GrasscutterTools/App.config index 699132f..2ded400 100644 --- a/Source/GrasscutterTools/App.config +++ b/Source/GrasscutterTools/App.config @@ -17,7 +17,7 @@ 10001 - zh-CN + @@ -38,7 +38,7 @@ - 1.2.2 + False diff --git a/Source/GrasscutterTools/Forms/FormMain.Designer.cs b/Source/GrasscutterTools/Forms/FormMain.Designer.cs index 1e6e793..3f68fef 100644 --- a/Source/GrasscutterTools/Forms/FormMain.Designer.cs +++ b/Source/GrasscutterTools/Forms/FormMain.Designer.cs @@ -86,9 +86,12 @@ namespace GrasscutterTools.Forms this.LblAccountUserName = new System.Windows.Forms.Label(); this.TxtAccountUserName = new System.Windows.Forms.TextBox(); this.GrpPermission = new System.Windows.Forms.GroupBox(); + this.LblPermNewCommandTip = new System.Windows.Forms.Label(); this.CmbPerm = new System.Windows.Forms.ComboBox(); this.NUDPermUID = new System.Windows.Forms.NumericUpDown(); + this.BtnPermClear = new System.Windows.Forms.Button(); this.BtmPermRemove = new System.Windows.Forms.Button(); + this.BtnPermList = new System.Windows.Forms.Button(); this.BtnPermAdd = new System.Windows.Forms.Button(); this.LblPerm = new System.Windows.Forms.Label(); this.LblPermUID = new System.Windows.Forms.Label(); @@ -218,8 +221,9 @@ namespace GrasscutterTools.Forms this.BtnOpenGachaBannerEditor = new System.Windows.Forms.Button(); this.GrasscutterToolsIcon = new System.Windows.Forms.PictureBox(); this.GrpSettings = new System.Windows.Forms.GroupBox(); + this.LblGCVersion = new System.Windows.Forms.Label(); + this.CmbGcVersions = new System.Windows.Forms.ComboBox(); this.ChkTopMost = new System.Windows.Forms.CheckBox(); - this.ChkNewCommand = new System.Windows.Forms.CheckBox(); this.CmbLanguage = new System.Windows.Forms.ComboBox(); this.LblLanguage = new System.Windows.Forms.Label(); this.NUDUid = new System.Windows.Forms.NumericUpDown(); @@ -726,15 +730,24 @@ namespace GrasscutterTools.Forms // GrpPermission // resources.ApplyResources(this.GrpPermission, "GrpPermission"); + this.GrpPermission.Controls.Add(this.LblPermNewCommandTip); this.GrpPermission.Controls.Add(this.CmbPerm); this.GrpPermission.Controls.Add(this.NUDPermUID); + this.GrpPermission.Controls.Add(this.BtnPermClear); this.GrpPermission.Controls.Add(this.BtmPermRemove); + this.GrpPermission.Controls.Add(this.BtnPermList); this.GrpPermission.Controls.Add(this.BtnPermAdd); this.GrpPermission.Controls.Add(this.LblPerm); this.GrpPermission.Controls.Add(this.LblPermUID); this.GrpPermission.Name = "GrpPermission"; this.GrpPermission.TabStop = false; // + // LblPermNewCommandTip + // + resources.ApplyResources(this.LblPermNewCommandTip, "LblPermNewCommandTip"); + this.LblPermNewCommandTip.ForeColor = System.Drawing.SystemColors.GrayText; + this.LblPermNewCommandTip.Name = "LblPermNewCommandTip"; + // // CmbPerm // resources.ApplyResources(this.CmbPerm, "CmbPerm"); @@ -758,6 +771,14 @@ namespace GrasscutterTools.Forms 0, 0}); // + // BtnPermClear + // + resources.ApplyResources(this.BtnPermClear, "BtnPermClear"); + this.BtnPermClear.Name = "BtnPermClear"; + this.BtnPermClear.Tag = "clear"; + this.BtnPermClear.UseVisualStyleBackColor = true; + this.BtnPermClear.Click += new System.EventHandler(this.BtnPermClick); + // // BtmPermRemove // resources.ApplyResources(this.BtmPermRemove, "BtmPermRemove"); @@ -766,6 +787,14 @@ namespace GrasscutterTools.Forms this.BtmPermRemove.UseVisualStyleBackColor = true; this.BtmPermRemove.Click += new System.EventHandler(this.BtnPermClick); // + // BtnPermList + // + resources.ApplyResources(this.BtnPermList, "BtnPermList"); + this.BtnPermList.Name = "BtnPermList"; + this.BtnPermList.Tag = "list"; + this.BtnPermList.UseVisualStyleBackColor = true; + this.BtnPermList.Click += new System.EventHandler(this.BtnPermClick); + // // BtnPermAdd // resources.ApplyResources(this.BtnPermAdd, "BtnPermAdd"); @@ -1916,8 +1945,9 @@ namespace GrasscutterTools.Forms // GrpSettings // resources.ApplyResources(this.GrpSettings, "GrpSettings"); + this.GrpSettings.Controls.Add(this.LblGCVersion); + this.GrpSettings.Controls.Add(this.CmbGcVersions); this.GrpSettings.Controls.Add(this.ChkTopMost); - this.GrpSettings.Controls.Add(this.ChkNewCommand); this.GrpSettings.Controls.Add(this.CmbLanguage); this.GrpSettings.Controls.Add(this.LblLanguage); this.GrpSettings.Controls.Add(this.NUDUid); @@ -1926,19 +1956,23 @@ namespace GrasscutterTools.Forms this.GrpSettings.Name = "GrpSettings"; this.GrpSettings.TabStop = false; // + // LblGCVersion + // + resources.ApplyResources(this.LblGCVersion, "LblGCVersion"); + this.LblGCVersion.Name = "LblGCVersion"; + // + // CmbGcVersions + // + resources.ApplyResources(this.CmbGcVersions, "CmbGcVersions"); + this.CmbGcVersions.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.CmbGcVersions.FormattingEnabled = true; + this.CmbGcVersions.Name = "CmbGcVersions"; + // // ChkTopMost // resources.ApplyResources(this.ChkTopMost, "ChkTopMost"); this.ChkTopMost.Name = "ChkTopMost"; this.ChkTopMost.UseVisualStyleBackColor = true; - this.ChkTopMost.CheckedChanged += new System.EventHandler(this.ChkTopMost_CheckedChanged); - // - // ChkNewCommand - // - resources.ApplyResources(this.ChkNewCommand, "ChkNewCommand"); - this.ChkNewCommand.Name = "ChkNewCommand"; - this.ChkNewCommand.UseVisualStyleBackColor = true; - this.ChkNewCommand.CheckedChanged += new System.EventHandler(this.ChkNewCommand_CheckedChanged); // // CmbLanguage // @@ -1946,7 +1980,6 @@ namespace GrasscutterTools.Forms this.CmbLanguage.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.CmbLanguage.FormattingEnabled = true; this.CmbLanguage.Name = "CmbLanguage"; - this.CmbLanguage.SelectedIndexChanged += new System.EventHandler(this.CmbLanguage_SelectedIndexChanged); // // LblLanguage // @@ -2272,7 +2305,6 @@ namespace GrasscutterTools.Forms private System.Windows.Forms.PictureBox GrasscutterToolsIcon; private System.Windows.Forms.GroupBox GrpSettings; private System.Windows.Forms.CheckBox ChkTopMost; - private System.Windows.Forms.CheckBox ChkNewCommand; private System.Windows.Forms.ComboBox CmbLanguage; private System.Windows.Forms.Label LblLanguage; private System.Windows.Forms.NumericUpDown NUDUid; @@ -2294,5 +2326,10 @@ namespace GrasscutterTools.Forms private System.Windows.Forms.LinkLabel LnkLinks; private System.Windows.Forms.Button BtnUnlockStat; private System.Windows.Forms.Button BtnLockStat; + private System.Windows.Forms.Label LblGCVersion; + private System.Windows.Forms.ComboBox CmbGcVersions; + private System.Windows.Forms.Label LblPermNewCommandTip; + private System.Windows.Forms.Button BtnPermClear; + private System.Windows.Forms.Button BtnPermList; } } diff --git a/Source/GrasscutterTools/Forms/FormMain.cs b/Source/GrasscutterTools/Forms/FormMain.cs index 2e3a821..669cd3a 100644 --- a/Source/GrasscutterTools/Forms/FormMain.cs +++ b/Source/GrasscutterTools/Forms/FormMain.cs @@ -23,6 +23,7 @@ using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; +using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; @@ -39,7 +40,7 @@ namespace GrasscutterTools.Forms { public partial class FormMain : Form { - #region - 初始化 - + #region - 初始化 Init - public FormMain() { @@ -52,7 +53,6 @@ namespace GrasscutterTools.Forms private void FormMain_Load(object sender, EventArgs e) { - MultiLanguage.LoadLanguage(this, typeof(FormMain)); #if DEBUG Text += " - by jie65535 - v" + AppVersion.ToString(3) + "-debug"; #else @@ -73,8 +73,6 @@ namespace GrasscutterTools.Forms InitQuestList(); ChangeTPArtifact(); - ChangeBtnGiveAllChar(); - } private void FormMain_FormClosed(object sender, FormClosedEventArgs e) @@ -82,31 +80,40 @@ namespace GrasscutterTools.Forms SaveSettings(); } - private readonly string[] LanguageNames = new string[] { "简体中文", "繁體中文", "English", "Русский" }; - private readonly string[] Languages = new string[] { "zh-CN", "zh-TW", "en-US", "ru-RU" }; - + /// + /// 应用版本 + /// private Version AppVersion; + + /// + /// 加载应用版本 + /// private void LoadVersion() { AppVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; } + /// + /// 载入设置 + /// private void LoadSettings() { try { + // 恢复自动复制选项状态 ChkAutoCopy.Checked = Settings.Default.AutoCopy; - NUDUid.Value = Settings.Default.Uid; - ChkTopMost.Checked = Settings.Default.IsTopMost; - ChkNewCommand.Checked = Settings.Default.CommandVersion == "1.2.2"; - - CmbLanguage.Items.AddRange(LanguageNames); - CmbLanguage.SelectedIndex = Array.IndexOf(Languages, Settings.Default.DefaultLanguage); - + + // 初始化首页设置 + InitHomeSettings(); + // 初始化获取物品记录 InitGiveItemRecord(); + + // 初始化生成记录 InitSpawnRecord(); + + // 初始化开放命令 InitOpenCommand(); } catch (Exception ex) @@ -115,14 +122,14 @@ namespace GrasscutterTools.Forms } } + /// + /// 保存设置 + /// private void SaveSettings() { try { Settings.Default.AutoCopy = ChkAutoCopy.Checked; - Settings.Default.Uid = NUDUid.Value; - Settings.Default.IsTopMost = ChkTopMost.Checked; - Settings.Default.CommandVersion = ChkNewCommand.Checked ? "1.2.2" : string.Empty; SaveCustomCommands(); SaveGiveItemRecord(); SaveSpawnRecord(); @@ -172,12 +179,60 @@ namespace GrasscutterTools.Forms #endif } - #endregion - 初始化 - + #endregion - 初始化 Init - - #region - 主页 - + #region - 主页 Home - + /// + /// 命令版本 + /// + private CommandVersion CommandVersion; + + /// + /// 卡池编辑器窗口实例 + /// private Form GachaBannerEditor; + /// + /// 初始化首页设置 + /// + private void InitHomeSettings() + { + // 玩家UID + NUDUid.Value = Settings.Default.Uid; + NUDUid.ValueChanged += (o, e) => Settings.Default.Uid = NUDUid.Value; + + // 置顶 + ChkTopMost.Checked = Settings.Default.IsTopMost; + ChkTopMost.CheckedChanged += (o, e) => Settings.Default.IsTopMost = TopMost = ChkTopMost.Checked; + + // 命令版本初始化 + CommandVersion = Version.TryParse(Settings.Default.CommandVersion, out Version current) ? new CommandVersion(current) : CommandVersion.Latest(); + CmbGcVersions.DataSource = CommandVersion.List.Select(it => it.ToString(3)).ToList(); + CmbGcVersions.SelectedIndex = Array.IndexOf(CommandVersion.List, CommandVersion.Current); + CmbGcVersions.SelectedIndexChanged += (o, e) => CommandVersion.Current = CommandVersion.List[CmbGcVersions.SelectedIndex]; + CommandVersion.VersionChanged += OnCommandVersionChanged; + + + // 初始化多语言 + CmbLanguage.DataSource = MultiLanguage.LanguageNames; + if (string.IsNullOrEmpty(Settings.Default.DefaultLanguage)) + { + // 如果未选择语言,则默认载入本地语言 + var i = Array.IndexOf(MultiLanguage.Languages, Thread.CurrentThread.CurrentUICulture); + // 仅支持时切换,避免重复加载 + if (i > 0) CmbLanguage.SelectedIndex = i; + } + else + { + CmbLanguage.SelectedIndex = Array.IndexOf(MultiLanguage.Languages, Settings.Default.DefaultLanguage); + } + CmbLanguage.SelectedIndexChanged += CmbLanguage_SelectedIndexChanged; + } + + /// + /// 点击打开卡池编辑器时触发 + /// private void BtnOpenGachaBannerEditor_Click(object sender, EventArgs e) { if (GachaBannerEditor == null || GachaBannerEditor.IsDisposed) @@ -192,6 +247,9 @@ namespace GrasscutterTools.Forms } } + /// + /// 文本浏览器窗口实例 + /// private FormTextMapBrowser TextMapBrowser; private void BtnOpenTextMap_Click(object sender, EventArgs e) @@ -207,6 +265,1658 @@ namespace GrasscutterTools.Forms TextMapBrowser.TopMost = false; } } + + /// + /// 语言选中项改变时触发 + /// + private void CmbLanguage_SelectedIndexChanged(object sender, EventArgs e) + { + if (CmbLanguage.SelectedIndex < 0) return; + // 切换默认语言 + MultiLanguage.SetDefaultLanguage(MultiLanguage.Languages[CmbLanguage.SelectedIndex]); + // 动态更改语言 + MultiLanguage.LoadLanguage(this, typeof(FormMain)); + // 重新载入页面资源 + FormMain_Load(this, EventArgs.Empty); + } + + /// + /// 命令版本改变时触发 + /// + /// + /// + private void OnCommandVersionChanged(object sender, EventArgs e) + { + Settings.Default.CommandVersion = CommandVersion.Current.ToString(3); + ChangeTPArtifact(); + } + + #endregion - 主页 Home - + + #region - 自定义 Custom - + + /// + /// 自定义命令保存位置 + /// + private readonly string CustomCommandsFilePath = Path.Combine(Application.LocalUserAppDataPath, "CustomCommands.txt"); + + /// + /// 自定义命令是否存在更改 + /// + private bool CustomCommandsChanged; + + /// + /// 加载自定义命令 + /// + private void LoadCustomCommands() + { + if (File.Exists(CustomCommandsFilePath)) + LoadCustomCommandControls(File.ReadAllText(CustomCommandsFilePath)); + else + LoadCustomCommandControls(Resources.CustomCommands); + } + + /// + /// 加载自定义命令控件列表 + /// + /// 命令集(示例:"标签1\n命令1\n标签2\n命令2") + private void LoadCustomCommandControls(string commands) + { + FLPCustomCommands.Controls.Clear(); + var lines = commands.Split('\n'); + for (int i = 0; i < lines.Length - 1; i += 2) + AddCustomCommand(lines[i].Trim(), lines[i + 1].Trim()); + } + + /// + /// 保存自定义命令 + /// + private void SaveCustomCommands() + { + if (CustomCommandsChanged) + File.WriteAllText(CustomCommandsFilePath, SaveCustomCommandControls()); + } + + /// + /// 保存自定义命令控件列表 + /// + /// 命令集(示例:"标签1\n命令1\n标签2\n命令2") + private string SaveCustomCommandControls() + { + StringBuilder builder = new StringBuilder(); + foreach (LinkLabel lnk in FLPCustomCommands.Controls) + { + builder.AppendLine(lnk.Text); + builder.AppendLine(lnk.Tag as string); + } + return builder.ToString(); + } + + /// + /// 自定义命令点击时触发 + /// + private void CustomCommand_Click(object sender, LinkLabelLinkClickedEventArgs e) + { + if (sender is LinkLabel lnk && lnk.Tag is string command) + { + TxtCustomName.Text = lnk.Text; + SetCommand(command); + } + } + + /// + /// 点击保存自定义命令列表时触发 + /// + /// + /// + private async void BtnSaveCustomCommand_Click(object sender, EventArgs e) + { + if (string.IsNullOrWhiteSpace(TxtCustomName.Text)) + { + MessageBox.Show(Resources.CommandTagCannotBeEmpty, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + if (string.IsNullOrWhiteSpace(TxtCommand.Text)) + { + MessageBox.Show(Resources.CommandContentCannotBeEmpty, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + var name = TxtCustomName.Text.Trim(); + var command = TxtCommand.Text.Trim(); + + foreach (LinkLabel lnk in FLPCustomCommands.Controls) + { + if (lnk.Text == name) + { + lnk.Tag = command; + CustomCommandsChanged = true; + await ButtonComplete(BtnSaveCustomCommand); + return; + } + } + + CustomCommandsChanged = true; + AddCustomCommand(name, command); + await ButtonComplete(BtnSaveCustomCommand); + } + + /// + /// 添加自定义命令 + /// + /// 标签 + /// 命令 + private void AddCustomCommand(string name, string command) + { + var lnk = new LinkLabel + { + Text = name, + Tag = command, + AutoSize = true, + }; + lnk.LinkClicked += CustomCommand_Click; + FLPCustomCommands.Controls.Add(lnk); + } + + /// + /// 点击移除自定义命令按钮时触发 + /// + private async void BtnRemoveCustomCommand_Click(object sender, EventArgs e) + { + if (string.IsNullOrWhiteSpace(TxtCustomName.Text)) + { + MessageBox.Show(Resources.CommandTagCannotBeEmpty, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + var name = TxtCustomName.Text.Trim(); + + foreach (LinkLabel lnk in FLPCustomCommands.Controls) + { + if (lnk.Text == name && MessageBox.Show(Resources.AskConfirmDeletion, Resources.Tips, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + FLPCustomCommands.Controls.Remove(lnk); + CustomCommandsChanged = true; + //TxtCustomName.Text = ""; + //TxtCommand.Text = ""; + await ButtonComplete(BtnRemoveCustomCommand); + return; + } + } + + MessageBox.Show(Resources.CommandNotFound, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + /// + /// 点击导入自定义命令时触发 + /// + private void BtnImport_Click(object sender, EventArgs e) + { + var dialog = new OpenFileDialog + { + Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*" + }; + if (dialog.ShowDialog() == DialogResult.OK) + { + using (var stream = dialog.OpenFile()) + using (var reader = new StreamReader(stream)) + { + LoadCustomCommandControls(reader.ReadToEnd()); + CustomCommandsChanged = true; + } + } + } + + /// + /// 点击导出自定义命令时触发 + /// + /// + /// + private void BtnExport_Click(object sender, EventArgs e) + { + var dialog = new SaveFileDialog + { + FileName = "Commands.txt", + Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*" + }; + if (dialog.ShowDialog() == DialogResult.OK) + { + using (var stream = dialog.OpenFile()) + using (var writer = new StreamWriter(stream)) + { + writer.Write(SaveCustomCommandControls()); + } + } + } + + /// + /// 点击重置链接按钮时触发 + /// + private void LnkResetCustomCommands_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + if (MessageBox.Show(Resources.RestoreCustomCommands, Resources.Tips, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes) + { + if (File.Exists(CustomCommandsFilePath)) + File.Delete(CustomCommandsFilePath); + LoadCustomCommandControls(Resources.CustomCommands); + } + } + + #endregion - 自定义 Custom - + + #region - 圣遗物 Artifact - + + /// + /// 副词条集 + /// + private Dictionary>> subAttrs; + + /// + /// 部位标签集 + /// + private string[] ArtifactPartLabels; + + /// + /// 初始化圣遗物列表 + /// + private void InitArtifactList() + { + CmbArtifactSet.Items.Clear(); + CmbArtifactSet.Items.AddRange(GameData.ArtifactCats.Names); + CmbMainAttribution.Items.Clear(); + CmbMainAttribution.Items.AddRange(GameData.ArtifactMainAttribution.Lines); + + subAttrs = new Dictionary>>(); + for (int i = 0; i < GameData.ArtifactSubAttribution.Count; i++) + { + var name = GameData.ArtifactSubAttribution.Names[i]; + var pi = name.IndexOf('+'); + var prefix = name.Substring(0, pi); + var value = name.Substring(pi); + if (!subAttrs.TryGetValue(prefix, out List> list)) + { + list = new List>(); + subAttrs[prefix] = list; + } + list.Add(new KeyValuePair(GameData.ArtifactSubAttribution.Ids[i], value)); + } + CmbSubAttribution.Items.Clear(); + CmbSubAttribution.Items.AddRange(subAttrs.Keys.ToArray()); + + ArtifactPartLabels = Resources.ArtifactPartLabels.Split(','); + } + + /// + /// 福词条下拉框选中项改变时触发 + /// + private void CmbSubAttribution_SelectedIndexChanged(object sender, EventArgs e) + { + CmbSubAttributionValue.Items.Clear(); + if (CmbSubAttribution.SelectedIndex >= 0) + { + CmbSubAttributionValue.Items.AddRange(subAttrs[CmbSubAttribution.SelectedItem as string].Select(kv => kv.Value).ToArray()); + CmbSubAttributionValue.SelectedIndex = 0; + } + } + + /// + /// 点击添加副词条按钮时触发 + /// + private void BtnAddSubAttr_Click(object sender, EventArgs e) + { + if (CmbSubAttribution.SelectedIndex >= 0 && CmbSubAttributionValue.SelectedIndex >= 0) + { + var name = CmbSubAttribution.SelectedItem as string; + var kv = subAttrs[name][CmbSubAttributionValue.SelectedIndex]; + ListSubAttributionChecked.Items.Add($"{kv.Key}:{name}{kv.Value} x{NUDSubAttributionTimes.Value}"); + ArtifactInputChanged(null, EventArgs.Empty); + } + } + + /// + /// 圣遗物套装下拉框选中项改变时触发 + /// + private void CmbArtifactSet_SelectedIndexChanged(object sender, EventArgs e) + { + if (CmbArtifactSet.SelectedIndex < 0) + return; + var setId = GameData.ArtifactCats.Ids[CmbArtifactSet.SelectedIndex]; + var beginIndex = Array.FindIndex(GameData.Artifacts.Ids, id => id / 1000 == setId); + var endIndex = Array.FindLastIndex(GameData.Artifacts.Ids, id => id / 1000 == setId); + + // 限制星级输入范围 + NUDArtifactStars.Minimum = GameData.Artifacts.Ids[beginIndex] / 100 % 10; + NUDArtifactStars.Maximum = GameData.Artifacts.Ids[endIndex] / 100 % 10; + + var parts = GameData.Artifacts.Names.Skip(beginIndex).Take(endIndex - beginIndex + 1).Distinct().ToArray(); + var i = CmbArtifactPart.SelectedIndex; + CmbArtifactPart.Items.Clear(); + CmbArtifactPart.Items.AddRange(parts); + if (i < parts.Length) // 重新选中 + CmbArtifactPart.SelectedIndex = i; + + ArtifactInputChanged(sender, e); + } + + /// + /// 圣遗物部件选中项改变时触发 + /// + private void CmbArtifactPart_SelectedIndexChanged(object sender, EventArgs e) + { + if (CmbArtifactPart.SelectedIndex < 0) + { + LblArtifactName.Text = ""; + return; + } + var name = CmbArtifactPart.SelectedItem as string; + var id = GameData.Artifacts.Ids[Array.IndexOf(GameData.Artifacts.Names, name)]; + var pardIndex = id / 10 % 10 - 1; + if (pardIndex < ArtifactPartLabels?.Length) + LblArtifactName.Text = ArtifactPartLabels[pardIndex]; + else + LblArtifactName.Text = ""; + ArtifactInputChanged(sender, e); + } + + /// + /// 圣遗物页面输入改变时调用 + /// + private void ArtifactInputChanged(object sender, EventArgs e) + { + // 圣遗物ID五位数,ABCDE,其中AB是圣遗物类型(魔女/水/风套......) + // C是星级(5就是五星),D是圣遗物部位,E是初始词条数量 + if (CmbArtifactSet.SelectedIndex < 0 || CmbArtifactPart.SelectedIndex < 0) + return; + //var setId = GameData.ArtifactCats.Ids[CmbArtifactSet.SelectedIndex]; + //var part = CmbArtifactPart.SelectedIndex+1; + //var index = Array.FindLastIndex( + // GameData.Artifacts.Ids, + // it => it / 1000 == setId // 套装ID + // //&& it / 100 % 10 == NUDArtifactStars.Value // 星级 + // && it / 10 % 10 == part // 部位 + // ); + var name = CmbArtifactPart.SelectedItem as string; + var id = GameData.Artifacts.Ids[Array.LastIndexOf(GameData.Artifacts.Names, name)]; + id = id / 1000 * 1000 + (int)NUDArtifactStars.Value * 100 + id % 100; + if (CmbMainAttribution.SelectedIndex < 0) + { + if (Check(CommandVersion.V1_2_2)) + SetCommand("/give", $"{id} lv{NUDArtifactLevel.Value}"); + else + SetCommand("/giveart", $"{id} {NUDArtifactLevel.Value}"); + } + else + { + var t = CmbMainAttribution.SelectedItem as string; + var mainAttr = t.Substring(0, t.IndexOf(':')).Trim(); + + var subAttrs = ""; + if (ListSubAttributionChecked.Items.Count > 0) + { + var subAttrDir = new Dictionary(ListSubAttributionChecked.Items.Count); + foreach (string item in ListSubAttributionChecked.Items) + { + var subId = item.Substring(0, item.IndexOf(':')).Trim(); + var times = int.Parse(item.Substring(item.LastIndexOf('x') + 1)); + if (subAttrDir.ContainsKey(subId)) + subAttrDir[subId] += times; + else + subAttrDir[subId] = times; + } + + foreach (var kv in subAttrDir) + { + if (kv.Value > 1) + subAttrs += $"{kv.Key},{kv.Value} "; + else + subAttrs += $"{kv.Key} "; + } + } + if (Check(CommandVersion.V1_2_2)) + SetCommand("/give", $"{id} lv{NUDArtifactLevel.Value} {mainAttr} {subAttrs}"); + else + SetCommand("/giveart", $"{id} {mainAttr} {subAttrs}{NUDArtifactLevel.Value}"); + } + } + + /// + /// 已添加的副词条列表选中项改变时触发 + /// + private void ListSubAttributionChecked_SelectedIndexChanged(object sender, EventArgs e) + { + if (ListSubAttributionChecked.SelectedIndex >= 0) + { + ListSubAttributionChecked.Items.RemoveAt(ListSubAttributionChecked.SelectedIndex); + ListSubAttributionChecked.ClearSelected(); + ArtifactInputChanged(null, EventArgs.Empty); + } + } + + /// + /// 清除词条链接标签点击时触发 + /// + /// + /// + private void LblClearSubAttrCheckedList_Click(object sender, EventArgs e) + { + CmbMainAttribution.SelectedIndex = -1; + ListSubAttributionChecked.Items.Clear(); + ArtifactInputChanged(null, EventArgs.Empty); + } + + /// + /// 改变圣遗物等级输入范围(旧版本范围是1-21) + /// + private void ChangeTPArtifact() + { + if (Check(CommandVersion.V1_2_2)) + { + NUDArtifactLevel.Minimum = 0; + NUDArtifactLevel.Maximum = 20; + } + else + { + NUDArtifactLevel.Minimum = 1; + NUDArtifactLevel.Maximum = 21; + } + LblArtifactLevelTip.Text = $"[{NUDArtifactLevel.Minimum}-{NUDArtifactLevel.Maximum}]"; + } + + #endregion - 圣遗物 Artifact - + + #region - 武器 Weapons - + + /// + /// 初始化武器列表 + /// + private void InitWeapons() + { + ListWeapons.Items.Clear(); + ListWeapons.Items.AddRange(GameData.Weapons.Lines); + } + + /// + /// 武器列表过滤器文本改变时触发 + /// + private void TxtWeaponFilter_TextChanged(object sender, EventArgs e) + { + var filter = TxtWeaponFilter.Text.Trim(); + ListWeapons.BeginUpdate(); + ListWeapons.Items.Clear(); + ListWeapons.Items.AddRange(GameData.Weapons.Lines.Where(n => n.Contains(filter)).ToArray()); + ListWeapons.EndUpdate(); + } + + /// + /// 武器页面输入改变时触发 + /// + private void WeaponValueChanged(object sender, EventArgs e) + { + var name = ListWeapons.SelectedItem as string; + if (!string.IsNullOrEmpty(name)) + { + var id = name.Substring(0, name.IndexOf(':')).Trim(); + if (Check(CommandVersion.V1_2_2)) + SetCommand("/give", $"{id} x{NUDWeaponAmout.Value} lv{NUDWeaponLevel.Value} r{NUDWeaponRefinement.Value}"); + else + SetCommand("/give", $"{id} {NUDWeaponAmout.Value} {NUDWeaponLevel.Value} {NUDWeaponRefinement.Value}"); + } + } + + #endregion - 武器 Weapons - + + #region - 物品 Items - + + /// + /// 初始化游戏物品列表 + /// + private void InitGameItemList() + { + ListGameItems.Items.Clear(); + ListGameItems.Items.AddRange(GameData.Items.Lines); + } + + /// + /// 物品列表过滤器文本改变时触发 + /// + private void TxtGameItemFilter_TextChanged(object sender, EventArgs e) + { + var filter = TxtGameItemFilter.Text.Trim(); + ListGameItems.BeginUpdate(); + ListGameItems.Items.Clear(); + ListGameItems.Items.AddRange(GameData.Items.Lines.Where(n => n.Contains(filter)).ToArray()); + ListGameItems.EndUpdate(); + } + + /// + /// 生成获取物品命令 + /// + /// 是否生成成功 + private bool GenGiveItemCommand() + { + var name = ListGameItems.SelectedItem as string; + if (!string.IsNullOrEmpty(name)) + { + var id = name.Substring(0, name.IndexOf(':')).Trim(); + + if (ChkDrop.Checked) + { + NUDGameItemLevel.Enabled = false; + SetCommand("/drop", $"{id} {NUDGameItemAmout.Value}"); + } + else + { + NUDGameItemLevel.Enabled = true; + if (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}", TxtCommand.Text); + GiveItemCommands.Add(cmd); + ListGiveItemLogs.Items.Add(cmd.Name); + } + } + + /// + /// 点击移除获取物品记录时触发 + /// + private void BtnRemoveGiveItemLog_Click(object sender, EventArgs e) + { + if (ListGiveItemLogs.SelectedIndex >= 0) + { + GiveItemCommands.RemoveAt(ListGiveItemLogs.SelectedIndex); + ListGiveItemLogs.Items.RemoveAt(ListGiveItemLogs.SelectedIndex); + } + } + + /// + /// 点击清空获取物品记录时触发 + /// + 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(); + } + } + + #endregion -- 物品记录 -- + + #endregion - 物品 Items - + + #region - 角色 Avatars - + + /// + /// 初始化角色列表 + /// + 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 AvatarInputChanged() + { + if (CmbAvatar.SelectedIndex >= 0) + GenAvatar((int)NUDAvatarLevel.Value); + } + + /// + /// 获取角色命令 + /// + /// 等级 + private void GenAvatar(int level) + { + if (Check(CommandVersion.V1_2_2)) + { + int avatarId = GameData.Avatars.Ids[CmbAvatar.SelectedIndex]; + SetCommand("/give", $"{avatarId} lv{level}"); + } + 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; + SetCommand("/give avatars", $"lv{level} c{constellation}"); + } + + #endregion - 角色 Avatars - + + #region - 生成 Spawns - + + /// + /// 初始化实体列表 + /// + private void InitEntityList() + { + RbEntityAnimal.Tag = GameData.Animals.Lines; + RbEntityMonster.Tag = GameData.Monsters.Lines; + RbEntityNPC.Tag = GameData.NPCs.Lines; + RbEntityAnimal.Checked = true; + LoadEntityList(); + } + + /// + /// 加载实体列表 + /// + private void LoadEntityList() + { + var rb = RbEntityAnimal.Checked ? RbEntityAnimal : + RbEntityMonster.Checked ? RbEntityMonster : + RbEntityNPC; + if (rb.Checked) + { + ListEntity.BeginUpdate(); + ListEntity.Items.Clear(); + ListEntity.Items.AddRange(rb.Tag as string[]); + ListEntity.EndUpdate(); + } + } + + /// + /// 实体列表过滤器文本改变时触发 + /// + private void TxtEntityFilter_TextChanged(object sender, EventArgs e) + { + var filter = TxtEntityFilter.Text.Trim(); + var rb = RbEntityAnimal.Checked ? RbEntityAnimal : + RbEntityMonster.Checked ? RbEntityMonster : + RbEntityNPC; + var data = rb.Tag as string[]; + ListEntity.BeginUpdate(); + ListEntity.Items.Clear(); + ListEntity.Items.AddRange(data.Where(n => n.Contains(filter)).ToArray()); + ListEntity.EndUpdate(); + } + + /// + /// 生成召唤实体命令 + /// + /// 是否生成成功 + private bool GenSpawnEntityCommand() + { + var selectedItem = ListEntity.SelectedItem as string; + if (!string.IsNullOrEmpty(selectedItem)) + { + var id = selectedItem.Substring(0, selectedItem.IndexOf(':')).Trim(); + SetCommand("/spawn", $"{id} {NUDEntityAmout.Value} {NUDEntityLevel.Value}"); + return true; + } + return false; + } + + /// + /// 生成页面输入改变时触发 + /// + private void SpawnEntityInputChanged(object sender, EventArgs e) + { + GenSpawnEntityCommand(); + } + + /// + /// 列表过滤选项切换时触发 + /// + private void RbEntity_CheckedChanged(object sender, EventArgs e) + { + LoadEntityList(); + } + + #region -- 生成记录 -- + + /// + /// 生成命令记录文件路径 + /// + private readonly string SpawnCommandsRecordPath = Path.Combine(Application.LocalUserAppDataPath, "SpawnCommands.txt"); + + /// + /// 生成命令记录 + /// + private List SpawnCommands; + + /// + /// 初始化生成记录 + /// + private void InitSpawnRecord() + { + if (File.Exists(SpawnCommandsRecordPath)) + { + SpawnCommands = GetCommands(File.ReadAllText(SpawnCommandsRecordPath)); + ListSpawnLogs.Items.AddRange(SpawnCommands.Select(c => c.Name).ToArray()); + } + else + { + SpawnCommands = new List(); + } + } + + /// + /// 保存生成记录 + /// + private void SaveSpawnRecord() + { + File.WriteAllText(SpawnCommandsRecordPath, GetCommandsText(SpawnCommands)); + } + + /// + /// 生成记录列表选中项改变时触发 + /// + private void ListSpawnLogs_SelectedIndexChanged(object sender, EventArgs e) + { + if (ListSpawnLogs.SelectedIndex >= 0) + { + BtnRemoveSpawnLog.Enabled = true; + SetCommand(SpawnCommands[ListSpawnLogs.SelectedIndex].Command); + } + else + { + BtnRemoveSpawnLog.Enabled = false; + } + } + + /// + /// 点击保存生成记录按钮时触发 + /// + private void BtnSaveSpawnLog_Click(object sender, EventArgs e) + { + if (GenSpawnEntityCommand()) + { + var cmd = new GameCommand($"{ListEntity.SelectedItem} Lv{NUDEntityLevel.Value} x{NUDEntityAmout.Value}", TxtCommand.Text); + SpawnCommands.Add(cmd); + ListSpawnLogs.Items.Add(cmd.Name); + } + } + + /// + /// 点击移除生成记录按钮时触发 + /// + private void BtnRemoveSpawnLog_Click(object sender, EventArgs e) + { + if (ListSpawnLogs.SelectedIndex >= 0) + { + SpawnCommands.RemoveAt(ListSpawnLogs.SelectedIndex); + ListSpawnLogs.Items.RemoveAt(ListSpawnLogs.SelectedIndex); + } + } + + /// + /// 点击清空生成记录按钮时触发 + /// + private void LblClearSpawnLogs_Click(object sender, EventArgs e) + { + if (MessageBox.Show(Resources.AskConfirmDeletion, Resources.Tips, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + SpawnCommands.Clear(); + ListSpawnLogs.Items.Clear(); + } + } + + #endregion -- 生成记录 -- + + #endregion - 生成 Spawns - + + #region - 场景 Scenes - + + /// + /// 初始化场景列表 + /// + private void InitScenes() + { + ListScenes.Items.Clear(); + ListScenes.Items.AddRange(GameData.Scenes.Lines); + + CmbClimateType.Items.Clear(); + CmbClimateType.Items.AddRange(Resources.ClimateType.Split(',')); + } + + /// + /// 场景列表过滤器输入项改变时触发 + /// + private void TxtSceneFilter_TextChanged(object sender, EventArgs e) + { + var filter = TxtSceneFilter.Text.Trim(); + ListScenes.BeginUpdate(); + ListScenes.Items.Clear(); + ListScenes.Items.AddRange(GameData.Scenes.Lines.Where(n => n.Contains(filter)).ToArray()); + ListScenes.EndUpdate(); + } + + /// + /// 场景列表选中项改变时触发 + /// + 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 = name.Substring(0, name.IndexOf(':')).Trim(); + if (Check(CommandVersion.V1_2_2)) + { + SetCommand("/scene", id.ToString()); + } + else + { + SetCommand("/tp ~ ~ ~", 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 (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 && ListScenes.SelectedIndex != -1) + args += $" {GameData.Scenes.Ids[ListScenes.SelectedIndex]}"; + SetCommand("/tp", args); + } + + #endregion - 场景 Scenes - + + #region - 数据 Stats - + + /// + /// 初始化数据列表 + /// + 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}"); + } + + /// + /// 点击设置技能按钮时触发 + /// + private void LnkSetTalentClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + SetCommand("/talent", $"{(sender as LinkLabel).Tag} {NUDTalentLevel.Value}"); + } + + #endregion - 数据 Stats - + + #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 - 关于 About - + + /// + /// 点击Github链接时触发 + /// + private void LnkGithub_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + OpenURL("https://github.com/jie65535/GrasscutterCommandGenerator"); + } + + #endregion - 关于 About - + + #region - 命令 Command - + + /// + /// 设置命令 + /// + /// 命令 + private void SetCommand(string command) + { + TxtCommand.Text = command; + if (ChkAutoCopy.Checked) + CopyCommand(); + if (ModifierKeys == Keys.Control) + OnOpenCommandInvoke(); + } + + /// + /// 设置带参数的命令 + /// + /// 命令 + /// 参数 + 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 ButtonComplete(BtnCopy); + } + + /// + /// 复制命令 + /// + private void CopyCommand() + { + if (!string.IsNullOrEmpty(TxtCommand.Text)) + Clipboard.SetText(TxtCommand.Text); + } + + /// + /// 开放命令执行时触发 + /// + private void OnOpenCommandInvoke() + { + BtnInvokeOpenCommand_Click(BtnInvokeOpenCommand, EventArgs.Empty); + } + + /// + /// 点击执行开放命令按钮时触发 + /// + private async void BtnInvokeOpenCommand_Click(object sender, EventArgs e) + { + if (!BtnInvokeOpenCommand.Enabled) return; + if (TxtCommand.Text.Length < 2) + { + ShowTip(Resources.CommandContentCannotBeEmpty, TxtCommand); + return; + } + await RunCommands(TxtCommand.Text); + } + + /// + /// 运行命令 + /// + /// 命令列表 + /// 是否执行成功 + 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.Substring(1); + 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 async Task ButtonComplete(Button btn) + { + var t = btn.Text; + btn.Text = "√"; + btn.Enabled = false; + await Task.Delay(300); + btn.Text = t; + btn.Enabled = true; + } + + /// + /// 窗口按键按下时触发 + /// + 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); + } + + /// + /// 检查命令版本 + /// + /// 最低要求版本 + /// 当前版本是否满足 + private bool Check(Version version) => CommandVersion.Current >= version; + + #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 - + + #region - 远程 Remote - + + /// + /// 开放命令接口 + /// + private OpenCommandAPI OC; + + /// + /// 初始化开放命令 + /// + private void InitOpenCommand() + { + NUDRemotePlayerId.Value = Settings.Default.RemoteUid; + TxtHost.Text = Settings.Default.Host; + if (!string.IsNullOrEmpty(Settings.Default.Host) && !string.IsNullOrEmpty(Settings.Default.TokenCache)) + { + OC = new OpenCommandAPI(Settings.Default.Host, Settings.Default.TokenCache); + TxtToken.Text = Settings.Default.TokenCache; + Task.Run(async () => + { + await Task.Delay(1000); + BeginInvoke(new Action(() => ShowTip(Resources.TokenRestoredFromCache, BtnInvokeOpenCommand))); + }); + } + else + { +#if !DEBUG + // 自动尝试查询本地服务端地址,降低使用门槛 + Task.Run(async () => + { + await Task.Delay(5000); + var localhosts = new string[] { + "http://127.0.0.1:443", + "https://127.0.0.1", + "http://127.0.0.1", + "https://127.0.0.1:80", + "http://127.0.0.1:8080", + "https://127.0.0.1:8080", + }; + foreach (var host in localhosts) + { + try + { + await UpdateServerStatus(host); + // 自动填写本地服务端地址 + TxtHost.Text = host; + break; + } + catch (Exception) + { + // Ignore + } + } + }); +#endif + } + } + + /// + /// 保存开放命令参数 + /// + private void SaveOpenCommand() + { + Settings.Default.RemoteUid = NUDRemotePlayerId.Value; + Settings.Default.Host = TxtHost.Text; + Settings.Default.TokenCache = OC?.Token; + } + + /// + /// 更新服务器状态 + /// + /// 主机地址 + private async Task UpdateServerStatus(string host) + { + var status = await DispatchServerAPI.QueryServerStatus(host); + LblServerVersion.Text = status.Version; + if (status.MaxPlayer >= 0) + LblPlayerCount.Text = $"{status.PlayerCount}/{status.MaxPlayer}"; + else + LblPlayerCount.Text = status.PlayerCount.ToString(); + } + + /// + /// 点击查询服务器状态按钮时触发 + /// + private async void BtnQueryServerStatus_Click(object sender, EventArgs e) + { + var btn = sender as Button; + btn.Enabled = false; + btn.Cursor = Cursors.WaitCursor; + try + { + try + { + await UpdateServerStatus(TxtHost.Text); + } + catch (Exception ex) + { + MessageBox.Show(Resources.QueryServerStatusFailed + ex.Message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + OC = new OpenCommandAPI(TxtHost.Text); + if (await OC.Ping()) + { + LblOpenCommandSupport.Text = "√"; + LblOpenCommandSupport.ForeColor = Color.Green; + GrpRemoteCommand.Enabled = true; + } + else + { + LblOpenCommandSupport.Text = "×"; + LblOpenCommandSupport.ForeColor = Color.Red; + GrpRemoteCommand.Enabled = false; + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally + { + btn.Cursor = Cursors.Default; + btn.Enabled = true; + } + } + + /// + /// 点击发送校验码按钮时触发 + /// + private async void BtnSendVerificationCode_Click(object sender, EventArgs e) + { + var btn = sender as Button; + var t = btn.Text; + btn.Enabled = false; + NUDRemotePlayerId.Enabled = false; + try + { + btn.Text = Resources.CodeSending; + await OC.SendCode((int)NUDRemotePlayerId.Value); + BtnConnectOpenCommand.Enabled = true; + NUDVerificationCode.Enabled = true; + NUDVerificationCode.Focus(); + for (int i = 60; i > 0 && !OC.CanInvoke; i--) + { + btn.Text = string.Format(Resources.CodeResendTip, i); + await Task.Delay(1000); + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally + { + btn.Text = t; + btn.Enabled = true; + NUDRemotePlayerId.Enabled = true; + } + } + + /// + /// 点击连接到开放命令按钮时触发 + /// + /// + /// + private async void BtnConnectOpenCommand_Click(object sender, EventArgs e) + { + var btn = sender as Button; + btn.Enabled = false; + try + { + await OC.Verify((int)NUDVerificationCode.Value); + GrpRemoteCommand.Enabled = false; + BtnInvokeOpenCommand.Focus(); + ShowTip(Resources.ConnectedTip, BtnInvokeOpenCommand); + ButtonOpenGOODImport.Enabled = true; + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally + { + btn.Cursor = Cursors.Default; + btn.Enabled = true; + } + } + + /// + /// 点击控制台连接按钮时触发 + /// + private void BtnConsoleConnect_Click(object sender, EventArgs e) + { + if (string.IsNullOrEmpty(TxtToken.Text)) + { + MessageBox.Show(Resources.TokenCannotBeEmpty, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + OC.Token = TxtToken.Text; + BtnConnectOpenCommand_Click(sender, e); + } + + /// + /// 点击开放命令标签时触发 + /// + private void LnkOpenCommandLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + OpenURL("https://github.com/jie65535/gc-opencommand-plugin"); + } + + /// + /// 点击帮助连接标签时触发 + /// + private void LnkRCHelp_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + MessageBox.Show(Resources.OpenCommandHelp, Resources.Help, MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + /// + /// 点击库存扫描链接标签时触发 + /// + private void LnkInventoryKamera_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + OpenURL("https://github.com/Andrewthe13th/Inventory_Kamera"); + } + + /// + /// 点击GOOD帮助链接标签时触发 + /// + private void LnkGOODHelp_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + OpenURL("https://frzyc.github.io/genshin-optimizer/#/doc"); + } + + /// + /// 点击链接帮助标签时触发 + /// + private void LnkLinks_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + var links = new List + { + "https://frzyc.github.io/genshin-optimizer/", + "https://genshin.aspirine.su/", + "https://genshin.mingyulab.com/", + "https://genshin-center.com/", + "https://github.com/Andrewthe13th/Inventory_Kamera", + "https://github.com/daydreaming666/Amenoma", + "https://seelie.me/", + "https://www.mona-uranai.com/", + }; + MessageBox.Show(string.Join("\n", links), "Links", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + /// + /// 使用浏览器打开网址 + /// + /// 网址 + private void OpenURL(string url) + { + try + { + System.Diagnostics.Process.Start(url); + } + catch (Exception) + { + MessageBox.Show(Resources.BrowserOpenFailedTip + "\n " + url, + Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + } + + #endregion - 远程 Remote - + + #region - GOOD - + + /// + /// 点击GOOD导入存档按钮时触发 + /// async private void ButtonOpenGOODImport_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog1 = new OpenFileDialog @@ -327,1280 +2037,21 @@ namespace GrasscutterTools.Forms } } - private void CmbLanguage_SelectedIndexChanged(object sender, EventArgs e) - { - MultiLanguage.SetDefaultLanguage(Languages[CmbLanguage.SelectedIndex]); - FormMain_Load(this, EventArgs.Empty); - } + #endregion - private void ChkTopMost_CheckedChanged(object sender, EventArgs e) - { - TopMost = ChkTopMost.Checked; - } - - private void ChkNewCommand_CheckedChanged(object sender, EventArgs e) - { - ChangeTPArtifact(); - ChangeBtnGiveAllChar(); - } - - #endregion - 主页 - - - #region - 自定义 - - - private readonly string CustomCommandsFilePath = Path.Combine(Application.LocalUserAppDataPath, "CustomCommands.txt"); - - private bool CustomCommandsChanged; - - private void LoadCustomCommands() - { - if (File.Exists(CustomCommandsFilePath)) - LoadCustomCommandControls(File.ReadAllText(CustomCommandsFilePath)); - else - LoadCustomCommandControls(Resources.CustomCommands); - } - - private void LoadCustomCommandControls(string commands) - { - FLPCustomCommands.Controls.Clear(); - var lines = commands.Split('\n'); - for (int i = 0; i < lines.Length - 1; i += 2) - AddCustomCommand(lines[i].Trim(), lines[i + 1].Trim()); - } - - private void SaveCustomCommands() - { - if (CustomCommandsChanged) - File.WriteAllText(CustomCommandsFilePath, SaveCustomCommandControls()); - } - - private string SaveCustomCommandControls() - { - StringBuilder builder = new StringBuilder(); - foreach (LinkLabel lnk in FLPCustomCommands.Controls) - { - builder.AppendLine(lnk.Text); - builder.AppendLine(lnk.Tag as string); - } - return builder.ToString(); - } - - private void CustomCommand_Click(object sender, LinkLabelLinkClickedEventArgs e) - { - if (sender is LinkLabel lnk && lnk.Tag is string command) - { - TxtCustomName.Text = lnk.Text; - SetCommand(command); - } - } - - private async void BtnSaveCustomCommand_Click(object sender, EventArgs e) - { - if (string.IsNullOrWhiteSpace(TxtCustomName.Text)) - { - MessageBox.Show(Resources.CommandTagCannotBeEmpty, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - if (string.IsNullOrWhiteSpace(TxtCommand.Text)) - { - MessageBox.Show(Resources.CommandContentCannotBeEmpty, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - var name = TxtCustomName.Text.Trim(); - var command = TxtCommand.Text.Trim(); - - foreach (LinkLabel lnk in FLPCustomCommands.Controls) - { - if (lnk.Text == name) - { - lnk.Tag = command; - CustomCommandsChanged = true; - await ButtonComplete(BtnSaveCustomCommand); - return; - } - } - - CustomCommandsChanged = true; - AddCustomCommand(name, command); - await ButtonComplete(BtnSaveCustomCommand); - } - - private void AddCustomCommand(string name, string command) - { - var lnk = new LinkLabel - { - Text = name, - Tag = command, - AutoSize = true, - }; - lnk.LinkClicked += CustomCommand_Click; - FLPCustomCommands.Controls.Add(lnk); - } - - private async void BtnRemoveCustomCommand_Click(object sender, EventArgs e) - { - if (string.IsNullOrWhiteSpace(TxtCustomName.Text)) - { - MessageBox.Show(Resources.CommandTagCannotBeEmpty, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - var name = TxtCustomName.Text.Trim(); - - foreach (LinkLabel lnk in FLPCustomCommands.Controls) - { - if (lnk.Text == name && MessageBox.Show(Resources.AskConfirmDeletion, Resources.Tips, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) - { - FLPCustomCommands.Controls.Remove(lnk); - CustomCommandsChanged = true; - //TxtCustomName.Text = ""; - //TxtCommand.Text = ""; - await ButtonComplete(BtnRemoveCustomCommand); - return; - } - } - - MessageBox.Show(Resources.CommandNotFound, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); - } - - private void BtnImport_Click(object sender, EventArgs e) - { - var dialog = new OpenFileDialog - { - Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*" - }; - if (dialog.ShowDialog() == DialogResult.OK) - { - using (var stream = dialog.OpenFile()) - using (var reader = new StreamReader(stream)) - { - LoadCustomCommandControls(reader.ReadToEnd()); - CustomCommandsChanged = true; - } - } - } - - private void BtnExport_Click(object sender, EventArgs e) - { - var dialog = new SaveFileDialog - { - FileName = "Commands.txt", - Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*" - }; - if (dialog.ShowDialog() == DialogResult.OK) - { - using (var stream = dialog.OpenFile()) - using (var writer = new StreamWriter(stream)) - { - writer.Write(SaveCustomCommandControls()); - } - } - } - - private void LnkResetCustomCommands_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - if (MessageBox.Show(Resources.RestoreCustomCommands, Resources.Tips, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes) - { - if (File.Exists(CustomCommandsFilePath)) - File.Delete(CustomCommandsFilePath); - LoadCustomCommandControls(Resources.CustomCommands); - } - } - - #endregion - 自定义 - - - #region - 圣遗物 - - - private Dictionary>> subAttrs; - - private string[] ArtifactPartLabels; - - private void InitArtifactList() - { - CmbArtifactSet.Items.Clear(); - CmbArtifactSet.Items.AddRange(GameData.ArtifactCats.Names); - CmbMainAttribution.Items.Clear(); - CmbMainAttribution.Items.AddRange(GameData.ArtifactMainAttribution.Lines); - - subAttrs = new Dictionary>>(); - for (int i = 0; i < GameData.ArtifactSubAttribution.Count; i++) - { - var name = GameData.ArtifactSubAttribution.Names[i]; - var pi = name.IndexOf('+'); - var prefix = name.Substring(0, pi); - var value = name.Substring(pi); - if (!subAttrs.TryGetValue(prefix, out List> list)) - { - list = new List>(); - subAttrs[prefix] = list; - } - list.Add(new KeyValuePair(GameData.ArtifactSubAttribution.Ids[i], value)); - } - CmbSubAttribution.Items.Clear(); - CmbSubAttribution.Items.AddRange(subAttrs.Keys.ToArray()); - - ArtifactPartLabels = Resources.ArtifactPartLabels.Split(','); - } - - private void CmbSubAttribution_SelectedIndexChanged(object sender, EventArgs e) - { - CmbSubAttributionValue.Items.Clear(); - if (CmbSubAttribution.SelectedIndex >= 0) - { - CmbSubAttributionValue.Items.AddRange(subAttrs[CmbSubAttribution.SelectedItem as string].Select(kv => kv.Value).ToArray()); - CmbSubAttributionValue.SelectedIndex = 0; - } - } - - private void BtnAddSubAttr_Click(object sender, EventArgs e) - { - if (CmbSubAttribution.SelectedIndex >= 0 && CmbSubAttributionValue.SelectedIndex >= 0) - { - var name = CmbSubAttribution.SelectedItem as string; - var kv = subAttrs[name][CmbSubAttributionValue.SelectedIndex]; - ListSubAttributionChecked.Items.Add($"{kv.Key}:{name}{kv.Value} x{NUDSubAttributionTimes.Value}"); - ArtifactInputChanged(null, EventArgs.Empty); - } - } - - private void CmbArtifactSet_SelectedIndexChanged(object sender, EventArgs e) - { - if (CmbArtifactSet.SelectedIndex < 0) - return; - var setId = GameData.ArtifactCats.Ids[CmbArtifactSet.SelectedIndex]; - var beginIndex = Array.FindIndex(GameData.Artifacts.Ids, id => id / 1000 == setId); - var endIndex = Array.FindLastIndex(GameData.Artifacts.Ids, id => id / 1000 == setId); - - // 限制星级输入范围 - NUDArtifactStars.Minimum = GameData.Artifacts.Ids[beginIndex] / 100 % 10; - NUDArtifactStars.Maximum = GameData.Artifacts.Ids[endIndex] / 100 % 10; - - var parts = GameData.Artifacts.Names.Skip(beginIndex).Take(endIndex - beginIndex + 1).Distinct().ToArray(); - var i = CmbArtifactPart.SelectedIndex; - CmbArtifactPart.Items.Clear(); - CmbArtifactPart.Items.AddRange(parts); - if (i < parts.Length) // 重新选中 - CmbArtifactPart.SelectedIndex = i; - - ArtifactInputChanged(sender, e); - } - - private void CmbArtifactPart_SelectedIndexChanged(object sender, EventArgs e) - { - if (CmbArtifactPart.SelectedIndex < 0) - { - LblArtifactName.Text = ""; - return; - } - var name = CmbArtifactPart.SelectedItem as string; - var id = GameData.Artifacts.Ids[Array.IndexOf(GameData.Artifacts.Names, name)]; - var pardIndex = id / 10 % 10 - 1; - if (pardIndex < ArtifactPartLabels?.Length) - LblArtifactName.Text = ArtifactPartLabels[pardIndex]; - else - LblArtifactName.Text = ""; - ArtifactInputChanged(sender, e); - } - - private void ArtifactInputChanged(object sender, EventArgs e) - { - // 圣遗物ID五位数,ABCDE,其中AB是圣遗物类型(魔女/水/风套......) - // C是星级(5就是五星),D是圣遗物部位,E是初始词条数量 - if (CmbArtifactSet.SelectedIndex < 0 || CmbArtifactPart.SelectedIndex < 0) - return; - //var setId = GameData.ArtifactCats.Ids[CmbArtifactSet.SelectedIndex]; - //var part = CmbArtifactPart.SelectedIndex+1; - //var index = Array.FindLastIndex( - // GameData.Artifacts.Ids, - // it => it / 1000 == setId // 套装ID - // //&& it / 100 % 10 == NUDArtifactStars.Value // 星级 - // && it / 10 % 10 == part // 部位 - // ); - var name = CmbArtifactPart.SelectedItem as string; - var id = GameData.Artifacts.Ids[Array.LastIndexOf(GameData.Artifacts.Names, name)]; - id = id / 1000 * 1000 + (int)NUDArtifactStars.Value * 100 + id % 100; - if (CmbMainAttribution.SelectedIndex < 0) - { - if (ChkNewCommand.Checked) - SetCommand("/give", $"{id} lv{NUDArtifactLevel.Value}"); - else - SetCommand("/giveart", $"{id} {NUDArtifactLevel.Value}"); - } - else - { - var t = CmbMainAttribution.SelectedItem as string; - var mainAttr = t.Substring(0, t.IndexOf(':')).Trim(); - - var subAttrs = ""; - if (ListSubAttributionChecked.Items.Count > 0) - { - var subAttrDir = new Dictionary(ListSubAttributionChecked.Items.Count); - foreach (string item in ListSubAttributionChecked.Items) - { - var subId = item.Substring(0, item.IndexOf(':')).Trim(); - var times = int.Parse(item.Substring(item.LastIndexOf('x') + 1)); - if (subAttrDir.ContainsKey(subId)) - subAttrDir[subId] += times; - else - subAttrDir[subId] = times; - } - - foreach (var kv in subAttrDir) - { - if (kv.Value > 1) - subAttrs += $"{kv.Key},{kv.Value} "; - else - subAttrs += $"{kv.Key} "; - } - } - if (ChkNewCommand.Checked) - SetCommand("/give", $"{id} lv{NUDArtifactLevel.Value} {mainAttr} {subAttrs}"); - else - SetCommand("/giveart", $"{id} {mainAttr} {subAttrs}{NUDArtifactLevel.Value}"); - } - } - - private void ListSubAttributionChecked_SelectedIndexChanged(object sender, EventArgs e) - { - if (ListSubAttributionChecked.SelectedIndex >= 0) - { - ListSubAttributionChecked.Items.RemoveAt(ListSubAttributionChecked.SelectedIndex); - ListSubAttributionChecked.ClearSelected(); - ArtifactInputChanged(null, EventArgs.Empty); - } - } - - private void LblClearSubAttrCheckedList_Click(object sender, EventArgs e) - { - CmbMainAttribution.SelectedIndex = -1; - ListSubAttributionChecked.Items.Clear(); - ArtifactInputChanged(null, EventArgs.Empty); - } - - private void ChangeTPArtifact() - { - if (ChkNewCommand.Checked) - { - NUDArtifactLevel.Minimum = 0; - NUDArtifactLevel.Maximum = 20; - } - else - { - NUDArtifactLevel.Minimum = 1; - NUDArtifactLevel.Maximum = 21; - } - LblArtifactLevelTip.Text = $"[{NUDArtifactLevel.Minimum}-{NUDArtifactLevel.Maximum}]"; - } - - #endregion - 圣遗物 - - - #region - 武器 - - - private void InitWeapons() - { - ListWeapons.Items.Clear(); - ListWeapons.Items.AddRange(GameData.Weapons.Lines); - } - - private void TxtWeaponFilter_TextChanged(object sender, EventArgs e) - { - var filter = TxtWeaponFilter.Text.Trim(); - ListWeapons.BeginUpdate(); - ListWeapons.Items.Clear(); - ListWeapons.Items.AddRange(GameData.Weapons.Lines.Where(n => n.Contains(filter)).ToArray()); - ListWeapons.EndUpdate(); - } - - private void WeaponValueChanged(object sender, EventArgs e) - { - var name = ListWeapons.SelectedItem as string; - if (!string.IsNullOrEmpty(name)) - { - var id = name.Substring(0, name.IndexOf(':')).Trim(); - if (ChkNewCommand.Checked) - SetCommand("/give", $"{id} x{NUDWeaponAmout.Value} lv{NUDWeaponLevel.Value} r{NUDWeaponRefinement.Value}"); - else - SetCommand("/give", $"{id} {NUDWeaponAmout.Value} {NUDWeaponLevel.Value} {NUDWeaponRefinement.Value}"); - } - } - - #endregion - 武器 - - - #region - 物品 - - - private void InitGameItemList() - { - ListGameItems.Items.Clear(); - ListGameItems.Items.AddRange(GameData.Items.Lines); - } - - private void TxtGameItemFilter_TextChanged(object sender, EventArgs e) - { - var filter = TxtGameItemFilter.Text.Trim(); - ListGameItems.BeginUpdate(); - ListGameItems.Items.Clear(); - ListGameItems.Items.AddRange(GameData.Items.Lines.Where(n => n.Contains(filter)).ToArray()); - ListGameItems.EndUpdate(); - } - - private bool GenGiveItemCommand() - { - var name = ListGameItems.SelectedItem as string; - if (!string.IsNullOrEmpty(name)) - { - var id = name.Substring(0, name.IndexOf(':')).Trim(); - - if (ChkDrop.Checked) - { - NUDGameItemLevel.Enabled = false; - SetCommand("/drop", $"{id} {NUDGameItemAmout.Value}"); - } - else - { - NUDGameItemLevel.Enabled = true; - if (ChkNewCommand.Checked) - 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}", TxtCommand.Text); - GiveItemCommands.Add(cmd); - ListGiveItemLogs.Items.Add(cmd.Name); - } - } - - private void BtnRemoveGiveItemLog_Click(object sender, EventArgs e) - { - if (ListGiveItemLogs.SelectedIndex >= 0) - { - GiveItemCommands.RemoveAt(ListGiveItemLogs.SelectedIndex); - ListGiveItemLogs.Items.RemoveAt(ListGiveItemLogs.SelectedIndex); - } - } - - 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(); - } - } - - #endregion -- 物品记录 -- - - #endregion - 物品 - - - #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 AvatarInputChanged() - { - if (CmbAvatar.SelectedIndex >= 0) - GenAvatar((int)NUDAvatarLevel.Value); - } - - private void GenAvatar(int level) - { - if (ChkNewCommand.Checked) - { - int avatarId = GameData.Avatars.Ids[CmbAvatar.SelectedIndex]; - SetCommand("/give", $"{avatarId} lv{level}"); - } - 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; - SetCommand("/give avatars", $"lv{level} c{constellation}"); - } - - private void ChangeBtnGiveAllChar() - { - if (ChkNewCommand.Checked) - BtnGiveAllChar.Enabled = true; - else - BtnGiveAllChar.Enabled = false; - } - - #endregion - 角色 - - - #region - 生成 - - - private void InitEntityList() - { - RbEntityAnimal.Tag = GameData.Animals.Lines; - RbEntityMonster.Tag = GameData.Monsters.Lines; - RbEntityNPC.Tag = GameData.NPCs.Lines; - RbEntityAnimal.Checked = true; - LoadEntityList(); - } - private void LoadEntityList() - { - var rb = RbEntityAnimal.Checked ? RbEntityAnimal : - RbEntityMonster.Checked ? RbEntityMonster : - RbEntityNPC; - if (rb.Checked) - { - ListEntity.BeginUpdate(); - ListEntity.Items.Clear(); - ListEntity.Items.AddRange(rb.Tag as string[]); - ListEntity.EndUpdate(); - } - } - - private void TxtEntityFilter_TextChanged(object sender, EventArgs e) - { - var filter = TxtEntityFilter.Text.Trim(); - var rb = RbEntityAnimal.Checked ? RbEntityAnimal : - RbEntityMonster.Checked ? RbEntityMonster : - RbEntityNPC; - var data = rb.Tag as string[]; - ListEntity.BeginUpdate(); - ListEntity.Items.Clear(); - ListEntity.Items.AddRange(data.Where(n => n.Contains(filter)).ToArray()); - ListEntity.EndUpdate(); - } - - private bool GenSpawnEntityCommand() - { - var selectedItem = ListEntity.SelectedItem as string; - if (!string.IsNullOrEmpty(selectedItem)) - { - var id = selectedItem.Substring(0, selectedItem.IndexOf(':')).Trim(); - SetCommand("/spawn", $"{id} {NUDEntityAmout.Value} {NUDEntityLevel.Value}"); - return true; - } - return false; - } - - private void SpawnEntityInputChanged(object sender, EventArgs e) - { - GenSpawnEntityCommand(); - } - - private void RbEntity_CheckedChanged(object sender, EventArgs e) - { - LoadEntityList(); - } - - #region -- 生成记录 -- - - private readonly string SpawnCommandsRecordPath = Path.Combine(Application.LocalUserAppDataPath, "SpawnCommands.txt"); - private List SpawnCommands; - - private void InitSpawnRecord() - { - if (File.Exists(SpawnCommandsRecordPath)) - { - SpawnCommands = GetCommands(File.ReadAllText(SpawnCommandsRecordPath)); - ListSpawnLogs.Items.AddRange(SpawnCommands.Select(c => c.Name).ToArray()); - } - else - { - SpawnCommands = new List(); - } - } - - private void SaveSpawnRecord() - { - File.WriteAllText(SpawnCommandsRecordPath, GetCommandsText(SpawnCommands)); - } - - private void ListSpawnLogs_SelectedIndexChanged(object sender, EventArgs e) - { - if (ListSpawnLogs.SelectedIndex >= 0) - { - BtnRemoveSpawnLog.Enabled = true; - SetCommand(SpawnCommands[ListSpawnLogs.SelectedIndex].Command); - } - else - { - BtnRemoveSpawnLog.Enabled = false; - } - } - - private void BtnSaveSpawnLog_Click(object sender, EventArgs e) - { - if (GenSpawnEntityCommand()) - { - var cmd = new GameCommand($"{ListEntity.SelectedItem} Lv{NUDEntityLevel.Value} x{NUDEntityAmout.Value}", TxtCommand.Text); - SpawnCommands.Add(cmd); - ListSpawnLogs.Items.Add(cmd.Name); - } - } - - private void BtnRemoveSpawnLog_Click(object sender, EventArgs e) - { - if (ListSpawnLogs.SelectedIndex >= 0) - { - SpawnCommands.RemoveAt(ListSpawnLogs.SelectedIndex); - ListSpawnLogs.Items.RemoveAt(ListSpawnLogs.SelectedIndex); - } - } - - private void LblClearSpawnLogs_Click(object sender, EventArgs e) - { - if (MessageBox.Show(Resources.AskConfirmDeletion, Resources.Tips, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) - { - SpawnCommands.Clear(); - ListSpawnLogs.Items.Clear(); - } - } - - #endregion -- 生成记录 -- - - #endregion - 生成 - - - #region - 场景 - - - private void InitScenes() - { - ListScenes.Items.Clear(); - ListScenes.Items.AddRange(GameData.Scenes.Lines); - - CmbClimateType.Items.Clear(); - CmbClimateType.Items.AddRange(Resources.ClimateType.Split(',')); - } - - private void TxtSceneFilter_TextChanged(object sender, EventArgs e) - { - var filter = TxtSceneFilter.Text.Trim(); - ListScenes.BeginUpdate(); - ListScenes.Items.Clear(); - ListScenes.Items.AddRange(GameData.Scenes.Lines.Where(n => n.Contains(filter)).ToArray()); - ListScenes.EndUpdate(); - } - - 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 = name.Substring(0, name.IndexOf(':')).Trim(); - if (!ChkNewCommand.Checked) - { - SetCommand("/scene", id.ToString()); - } - else - { - SetCommand("/tp ~ ~ ~", 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 (ChkNewCommand.Checked) - 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 && ListScenes.SelectedIndex != -1) - args += $" {GameData.Scenes.Ids[ListScenes.SelectedIndex]}"; - SetCommand("/tp", args); - } - - #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}"); - } - - private void LnkSetTalentClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - SetCommand("/talent", $"{(sender as LinkLabel).Tag} {NUDTalentLevel.Value}"); - } - - #endregion - 数据 - - - #region - 管理 - - - 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(); - if (string.IsNullOrEmpty(perm)) - { - MessageBox.Show(Resources.PermissionCannotBeEmpty, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - SetCommand($"/permission {(sender as Button).Tag} @{uid} {perm}"); - } - - 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 - 管理 - - - #region - 关于 - - - private void LnkGithub_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - OpenURL("https://github.com/jie65535/GrasscutterCommandGenerator"); - } - - #endregion - 关于 - - - #region - 命令 - - - private void SetCommand(string command) - { - TxtCommand.Text = command; - if (ChkAutoCopy.Checked) - CopyCommand(); - if (ModifierKeys == Keys.Control) - OnOpenCommandInvoke(); - } - - 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 ButtonComplete(BtnCopy); - } - - private void CopyCommand() - { - if (!string.IsNullOrEmpty(TxtCommand.Text)) - Clipboard.SetText(TxtCommand.Text); - } - - private void OnOpenCommandInvoke() - { - BtnInvokeOpenCommand_Click(BtnInvokeOpenCommand, EventArgs.Empty); - } - - private async void BtnInvokeOpenCommand_Click(object sender, EventArgs e) - { - if (!BtnInvokeOpenCommand.Enabled) return; - if (TxtCommand.Text.Length < 2) - { - ShowTip(Resources.CommandContentCannotBeEmpty, TxtCommand); - return; - } - await RunCommands(TxtCommand.Text); - } - - 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.Substring(1); - 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 - 命令 - - - #region - 通用 - - - private async Task ButtonComplete(Button btn) - { - var t = btn.Text; - btn.Text = "√"; - btn.Enabled = false; - await Task.Delay(300); - btn.Text = t; - btn.Enabled = true; - } - - private void FormMain_KeyDown(object sender, KeyEventArgs e) - { - if (e.KeyCode == Keys.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 - 通用 - - - #region - 命令记录 - - - 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; - } - - 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 - 命令记录 - - - #region - 远程 - - - private OpenCommandAPI OC; - - private void InitOpenCommand() - { - NUDRemotePlayerId.Value = Settings.Default.RemoteUid; - TxtHost.Text = Settings.Default.Host; - if (!string.IsNullOrEmpty(Settings.Default.Host) && !string.IsNullOrEmpty(Settings.Default.TokenCache)) - { - OC = new OpenCommandAPI(Settings.Default.Host, Settings.Default.TokenCache); - TxtToken.Text = Settings.Default.TokenCache; - Task.Run(async () => - { - await Task.Delay(1000); - BeginInvoke(new Action(() => ShowTip(Resources.TokenRestoredFromCache, BtnInvokeOpenCommand))); - }); - } - else - { - // 自动尝试查询本地服务端地址,降低门槛 - Task.Run(async () => - { - await Task.Delay(5000); - var localhosts = new string[] { - "http://127.0.0.1:443", - "https://127.0.0.1", - "http://127.0.0.1", - "https://127.0.0.1:80", - "http://127.0.0.1:8080", - "https://127.0.0.1:8080", - }; - foreach (var host in localhosts) - { - try - { - await UpdateServerStatus(host); - // 自动填写本地服务端地址 - TxtHost.Text = host; - break; - } - catch (Exception) - { - // Ignore - } - } - }); - } - } - - private void SaveOpenCommand() - { - Settings.Default.RemoteUid = NUDRemotePlayerId.Value; - Settings.Default.Host = TxtHost.Text; - Settings.Default.TokenCache = OC?.Token; - } - - private async Task UpdateServerStatus(string host) - { - var status = await DispatchServerAPI.QueryServerStatus(host); - LblServerVersion.Text = status.Version; - if (status.MaxPlayer >= 0) - LblPlayerCount.Text = $"{status.PlayerCount}/{status.MaxPlayer}"; - else - LblPlayerCount.Text = status.PlayerCount.ToString(); - } - - private async void BtnQueryServerStatus_Click(object sender, EventArgs e) - { - var btn = sender as Button; - btn.Enabled = false; - btn.Cursor = Cursors.WaitCursor; - try - { - try - { - await UpdateServerStatus(TxtHost.Text); - } - catch (Exception ex) - { - MessageBox.Show(Resources.QueryServerStatusFailed + ex.Message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - - OC = new OpenCommandAPI(TxtHost.Text); - if (await OC.Ping()) - { - LblOpenCommandSupport.Text = "√"; - LblOpenCommandSupport.ForeColor = Color.Green; - GrpRemoteCommand.Enabled = true; - } - else - { - LblOpenCommandSupport.Text = "×"; - LblOpenCommandSupport.ForeColor = Color.Red; - GrpRemoteCommand.Enabled = false; - } - } - catch (Exception ex) - { - MessageBox.Show(ex.Message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - btn.Cursor = Cursors.Default; - btn.Enabled = true; - } - } - - private async void BtnSendVerificationCode_Click(object sender, EventArgs e) - { - var btn = sender as Button; - var t = btn.Text; - btn.Enabled = false; - NUDRemotePlayerId.Enabled = false; - try - { - btn.Text = Resources.CodeSending; - await OC.SendCode((int)NUDRemotePlayerId.Value); - BtnConnectOpenCommand.Enabled = true; - NUDVerificationCode.Enabled = true; - NUDVerificationCode.Focus(); - for (int i = 60; i > 0 && !OC.CanInvoke; i--) - { - btn.Text = string.Format(Resources.CodeResendTip, i); - await Task.Delay(1000); - } - } - catch (Exception ex) - { - MessageBox.Show(ex.Message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - btn.Text = t; - btn.Enabled = true; - NUDRemotePlayerId.Enabled = true; - } - } - - private async void BtnConnectOpenCommand_Click(object sender, EventArgs e) - { - var btn = sender as Button; - btn.Enabled = false; - try - { - await OC.Verify((int)NUDVerificationCode.Value); - GrpRemoteCommand.Enabled = false; - BtnInvokeOpenCommand.Focus(); - ShowTip(Resources.ConnectedTip, BtnInvokeOpenCommand); - ButtonOpenGOODImport.Enabled = true; - } - catch (Exception ex) - { - MessageBox.Show(ex.Message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - btn.Cursor = Cursors.Default; - btn.Enabled = true; - } - } - - private void BtnConsoleConnect_Click(object sender, EventArgs e) - { - if (string.IsNullOrEmpty(TxtToken.Text)) - { - MessageBox.Show(Resources.TokenCannotBeEmpty, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - OC.Token = TxtToken.Text; - BtnConnectOpenCommand_Click(sender, e); - } - - private void LnkOpenCommandLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - OpenURL("https://github.com/jie65535/gc-opencommand-plugin"); - } - - private void LnkRCHelp_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - MessageBox.Show(Resources.OpenCommandHelp, Resources.Help, MessageBoxButtons.OK, MessageBoxIcon.Information); - } - - private void LnkInventoryKamera_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - OpenURL("https://github.com/Andrewthe13th/Inventory_Kamera"); - } - - private void LnkGOODHelp_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - OpenURL("https://frzyc.github.io/genshin-optimizer/#/doc"); - } - - private void LnkLinks_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - var links = new List - { - "https://frzyc.github.io/genshin-optimizer/", - "https://genshin.aspirine.su/", - "https://genshin.mingyulab.com/", - "https://genshin-center.com/", - "https://github.com/Andrewthe13th/Inventory_Kamera", - "https://github.com/daydreaming666/Amenoma", - "https://seelie.me/", - "https://www.mona-uranai.com/", - }; - MessageBox.Show(string.Join("\n", links), "Links", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - - private void OpenURL(string url) - { - try - { - System.Diagnostics.Process.Start(url); - } - catch (Exception) - { - MessageBox.Show(Resources.BrowserOpenFailedTip + "\n " + url, - Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - } - - #endregion - 远程 - - - #region - 任务 - + #region - 任务 Quests - + /// + /// 初始化任务列表 + /// private void InitQuestList() { QuestFilterChanged(null, EventArgs.Empty); } + /// + /// 任务列表过滤器文本改变时触发 + /// private void QuestFilterChanged(object sender, EventArgs e) { ListQuest.BeginUpdate(); @@ -1620,6 +2071,9 @@ namespace GrasscutterTools.Forms ListQuest.EndUpdate(); } + /// + /// 任务相关按钮点击时触发(Tag带子命令) + /// private void QuestButsClicked(object sender, EventArgs e) { if (ListQuest.SelectedIndex == -1) @@ -1629,7 +2083,7 @@ namespace GrasscutterTools.Forms SetCommand("/quest", $"{(sender as Button).Tag} {id}"); } - #endregion - 任务 - + #endregion - 任务 Quests - } } diff --git a/Source/GrasscutterTools/Forms/FormMain.en-us.resx b/Source/GrasscutterTools/Forms/FormMain.en-us.resx index 629ce5b..8a1d5d6 100644 --- a/Source/GrasscutterTools/Forms/FormMain.en-us.resx +++ b/Source/GrasscutterTools/Forms/FormMain.en-us.resx @@ -127,14 +127,11 @@ Auto - - Command (Press and hold Ctrl to run automatically) - Run(F5) - - Remote + + Command (Press and hold Ctrl to run automatically) InventoryKamera @@ -154,9 +151,6 @@ Please be sure https:// or http:// is included with the IP address - - Server status - 13, 63 @@ -193,11 +187,8 @@ Player count - - Remote Cell - - - Player + + Server status 35, 17 @@ -217,11 +208,8 @@ Send Code - - 296, 111 - - - Console + + Player Connect @@ -229,6 +217,12 @@ Note that normal commands in the console state must specify the target (set include UID) + + Console + + + Remote Cell + 111, 36 @@ -250,20 +244,22 @@ Server IP - - About + + Remote - 110, 17 + 387, 102 - Grasscutter Tools + Grasscutter Tools + +This is a free and open source project. +If you think this is helpful to you, you can give me a free Star. +If there is a problem with the command generation, +or there is a new feature request, you can file an issue on Github. - - Manage - - - Ban + + About Unban @@ -283,8 +279,8 @@ UID - - Account + + Ban 49, 21 @@ -319,8 +315,8 @@ 127, 23 - - Permissions + + Account 262, 21 @@ -328,9 +324,15 @@ 138, 25 + + Clear + Delete + + List + Add @@ -349,8 +351,11 @@ UID - - Scene + + Permissions + + + Manage 91, 213 @@ -422,8 +427,8 @@ In the command, you can use ~ to indicate the current position, and ~100 to indi Scene control Tip: Most of the scenes have no effect and cannot be entered. - - Items + + Scene 50, 17 @@ -476,8 +481,8 @@ Tip: Most of the scenes have no effect and cannot be entered. Give item to player - - Weapons + + Items 86, 17 @@ -518,11 +523,8 @@ Tip: Most of the scenes have no effect and cannot be entered. 147, 216 - - Stats - - - Stats + + Weapons Unlock @@ -533,8 +535,8 @@ Tip: Most of the scenes have no effect and cannot be entered. Tip - - Talent Level + + Stats 283, 24 @@ -566,14 +568,17 @@ Tip: Most of the scenes have no effect and cannot be entered. 128, 23 + + Talent Level + 179, 17 Set current active Avatar data - - Avatar + + Stats Give All Char @@ -605,8 +610,8 @@ Tip: Most of the scenes have no effect and cannot be entered. Level - - Spawn + + Avatar 50, 17 @@ -623,9 +628,6 @@ Tip: Most of the scenes have no effect and cannot be entered. Records - - Class - 65, 21 @@ -638,6 +640,9 @@ Tip: Most of the scenes have no effect and cannot be entered. Monster + + Class + 81, 17 @@ -665,11 +670,8 @@ Tip: Most of the scenes have no effect and cannot be entered. 146, 216 - - Quest - - - List Filter + + Spawn 51, 21 @@ -689,6 +691,9 @@ Tip: Most of the scenes have no effect and cannot be entered. Hidden + + List Filter + Finish @@ -700,8 +705,8 @@ Tip: Most of the scenes have no effect and cannot be entered. Tip: Many quest require server-side scripting support Therefore, the quest can be added and finished, but not necessarily work. - - Artifacts + + Quest + Add @@ -760,8 +765,8 @@ Therefore, the quest can be added and finished, but not necessarily work. Stars - - Custom + + Artifacts 533, 216 @@ -787,9 +792,6 @@ Therefore, the quest can be added and finished, but not necessarily work. Tag - - List - 531, -1 @@ -799,6 +801,9 @@ Therefore, the quest can be added and finished, but not necessarily work. Restore + + List + 393, 216 @@ -820,8 +825,8 @@ Therefore, the quest can be added and finished, but not necessarily work. 267, 23 - - Home + + Custom 74, 38 @@ -841,9 +846,6 @@ Therefore, the quest can be added and finished, but not necessarily work. Banner Editor - - Settings - 109, 21 @@ -856,8 +858,10 @@ Therefore, the quest can be added and finished, but not necessarily work. Include UID - - - Inherit + + Settings + + + Home \ No newline at end of file diff --git a/Source/GrasscutterTools/Forms/FormMain.resx b/Source/GrasscutterTools/Forms/FormMain.resx index d981f9f..e28795d 100644 --- a/Source/GrasscutterTools/Forms/FormMain.resx +++ b/Source/GrasscutterTools/Forms/FormMain.resx @@ -138,14 +138,14 @@ Top - - NoControl - 45, 39 - - Bottom, Left + + 12 + + + groupBox1 366, 39 @@ -153,14 +153,17 @@ 17 - - TPArtifact + + 68, 69 + + + Top TPSpawn - - Top + + GrpTalentLevel System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -183,11 +186,8 @@ System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 2 - - - 1 + + None 133, 21 @@ -195,18 +195,21 @@ 25, 45 + + 7 + NUDAvatarLevel + + TPWeapon + 7 System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 完成任务 - ※仅给予所有角色时生效 @@ -231,9 +234,6 @@ None - - GrpSetStats - 66, 22 @@ -258,8 +258,11 @@ 5 - - 12 + + 11 + + + 407, 51 1 @@ -267,11 +270,8 @@ 1 - - TCMain - - - 44, 22 + + 1 设置当前活跃角色数据 @@ -279,6 +279,9 @@ System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + LblWeaponDescription + 5 @@ -288,9 +291,6 @@ 6 - - True - NoControl @@ -306,6 +306,9 @@ GOOD + + 0 + NoControl @@ -327,8 +330,8 @@ 135, 156 - - 99, 45 + + 116, 17 8 @@ -339,9 +342,6 @@ 6 - - 4 - NoControl @@ -369,8 +369,8 @@ LblStatPercent - - GrpBanPlayer + + 311, 98 NUDStat @@ -393,8 +393,8 @@ System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 2 + + GrpPermission 75, 23 @@ -405,11 +405,14 @@ TPSpawn + + LblAbout + GrpQuestFilters - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + BtnBan BtnUnlockStat @@ -438,6 +441,9 @@ NUDUid + + 8 + GrpPermission @@ -450,6 +456,9 @@ Top, Left, Right + + 264, 54 + 3 @@ -474,6 +483,9 @@ TxtBanReason + + BtnSaveCustomCommand + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -513,8 +525,8 @@ ButtonOpenGOODImport - - 4 + + 10 NUDGameItemAmout @@ -555,6 +567,9 @@ System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + CmbArtifactPart + 218, 161 @@ -572,9 +587,6 @@ 如果愿意请我喝一杯奶茶,那就更好了 : ) 指令生成有问题,或者有新的功能请求,都可以来Github提出 - - LblClearSubAttrCheckedList - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -584,11 +596,11 @@ GrasscutterToolsSupport - - 13 + + 4, 26 - - NoControl + + 60, 23 一键获得所有角色 @@ -602,6 +614,9 @@ GrpServerStatus + + False + 24 @@ -632,6 +647,9 @@ 602, 245 + + 215, 216 + 590, 204 @@ -644,6 +662,9 @@ 设置 + + 列出 + 3, 19 @@ -661,9 +682,6 @@ 4, 26 - - True - TxtHost @@ -694,9 +712,6 @@ LblClearSpawnLogs - - 掉落 - CmbClimateType @@ -706,11 +721,8 @@ 0 - - NoControl - - - 610, 56 + + 10 260, 24 @@ -727,8 +739,8 @@ 6, 161 - - TPRemoteCall + + 135, 54 7, 24 @@ -766,9 +778,6 @@ 238, 23 - - NoControl - $this @@ -778,19 +787,19 @@ 395, 192 - - NoControl - Bottom, Left + + GrpPermission + True TPPlayerCheck - + NoControl @@ -850,8 +859,8 @@ NUDWeaponRefinement - - 3 + + NoControl System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -865,6 +874,9 @@ System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 5 + LnkRCHelp @@ -931,9 +943,6 @@ 未发布的任务 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - 6 @@ -943,9 +952,6 @@ True - - 31, 72 - 99, 62 @@ -958,15 +964,12 @@ TPCustom - - 76, 21 + + Bottom, Left Bottom, Left - - TPConsoleCheck - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -979,6 +982,9 @@ 1 + + 92, 102 + 2 @@ -1000,6 +1006,9 @@ Fill + + 328, 41 + 4, 26 @@ -1021,6 +1030,9 @@ 2 + + 17 + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -1030,18 +1042,24 @@ 51, 21 - - Bottom, Left - NoControl TPWeapon + + 23 + 3 + + 0 + + + TPScene + 265, 45 @@ -1060,6 +1078,9 @@ LblWeaponRefinement + + ChkIncludeUID + NUDRemotePlayerId @@ -1093,9 +1114,6 @@ TxtToken - - LblPermUID - TPAvatar @@ -1105,20 +1123,17 @@ LblGameItemAmount - - Bottom, Right - TPPlayerCheck - - 11 + + NoControl TPWeapon - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Bottom, Left ListGameItems @@ -1159,15 +1174,27 @@ 92, 82 + + Fill + 9 + + 30, 17 + 0 + + System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + NoControl + + TPArtifact + True @@ -1209,6 +1236,9 @@ 标签 + + BtnPermList + Top @@ -1218,18 +1248,21 @@ 11 + + 610, 56 + 12 - - 1 - 6, 219 System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 100, 25 + 9, 188 @@ -1245,6 +1278,9 @@ CmbMainAttribution + + 0 + 2 @@ -1254,9 +1290,6 @@ 3 - - Bottom, Left - 12 @@ -1285,15 +1318,15 @@ 3 + + System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + 32, 17 87, 116 - - 生物志 - 4 @@ -1321,6 +1354,9 @@ NoControl + + 3, 19 + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -1336,9 +1372,15 @@ System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Top + 14 + + 4, 26 + 5 @@ -1360,12 +1402,6 @@ 44, 17 - - True - - - 数量 - 0 @@ -1399,6 +1435,9 @@ 80, 23 + + 1 + 玩家验证 @@ -1414,20 +1453,14 @@ TPArtifact - - 182, 23 - - - False - 解封 0 - - None + + 313, 6 163, 25 @@ -1456,8 +1489,8 @@ ListSubAttributionChecked - - 18 + + 5 Top, Bottom, Right @@ -1474,6 +1507,9 @@ GrpQuestFilters + + 224, 51 + TPAvatar @@ -1513,9 +1549,6 @@ Links - - 0 - 4 @@ -1549,6 +1582,9 @@ 普通攻击 + + GrpBanPlayer + 54, 17 @@ -1573,6 +1609,9 @@ System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 任务 + True @@ -1642,9 +1681,6 @@ 304, 139 - - Top, Right - 6 @@ -1657,11 +1693,8 @@ 0 - - Bottom, Left - - - 68, 69 + + None NoControl @@ -1684,6 +1717,9 @@ 1 + + GrpSettings + 0 @@ -1738,17 +1774,11 @@ 602, 245 - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - TPArtifact - NoControl - 31, 138 + 31, 158 NoControl @@ -1768,8 +1798,8 @@ True - - 328, 41 + + 256, 216 LblConsoleTip @@ -1783,11 +1813,11 @@ 39, 17 - - 目标UID + + 367, 206 - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 13, 62 10 @@ -1795,15 +1825,12 @@ BtnFinishQuest - - True + + 137, 216 17, 13 - - 15 - 32, 17 @@ -1819,8 +1846,8 @@ True - - NoControl + + True System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -1831,16 +1858,12 @@ GrpQuestFilters - - True + + Top, Right Top, Bottom, Left - - 给玩家指定物品 -说明:可选择直接给到背包或者掉落到世界 - False @@ -1850,14 +1873,17 @@ 358, 5 + + 50, 23 + 远程 32, 17 - - 6, 216 + + TPRemoteCall ListSpawnLogs @@ -1881,19 +1907,22 @@ 23, 17 - 0 + 2 Right - - 256, 216 - TPRemoteCall - - Top, Bottom, Left, Right + + None + + + 634, 361 + + + 4 1 @@ -1919,8 +1948,8 @@ 6, 72 - - 5 + + 1 ListEntity @@ -1955,11 +1984,8 @@ 310, 161 - - RbEntityMonster - - - FormMain + + 0 True @@ -1979,14 +2005,14 @@ GrpGiveItemRecord - - 40, 16 + + 导出 44, 17 - - LblTpY + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 TPSpawn @@ -1998,7 +2024,7 @@ 5 - 4 + 7 188, 216 @@ -2018,6 +2044,9 @@ System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + BtnPermClear + 远程执行插件 @@ -2048,6 +2077,12 @@ Bottom, Left + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 4 + 215, 23 @@ -2066,14 +2101,17 @@ 5, 218 - + + NoControl + + NoControl 7 - - 212, 25 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Top, Bottom, Left, Right @@ -2102,9 +2140,6 @@ 17 - - LblClimateType - 6, 86 @@ -2114,8 +2149,8 @@ ChkQuestFilterTEST - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl GrpCommand @@ -2123,18 +2158,12 @@ False - - 243, 140 - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 TPArtifact - - 116, 16 - 4, 26 @@ -2150,9 +2179,6 @@ 关于 - - LblAccountUserName - 44, 17 @@ -2177,9 +2203,6 @@ NoControl - - 32, 17 - 50, 23 @@ -2222,6 +2245,9 @@ None + + GrpSettings + 32, 17 @@ -2231,6 +2257,9 @@ 311, 8 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + 346, 31 @@ -2243,9 +2272,6 @@ 3, 3, 3, 3 - - 1 - 0, 17 @@ -2258,24 +2284,12 @@ 265, 123 - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - NoControl True - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 6, 54 - 0 @@ -2285,14 +2299,11 @@ LblArtifactStars - - Bottom, Left - TPScene - - TPScene + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 6, 6 @@ -2303,18 +2314,12 @@ 15, 39 - - GrpSettings - Bottom, Left TPConsoleCheck - - 0 - GrpServerStatus @@ -2330,11 +2335,8 @@ True - - 17 - - - TPPlayerCheck + + Top 4, 26 @@ -2360,9 +2362,6 @@ 1 - - Top - 3, 3, 3, 3 @@ -2372,11 +2371,8 @@ TPArtifact - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 99, 218 + + TPArtifact 32, 17 @@ -2384,6 +2380,9 @@ --- + + 6 + 43, 36 @@ -2393,7 +2392,7 @@ NUDArtifactStars - + 1 @@ -2405,6 +2404,9 @@ System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + groupBox1 + 圣遗物 @@ -2414,9 +2416,6 @@ GrpSetStats - - True - TCMain @@ -2426,6 +2425,9 @@ System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + TPHome + 610, 275 @@ -2438,6 +2440,9 @@ NoControl + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + 120, 25 @@ -2447,6 +2452,9 @@ TPWeapon + + NoControl + 2 @@ -2459,6 +2467,9 @@ 250, 22 + + 461, 183 + 0 @@ -2468,9 +2479,6 @@ 136, 24 - - 602, 245 - True @@ -2504,20 +2512,26 @@ NoControl + + 3 + × 删除 等级 - - GrpServerStatus + + BtnUnban + + + 6 NoControl - - NoControl + + Q技能 154, 22 @@ -2582,8 +2596,8 @@ LblWeaponLevel - - BtnOpenTextMap + + 3 TPSpawn @@ -2621,17 +2635,17 @@ 8 - - 137, 216 + + TPWeapon 13 - - 11 + + True - - 4 + + 16, 23 权限 @@ -2642,6 +2656,9 @@ NoControl + + Top, Bottom, Left, Right + 14, 17 @@ -2654,8 +2671,8 @@ TPArtifact - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Token NUDTpZ @@ -2684,9 +2701,6 @@ 75, 21 - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Bottom, Left @@ -2699,15 +2713,15 @@ System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - True - 75, 23 1 + + 6, 6 + 4 @@ -2717,6 +2731,9 @@ 379, 94 + + 3, 3, 3, 3 + 4 @@ -2726,6 +2743,12 @@ TPAvatar + + 104, 11 + + + 99, 45 + NoControl @@ -2735,6 +2758,12 @@ 60, 23 + + Left + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + None @@ -2756,14 +2785,17 @@ ChkDrop + + GrpSettings + 7 - - 2 + + 142, 39 - 2 + 3 92, 71 @@ -2807,11 +2839,14 @@ LblGOODHelp + + LblPermNewCommandTip + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - NUDAvatarConstellation + + 11 60, 23 @@ -2822,12 +2857,6 @@ 4 - - 10 - - - NUDVerificationCode - X 清空 @@ -2840,11 +2869,14 @@ 14, 17 + + TPScene + 142, 99 - - TPCustom + + 6, 99 TPSpawn @@ -2855,11 +2887,8 @@ TPScene - - 3 - - - TPItem + + TPArtifact True @@ -2897,20 +2926,20 @@ 4 - - LnkTalentQ + + LblClimateType NUDBanUID - - 3 + + 0 - - 导出 + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - True + + 602, 245 × 删除 @@ -2921,9 +2950,15 @@ TPItem + + GrpSetStats + ChkQuestFilterUNRELEASED + + 9 + 3, 19 @@ -2952,7 +2987,7 @@ ImgAvatar - 3 + 6 System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -2960,9 +2995,6 @@ Microsoft YaHei UI, 13pt - - 116, 17 - LnkGithub @@ -2975,8 +3007,22 @@ 3 - - 0 + + 获取武器 + +说明:设置等级会自动设置突破等级 +>20级 突破1 +>40级 突破2 +>50级 突破3 +>60级 突破4 +>70级 突破5 +>80级 突破6 + + + 3 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 1 @@ -2999,6 +3045,9 @@ 32, 17 + + 控制台 + NoControl @@ -3008,27 +3057,36 @@ 7 + + GrpPermission + 3, 3, 3, 3 武器 - - 7 + + 265, 79 - - TPRemoteCall + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 LblConstellationTip + + Bottom, Right + 5 TPScene + + 4 + TPPlayerCheck @@ -3078,7 +3136,10 @@ 3, 3, 3, 3 - 1 + 2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 TPScene @@ -3086,8 +3147,8 @@ 4 - - TPWeapon + + 212, 25 BtnExportCustomCommands @@ -3101,11 +3162,11 @@ 1 - - 4, 26 + + [0-20] - - 1 + + NPC 2 @@ -3131,9 +3192,6 @@ TPStats - - TPItem - 4 @@ -3164,20 +3222,14 @@ 2 - - 75, 23 - - - 602, 245 + + CmbGcVersions 执行(F5) - - 50, 23 - - - GrpSettings + + True 9 @@ -3194,21 +3246,18 @@ 7 - - 生成记录本 + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 TPArtifact - - TPArtifact + + 44, 22 ChkIncludeSceneId - - 265, 79 - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -3221,6 +3270,9 @@ BtnLoadCustomCommands + + FormMain + Top, Left, Right @@ -3236,6 +3288,9 @@ 15, 16 + + 4 + 100, 23 @@ -3245,8 +3300,8 @@ Top - - 17 + + TxtGameItemFilter 118, 23 @@ -3257,8 +3312,8 @@ 65, 13 - - True + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 50, 23 @@ -3288,7 +3343,7 @@ 198, 41 - 5 + 6 True @@ -3302,26 +3357,23 @@ 0 - - LnkTalentNormalATK + + 11 True - - 2 - 44, 17 - 4 + 5 6 - - 4 + + 90, 23 System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -3329,9 +3381,6 @@ System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 73, 21 - GrpSettings @@ -3347,14 +3396,8 @@ 1 - - Q技能 - - - 296, 109 - - - 添加任务 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 8 @@ -3362,14 +3405,14 @@ TCMain - - GrpEntityType + + 4 CmbAvatar - 0 + 1 封禁管理 @@ -3380,8 +3423,11 @@ TPScene - - 4 + + 41, 80 + + + True NoControl @@ -3389,9 +3435,18 @@ ListQuest + + 0 + + + Top + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + GrpGiveItemRecord + 14 @@ -3401,8 +3456,8 @@ 2 - - 命座 + + True TxtEntityFilter @@ -3410,8 +3465,8 @@ LblArtifactSet - - GrpTalentLevel + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -3419,17 +3474,14 @@ 0 - - None - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 4, 26 - - System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + LnkTalentQ System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -3446,9 +3498,6 @@ 5 - - 5 - TPAvatar @@ -3461,6 +3510,9 @@ Bottom, Left + + 3 + 421, 216 @@ -3506,18 +3558,21 @@ 6 - - 4, 26 - 4 System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + 11 + + 11 + 4, 26 @@ -3533,11 +3588,14 @@ 4 - - 3 + + 7 - - 11 + + TPCustom + + + 38 4 @@ -3551,6 +3609,9 @@ 6, 128 + + TPArtifact + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -3626,17 +3687,23 @@ True + + 12 + Bottom, Left 1 + + 50, 23 + LnkInventoryKamera - - 1 + + True System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -3644,9 +3711,6 @@ 7 - - 7 - 346, 5 @@ -3680,20 +3744,20 @@ 精炼等级 - - NoControl - - - 等级 - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 90, 23 - - 4 + + 296, 51 + + + True + + + TCMain None @@ -3710,8 +3774,8 @@ System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 12 + + LblPermUID 438, 139 @@ -3722,8 +3786,8 @@ 查询 - - 367, 206 + + x 清空 Right @@ -3734,8 +3798,8 @@ 8 - - 4, 26 + + 9 System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -3752,6 +3816,9 @@ 2 + + NoControl + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -3764,8 +3831,8 @@ Bottom, Left - - TPSpawn + + GrpServerStatus GrpRemoteCommand @@ -3782,15 +3849,15 @@ NUDWeaponAmout - - 物品记录本 - 60, 23 32, 17 + + NoControl + GrasscutterToolsIcon @@ -3806,6 +3873,9 @@ 10 + + Top + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -3818,27 +3888,36 @@ 6 - - 6, 99 + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 142, 39 - - - LblArtifactPart + + TPArtifact - 5 + 8 9 + + NoControl + + + 11 + 5 128, 17 + + False + + + True + 19, 17 @@ -3854,6 +3933,9 @@ 3 + + 6 + NoControl @@ -3884,6 +3966,9 @@ 3 + + 13 + 10 @@ -3905,6 +3990,9 @@ NoControl + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Bottom, Left @@ -3920,8 +4008,8 @@ 10 - - BtnUnban + + LblTpY GrpRemoteCommand @@ -3974,12 +4062,12 @@ 0 - - 32, 17 - groupBox1 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Top @@ -4040,9 +4128,6 @@ 3 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - 9 @@ -4064,8 +4149,8 @@ NoControl - - 50, 23 + + NoControl 验证码 @@ -4073,9 +4158,6 @@ System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - [0-20] - TPPlayerCheck @@ -4094,8 +4176,11 @@ y - - System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NUDAvatarConstellation + + + TPArtifact 66, 22 @@ -4121,14 +4206,8 @@ System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Bottom, Right - - - GC >= 1.2.2 - - - True + + GC 2 @@ -4142,9 +4221,6 @@ 18 - - True - 15 @@ -4160,15 +4236,12 @@ TPArtifact - - NUDTpY + + 1 NoControl - - NoControl - GrpSetStats @@ -4178,12 +4251,12 @@ Bottom, Left - - 112, 161 - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 400, 23 + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -4226,12 +4299,18 @@ True + + 4 + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 1 + + 9 + 0 @@ -4241,23 +4320,26 @@ 10 - - 262, 193 + + 1 32, 17 - - TPArtifact + + True - - 3, 3, 3, 3 + + GrpEntityType 70, 23 - - Top + + 250, 21 + + + TPPlayerCheck TPQuest @@ -4274,8 +4356,8 @@ 提示 - - 147, 23 + + 2 GrpBanPlayer @@ -4283,11 +4365,14 @@ NoControl + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + 6, 105 - - TxtCommand + + Right 493, 22 @@ -4310,14 +4395,14 @@ TPQuest - - TPHome + + Bottom, Left System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 38 + + 1 5 @@ -4355,6 +4440,9 @@ 7, 17 + + 16 + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -4379,8 +4467,8 @@ NoControl - - BtnSaveCustomCommand + + LblArtifactPart TCMain @@ -4394,6 +4482,9 @@ System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + BtnOpenTextMap + 140, 23 @@ -4403,6 +4494,9 @@ 41, 51 + + NoControl + 200, 23 @@ -4412,14 +4506,14 @@ LblEntityAmount + + 137, 17 + 11 - - 215, 216 - - - 角色 + + Bottom, Left Top, Bottom, Left, Right @@ -4427,8 +4521,8 @@ True - - TPArtifact + + 目标UID 106, 23 @@ -4454,9 +4548,6 @@ System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - NoControl - None @@ -4478,6 +4569,9 @@ 14 + + 473, 22 + 60, 23 @@ -4487,11 +4581,11 @@ System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - GrpGiveItemRecord + + 2 - GrasscutterTools.Controls.TextBoxXP, GrasscutterTools, Version=1.6.2.0, Culture=neutral, PublicKeyToken=null + GrasscutterTools.Controls.TextBoxXP, GrasscutterTools, Version=1.6.3.0, Culture=neutral, PublicKeyToken=null TPAvatar @@ -4508,37 +4602,35 @@ NoControl - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 182, 23 System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 31, 72 - - 461, 183 + + 角色 LnkResetCustomCommands - - 158, 25 + + 5 + + + NoControl 3 - - 获取武器 - -说明:设置等级会自动设置突破等级 ->20级 突破1 ->40级 突破2 ->50级 突破3 ->60级 突破4 ->70级 突破5 ->80级 突破6 + + 17 + + + 3 6, 25 @@ -4552,38 +4644,26 @@ 44, 17 - - 3, 19 - - - Bottom, Left - - - GrpPermission + + True 10 - - GrpTalentLevel + + 帮助 3 - - 9 - LblTp System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - NoControl - - - 16 + + 6, 54 9 @@ -4591,17 +4671,11 @@ LblStatsDescription - - NPC - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - GrpPermission - - - 5 + + TPItem True @@ -4627,14 +4701,14 @@ 副词条 - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + TPSpawn NUDEntityAmout - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + True Microsoft YaHei UI, 9pt @@ -4666,9 +4740,15 @@ Bottom, Right + + System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + 17 + + 549, 24 + TPHome @@ -4678,17 +4758,17 @@ 2 - - 3 + + TPRemoteCall - - CmbLanguage + + 76, 21 2 - - 473, 22 + + None True @@ -4717,6 +4797,9 @@ BtnCreateAccount + + GrpSettings + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -4747,20 +4830,17 @@ True - - ChkNewCommand - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 8 - - 23 + + TPConsoleCheck - - 250, 21 + + 数量 奖池编辑器 @@ -4789,8 +4869,8 @@ 2 - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + TxtCommand 2 @@ -4801,6 +4881,9 @@ 重置 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -4810,9 +4893,6 @@ 3, 3, 3, 3 - - None - Zoom @@ -4822,17 +4902,17 @@ ChkTopMost - - 1 + + NoControl - - 11 + + 等级 - - 224, 51 + + NoControl - - ChkIncludeUID + + 4, 26 3, 3, 3, 3 @@ -4858,6 +4938,9 @@ TPItem + + 解锁 + NUDPermUID @@ -4871,13 +4954,13 @@ 1 - 540, 60 + 540, 80 2 - - Top + + GrpPermission 坐标传送 @@ -4893,20 +4976,26 @@ Microsoft YaHei UI, 9pt, style=Italic - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NUDTpY 80, 23 - - 5 + + 25, 17 + + + LblGCVersion + + + 90, 190 True - - NoControl + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 BtnConsoleConnect @@ -4914,27 +5003,27 @@ 14 - - BtnBan - 2 3, 4, 3, 4 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + True - - 0 + + 12 - - LblWeaponDescription + + NoControl 459, 203 + + TPRemoteCall + LblSceneDescription @@ -4944,8 +5033,8 @@ LblLanguage - - False + + NoControl 3 @@ -4971,6 +5060,9 @@ Top, Right + + GrpBanPlayer + Top, Bottom, Left, Right @@ -4981,22 +5073,25 @@ NoControl - 3 + 4 TPItem + + 100, 25 + 1 - - Right + + 2 TPManage - - 6 + + 18 System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -5016,14 +5111,14 @@ 4, 26 - - NoControl + + 5 - - 3 + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - TxtGameItemFilter + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 355, 216 @@ -5031,11 +5126,11 @@ None - - 363, 139 + + v1.2.3 2022/8/27 Add* - - True + + GrpSettings 5 @@ -5043,15 +5138,12 @@ CmbPerm - - 控制台 + + 命座 275, 40 - - LblServerVersion - 12 @@ -5067,8 +5159,8 @@ NoControl - - 0 + + 8 LblQuestDescription @@ -5076,17 +5168,17 @@ System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 90, 23 + + True 1 - - NoControl + + LblServerVersion - - 13, 62 + + 添加任务 238, 23 @@ -5094,20 +5186,17 @@ 6 - - GrpSettings - - - Token + + False 12, 12 - - groupBox1 + + 6, 216 - - 30, 17 + + 296, 111 System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -5115,8 +5204,8 @@ 2 - - TPScene + + 473, 51 584, 182 @@ -5124,20 +5213,23 @@ 0 + + 7, 83 + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 NoControl - - 296, 51 + + GrpTalentLevel TPManage - - 4 + + LnkTalentNormalATK True @@ -5145,17 +5237,20 @@ 44, 17 + + 99, 218 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + 6 ListScenes - - BtnDeleteAccount - - - 5 + + 物品记录本 32, 17 @@ -5169,14 +5264,14 @@ 快来将你的官服存档导入GC吧! - - False + + 262, 193 NoControl - - LblAbout + + 完成任务 50, 23 @@ -5199,6 +5294,9 @@ 283, 233 + + 生成记录本 + LblAvatar @@ -5220,17 +5318,20 @@ 6 - - groupBox1 + + 112, 161 + + + CenterScreen System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 17 + + 3 - - TPWeapon + + TPItem 407, 22 @@ -5238,8 +5339,8 @@ 44, 216 - - 0 + + 生物志 3 @@ -5250,8 +5351,8 @@ 3 - - 549, 24 + + 0 数据 @@ -5268,8 +5369,8 @@ 265, 48 - - TPArtifact + + Bottom, Right 0 @@ -5277,29 +5378,32 @@ TPHome - - 任务 + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 182, 23 - 2 + 4 - - NoControl + + 147, 23 + + + 32, 17 LblStatTip - - 3 + + 32, 17 2 - - GrpSettings + + 3 TPArtifact @@ -5310,8 +5414,8 @@ System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 634, 361 + + 60, 23 test @@ -5325,14 +5429,17 @@ GrpServerStatus + + 指定UID + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 238, 208 - - 12 + + 75, 23 System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -5340,20 +5447,17 @@ 0 - - True + + NUDVerificationCode TPConsoleCheck - - TPManage - LblSpawnDescription - - 指定UID + + Bottom, Left 13 @@ -5361,9 +5465,6 @@ 3 - - 311, 98 - 7 @@ -5376,8 +5477,8 @@ 4 - - GrpBanPlayer + + BtnDeleteAccount 9, 26 @@ -5400,8 +5501,8 @@ 5 - - Left + + LblClearSubAttrCheckedList TPScene @@ -5427,9 +5528,6 @@ System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 41, 82 - - 删除 @@ -5437,10 +5535,10 @@ System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - 6 + 7 - - CmbArtifactPart + + NoControl NoControl @@ -5448,11 +5546,14 @@ NoControl - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 2 - - 8 + + 5 + + + 158, 25 26, 28 @@ -5472,8 +5573,8 @@ TPItem - - 313, 6 + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 1 @@ -5481,20 +5582,14 @@ LblPlayerCount - + NoControl - - 7 - 82, 23 - - 讨伐对象 - - - Top + + GrpSetStats Right @@ -5511,17 +5606,14 @@ 6 - - 16, 23 - 0 True - - 9 + + RbEntityMonster System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -5538,14 +5630,17 @@ GrpSpawnRecord - - 解锁 + + NoControl 4 - - 11 + + 4 + + + 7 540, 60 @@ -5556,26 +5651,30 @@ TPCustom - - 135, 54 + + Bottom, Left True - - None + + 给玩家指定物品 +说明:可选择直接给到背包或者掉落到世界 - - 97, 21 + + 8 - - 100, 25 + + 363, 139 - - 90, 190 + + 17 - - 1 + + 602, 245 + + + 116, 16 System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -5586,8 +5685,8 @@ TPScene - - System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 3 System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -5595,23 +5694,20 @@ 1 - - Bottom, Left + + True Bottom, Left - - NoControl - 4, 26 - - 6 + + 243, 140 - - 92, 102 + + Bottom, Left System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -5628,17 +5724,20 @@ 连接 + + GrpPermission + 31, 6 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 5 - - 6, 6 + + 掉落 - - True + + 1 10 @@ -5646,8 +5745,8 @@ NoControl - - 400, 23 + + 0 132, 159 @@ -5679,8 +5778,8 @@ NoControl - - CenterScreen + + TPManage 100, 23 @@ -5694,14 +5793,17 @@ + 创建 - - Fill + + 讨伐对象 - 移除 - - 帮助 + + 15 + + + True 7 @@ -5721,14 +5823,14 @@ TPArtifact - - 8 + + 40, 16 - - 104, 11 + + NoControl - - TPRemoteCall + + 73, 21 3 @@ -5745,11 +5847,11 @@ 5 - - GrpSetStats + + CmbLanguage - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + LblAccountUserName 数量 diff --git a/Source/GrasscutterTools/Forms/FormMain.ru-ru.resx b/Source/GrasscutterTools/Forms/FormMain.ru-ru.resx index 5cd042d..303d200 100644 --- a/Source/GrasscutterTools/Forms/FormMain.ru-ru.resx +++ b/Source/GrasscutterTools/Forms/FormMain.ru-ru.resx @@ -220,9 +220,6 @@ Отправить код - - 296, 111 - консоль @@ -267,13 +264,20 @@ Справка - 355, 68 + 355, 170 Grasscutter Tools - основной перевод Юрий Дворецкий - + +Это бесплатный проект с открытым исходным кодом. +Если вы считаете, что это полезно для вас, + вы можете дать мне бесплатную звезду. +Если возникла проблема с генерацией команды или + есть запрос на новую функцию, + вы можете написать о проблеме на Github. + Спасибо:Dhar_Jinxed - + Управлять @@ -350,6 +354,9 @@ Управление правами + + 244, 54 + 240, 21 @@ -359,6 +366,15 @@ 42, 23 + + 463, 51 + + + 70, 23 + + + очистить + 463, 22 @@ -368,6 +384,15 @@ Удалить + + 387, 51 + + + 70, 23 + + + Список + 387, 22 @@ -977,10 +1002,6 @@ Включить UID - - - Inherit - GrasscutterTools - перевод Юрий Дворецкий diff --git a/Source/GrasscutterTools/Forms/FormMain.zh-TW.resx b/Source/GrasscutterTools/Forms/FormMain.zh-TW.resx index 56fb0da..d6ff298 100644 --- a/Source/GrasscutterTools/Forms/FormMain.zh-TW.resx +++ b/Source/GrasscutterTools/Forms/FormMain.zh-TW.resx @@ -123,14 +123,11 @@ 自動 - - 命令(按住 Ctrl 自動執行) - 執行(F5) - - 遠程 + + 命令(按住 Ctrl 自動執行) 存檔掃描開源工具 @@ -148,9 +145,6 @@ 請確保地址中包含 http:// 或 https:// - - 伺服器狀態 - 遠程執行插件 @@ -160,11 +154,8 @@ 當前玩家數 - - 遠程執行 - - - 玩家驗證 + + 伺服器狀態 幫助 @@ -178,8 +169,8 @@ 發送驗證碼 - - 296, 111 + + 玩家驗證 連接 @@ -188,14 +179,17 @@ 請注意,控制台狀態下普通命令必須指定目標 (即設置包含UID) + + 遠程執行 + 查詢 伺服器地址 - - 關於 + + 遠程 割草機工具箱 @@ -205,15 +199,15 @@ 如果願意請我喝一杯奶茶,那就更好了 : ) 指令生成有問題,或者有新的功能請求,都可以來Github提出 + + 關於 + 封號 目標UID - - 賬號管理 - - 刪除 @@ -223,8 +217,8 @@ 用戶名 - - 權限管理 + + 賬號管理 權限 @@ -232,8 +226,8 @@ 目標UID - - 場景 + + 權限管理 含場景ID @@ -254,6 +248,9 @@ 提示:大部分場景沒有作用,無法進入。 + + 場景 + √ 記錄 @@ -293,27 +290,27 @@ 等級 - - 數據 - - - 角色屬性 - 解鎖 鎖定 - - 技能等級 + + 角色屬性 普通攻擊 + + 技能等級 + 設置當前活躍角色數據 + + 數據 + 一鍵獲得所有角色 @@ -329,15 +326,15 @@ 生成記錄本 - - 列表分類 - 生物誌 討伐對象 + + 列表分類 + 在玩家附近召喚生物 @@ -347,12 +344,6 @@ 等級 - - 任務 - - - 列表過濾 - 測試任務 @@ -362,6 +353,9 @@ 隱藏的任務 + + 列表過濾 + 完成任務 @@ -373,8 +367,8 @@ 提示:許多任務需要服務端腳本支持 囙此任務可以接,可以完成,但是不一定可以做 - - 聖遺物 + + 任務 套裝 @@ -391,8 +385,8 @@ 星級 - - 自定義 + + 聖遺物 導出 @@ -406,8 +400,8 @@ × 刪除 - - 主頁 + + 自定義 文本瀏覽器 @@ -418,8 +412,7 @@ 置頂 - - - Inherit + + 主頁 \ No newline at end of file diff --git a/Source/GrasscutterTools/Game/CommandVersion.cs b/Source/GrasscutterTools/Game/CommandVersion.cs new file mode 100644 index 0000000..a49414e --- /dev/null +++ b/Source/GrasscutterTools/Game/CommandVersion.cs @@ -0,0 +1,112 @@ +/** + * 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; + +namespace GrasscutterTools.Game +{ + /// + /// 命令版本 + /// + /// 用法: + /// ver = Version.TryParse(input, out Version current) ? new CommandVersion(current) : CommandVersion.Latest(); + /// + /// + internal class CommandVersion + { + /// + /// 初始化当前版本 + /// + /// + public CommandVersion(Version current) + { + this.current = current ?? throw new ArgumentNullException(nameof(current)); + } + + private Version current; + + /// + /// 当前命令版本 + /// + public Version Current + { + get => current; + set + { + if (current != value) + { + current = value; + OnVersionChanged(); + } + } + } + + /// + /// 选中版本改变事件 + /// + public event EventHandler VersionChanged; + + /// + /// 触发版本更改事件 + /// + private void OnVersionChanged() => VersionChanged?.Invoke(this, EventArgs.Empty); + + /// + /// 当前支持的最新版本 - 当未选择版本时,默认为最新版本 + /// + public static CommandVersion Latest() => new CommandVersion(List[List.Length - 1]); + + + #region - 版本列表 Version List - + + // 忽略更早以前的版本 + /// + /// v1.2.1 2022/6/18 + /// git 30c7bb94439a123417a6a1e0116acd3c40f2d115 + /// + public static readonly Version V1_2_1 = new Version(1, 2, 1); + + /// + /// v1.2.1 -> v1.2.2 2022/6/22 + /// git aa43943025fefcda9739c9fcf242e67f1a7b83b4 + /// + public static readonly Version V1_2_2 = new Version(1, 2, 2); + + /// + /// v1.2.2 -> v1.2.3 2022/7/21 + /// git a07b3f21e6fbeb9abfad8862d6fa0dc4a1c3c1a3 + /// + public static readonly Version V1_2_3 = new Version(1, 2, 3); + + // More... + /// + /// v1.2.3 -> v1.2.4 2022/7/21 + /// git hash + /// + //public static readonly Version V1_2_4 = new Version(1, 2, 4); + + public static Version[] List { get; } = new Version[] { + V1_2_1, + V1_2_2, + V1_2_3, + //V1_2_4, + }; + + #endregion - 版本列表 Version List - + } +} diff --git a/Source/GrasscutterTools/GrasscutterTools.csproj b/Source/GrasscutterTools/GrasscutterTools.csproj index f464631..d80e97f 100644 --- a/Source/GrasscutterTools/GrasscutterTools.csproj +++ b/Source/GrasscutterTools/GrasscutterTools.csproj @@ -81,6 +81,7 @@ FormTextMapBrowser.cs + @@ -103,6 +104,7 @@ True True + diff --git a/Source/GrasscutterTools/MultiLanguage.cs b/Source/GrasscutterTools/MultiLanguage.cs index 6bd766d..49ca45e 100644 --- a/Source/GrasscutterTools/MultiLanguage.cs +++ b/Source/GrasscutterTools/MultiLanguage.cs @@ -23,14 +23,20 @@ namespace GrasscutterTools { internal static class MultiLanguage { - public static string DefaultLanguage = "zh-CN"; + /// + /// 语言名称列表 + /// + public static readonly string[] LanguageNames = new string[] { "简体中文", "繁體中文", "English", "Русский" }; + + /// + /// 语言代码列表 + /// + public static readonly string[] Languages = new string[] { "zh-CN", "zh-TW", "en-US", "ru-RU" }; public static void SetDefaultLanguage(string lang) { System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(lang); - DefaultLanguage = lang; Properties.Settings.Default.DefaultLanguage = lang; - Properties.Settings.Default.Save(); } /// diff --git a/Source/GrasscutterTools/Program.cs b/Source/GrasscutterTools/Program.cs index e41ddc0..f6365a9 100644 --- a/Source/GrasscutterTools/Program.cs +++ b/Source/GrasscutterTools/Program.cs @@ -72,6 +72,10 @@ namespace GrasscutterTools //处理非UI线程异常 AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; + // 初始化语言环境 + if (!string.IsNullOrEmpty(Settings.Default.DefaultLanguage)) + MultiLanguage.SetDefaultLanguage(Settings.Default.DefaultLanguage); + Application.Run(new Forms.FormMain()); } diff --git a/Source/GrasscutterTools/Properties/AssemblyInfo.cs b/Source/GrasscutterTools/Properties/AssemblyInfo.cs index a748930..53ae1af 100644 --- a/Source/GrasscutterTools/Properties/AssemblyInfo.cs +++ b/Source/GrasscutterTools/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 //通过使用 "*",如下所示: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.6.2")] -[assembly: AssemblyFileVersion("1.6.2")] \ No newline at end of file +[assembly: AssemblyVersion("1.6.3")] +[assembly: AssemblyFileVersion("1.6.3")] \ No newline at end of file diff --git a/Source/GrasscutterTools/Properties/Settings.Designer.cs b/Source/GrasscutterTools/Properties/Settings.Designer.cs index 811b763..b59134c 100644 --- a/Source/GrasscutterTools/Properties/Settings.Designer.cs +++ b/Source/GrasscutterTools/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace GrasscutterTools.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.2.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.3.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -49,7 +49,7 @@ namespace GrasscutterTools.Properties { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("zh-CN")] + [global::System.Configuration.DefaultSettingValueAttribute("")] public string DefaultLanguage { get { return ((string)(this["DefaultLanguage"])); @@ -133,7 +133,7 @@ namespace GrasscutterTools.Properties { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("1.2.2")] + [global::System.Configuration.DefaultSettingValueAttribute("")] public string CommandVersion { get { return ((string)(this["CommandVersion"])); diff --git a/Source/GrasscutterTools/Properties/Settings.settings b/Source/GrasscutterTools/Properties/Settings.settings index 9f128f0..9e6a92c 100644 --- a/Source/GrasscutterTools/Properties/Settings.settings +++ b/Source/GrasscutterTools/Properties/Settings.settings @@ -9,7 +9,7 @@ 10001 - zh-CN + @@ -30,7 +30,7 @@ - 1.2.2 + False diff --git a/Source/GrasscutterTools/Settings.cs b/Source/GrasscutterTools/Settings.cs new file mode 100644 index 0000000..3d9e5be --- /dev/null +++ b/Source/GrasscutterTools/Settings.cs @@ -0,0 +1,28 @@ +namespace GrasscutterTools.Properties { + + + // 通过此类可以处理设置类的特定事件: + // 在更改某个设置的值之前将引发 SettingChanging 事件。 + // 在更改某个设置的值之后将引发 PropertyChanged 事件。 + // 在加载设置值之后将引发 SettingsLoaded 事件。 + // 在保存设置值之前将引发 SettingsSaving 事件。 + internal sealed partial class Settings { + + public Settings() { + // // 若要为保存和更改设置添加事件处理程序,请取消注释下列行: + // + // this.SettingChanging += this.SettingChangingEventHandler; + // + // this.SettingsSaving += this.SettingsSavingEventHandler; + // + } + + private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) { + // 在此处添加用于处理 SettingChangingEvent 事件的代码。 + } + + private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) { + // 在此处添加用于处理 SettingsSaving 事件的代码。 + } + } +}