mirror of
https://github.com/waynebian01/Shigure.git
synced 2026-09-03 07:15:24 +08:00
保存宏时同步写入该职业模块依赖快照
宏页保存原先只更新 keymap 和插件,模块快照仍停留在旧宏。改为走与配置页相同的回调,按当前职业捕获并保存模块。 Co-authored-by: Wayne-Arasaka <waynebian01@users.noreply.github.com>
This commit is contained in:
@@ -104,7 +104,7 @@ wow_process.txt 目标游戏进程名列表;构建时复制,运行期间每
|
||||
|
||||
- [UI/ClassConfigEditorControl.cs](UI/ClassConfigEditorControl.cs):左侧职业列表 + 右侧按专精切换的六页编辑器(状态/光环/冷却/队伍/技能列表/物品列表),状态字段用 `ClassStateCatalog` 驱动的 `ComboBoxColumn`。
|
||||
- [UI/ClassMacrosEditorControl.cs](UI/ClassMacrosEditorControl.cs):左侧职业列表 + 右侧三页编辑器(动态宏/静态宏/特殊宏),偏移提示显示槽位编号计算。
|
||||
- 两个编辑器均接受 `Func<string?>` 项目路径解析器 + `Func<string, Task<string?>>` 保存回调,由 `MainForm` 在构造时注入。保存流程:编辑器调 `Store.Save()` → 传入已保存文件路径 → 重新生成 config/keymap → 单文件部署游戏 → 重启运行时;部署失败返回说明,但不回滚本地文件。
|
||||
- 两个编辑器均接受 `Func<string?>` 项目路径解析器 + `Func<string, int, Task<ClassConfigPostSaveResult>>` 保存回调,由 `MainForm` 在构造时注入。保存流程:编辑器调 `Store.Save()` → 同步保存该职业模块依赖快照 → 传入已保存文件路径 → 重新生成 config/keymap → 单文件部署游戏 → 重启运行时;部署失败返回说明,但不回滚本地文件。
|
||||
- 配置更新的多个入口通过任务尾队列串行执行;运行时重启会等待该队列稳定,主窗口关闭也会等待正在写盘的转换和部署完成。新增同步入口必须继续走这条队列。
|
||||
|
||||
## UI 约定
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Shigure;
|
||||
public sealed class ClassMacrosEditorControl : UserControl
|
||||
{
|
||||
private readonly Func<string?> _resolveClassMacrosPath;
|
||||
private readonly Func<string, Task<string?>> _updateConfigAsync;
|
||||
private readonly Func<string, int, Task<ClassConfigPostSaveResult>> _updateConfigAsync;
|
||||
|
||||
private readonly ListBox _classList = new();
|
||||
private readonly Label _pathLabel = new();
|
||||
@@ -43,7 +43,7 @@ public sealed class ClassMacrosEditorControl : UserControl
|
||||
|
||||
public ClassMacrosEditorControl(
|
||||
Func<string?> resolveClassMacrosPath,
|
||||
Func<string, Task<string?>> updateConfigAsync)
|
||||
Func<string, int, Task<ClassConfigPostSaveResult>> updateConfigAsync)
|
||||
{
|
||||
_resolveClassMacrosPath = resolveClassMacrosPath;
|
||||
_updateConfigAsync = updateConfigAsync;
|
||||
@@ -1020,6 +1020,12 @@ public sealed class ClassMacrosEditorControl : UserControl
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentClassId is not { } classId)
|
||||
{
|
||||
MessageBox.Show("请先选择职业。", "宏", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
var localSaved = false;
|
||||
try
|
||||
{
|
||||
@@ -1028,17 +1034,18 @@ public sealed class ClassMacrosEditorControl : UserControl
|
||||
localSaved = true;
|
||||
SetDirty(false);
|
||||
_statusLabel.Text = "本地 Lua 已保存,正在更新配置并同步游戏…";
|
||||
var syncIssue = await _updateConfigAsync(_document.FilePath);
|
||||
var updateResult = await _updateConfigAsync(_document.FilePath, classId);
|
||||
if (IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(syncIssue))
|
||||
if (!string.IsNullOrWhiteSpace(updateResult.AddonSyncIssue))
|
||||
{
|
||||
_statusLabel.Text = "本地已保存并更新配置,但游戏同步失败";
|
||||
MessageBox.Show(
|
||||
$"本地 Lua 已保存,config/keymap 已更新,但游戏插件同步未完成:\n{syncIssue}",
|
||||
$"本地 Lua、该职业的 {updateResult.SavedModuleCount} 个模块及 config/keymap 已保存,"
|
||||
+ $"但游戏插件同步未完成:\n{updateResult.AddonSyncIssue}",
|
||||
"游戏同步失败",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Warning);
|
||||
@@ -1046,13 +1053,16 @@ public sealed class ClassMacrosEditorControl : UserControl
|
||||
return;
|
||||
}
|
||||
|
||||
_statusLabel.Text = "已保存并更新配置";
|
||||
_statusLabel.Text = $"已保存宏及该职业的 {updateResult.SavedModuleCount} 个模块";
|
||||
UpdateOffsetHint();
|
||||
var warningText = updateResult.ModuleWarnings.Count == 0
|
||||
? string.Empty
|
||||
: $"\n\n有 {updateResult.ModuleWarnings.Count} 个模块未携带依赖,详情见日志。";
|
||||
MessageBox.Show(
|
||||
"请在游戏内重载界面, /reload",
|
||||
$"已一并保存该职业的 {updateResult.SavedModuleCount} 个模块。{warningText}\n\n请在游戏内重载界面, /reload",
|
||||
"保存成功",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Information);
|
||||
updateResult.ModuleWarnings.Count == 0 ? MessageBoxIcon.Information : MessageBoxIcon.Warning);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -185,7 +185,7 @@ public sealed class MainForm : Form, IMessageFilter
|
||||
_classConfigEditor.DirtyStateChanged += dirty => _statusForm.SetPageDirty(SettingsPage.Config, dirty);
|
||||
_classMacrosEditor = new ClassMacrosEditorControl(
|
||||
() => Path.Combine(_addonSyncService.SourceRoot, "core", "classmacros.lua"),
|
||||
UpdateConfigAfterSaveAsync);
|
||||
UpdateClassConfigAfterSaveAsync);
|
||||
_statusForm.AttachMacrosEditor(_classMacrosEditor);
|
||||
_classMacrosEditor.DirtyStateChanged += dirty => _statusForm.SetPageDirty(SettingsPage.Macros, dirty);
|
||||
_statusForm.FormClosing += (_, _) =>
|
||||
@@ -1497,12 +1497,6 @@ public sealed class MainForm : Form, IMessageFilter
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string?> UpdateConfigAfterSaveAsync(string savedAddonFilePath)
|
||||
{
|
||||
var result = await QueueProjectConfigUpdateAsync(savedAddonFilePath);
|
||||
return DescribeAddonSyncIssue(result.AddonSync);
|
||||
}
|
||||
|
||||
private async Task<ClassConfigPostSaveResult> UpdateClassConfigAfterSaveAsync(
|
||||
string savedAddonFilePath,
|
||||
int classId)
|
||||
@@ -1512,7 +1506,7 @@ public sealed class MainForm : Form, IMessageFilter
|
||||
if (moduleResult.Errors.Count > 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"配置已更新,但该职业有 {moduleResult.Errors.Count} 个模块保存失败;"
|
||||
$"该职业有 {moduleResult.Errors.Count} 个模块保存失败;"
|
||||
+ $"已成功保存 {moduleResult.SavedCount} 个模块。详情见日志。");
|
||||
}
|
||||
|
||||
@@ -1551,7 +1545,7 @@ public sealed class MainForm : Form, IMessageFilter
|
||||
}
|
||||
|
||||
var className = ClassNames.GetClassAndSpecName(classId, null).ClassName ?? $"职业{classId}";
|
||||
AppendLog($"保存{className}配置时已同步保存 {savedCount}/{modules.Count} 个该职业模块。");
|
||||
AppendLog($"已同步保存 {savedCount}/{modules.Count} 个{className}模块。");
|
||||
foreach (var warning in warnings)
|
||||
{
|
||||
AppendLog($"模块依赖保存提示: {warning}");
|
||||
|
||||
Reference in New Issue
Block a user