mirror of
https://github.com/waynebian01/Shigure.git
synced 2026-09-03 07:15:24 +08:00
保存配置会将当前职业的所有模块一起保存, 覆盖掉可能冲突项
This commit is contained in:
@@ -476,9 +476,9 @@ public sealed class ModuleStore
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回写导入阶段清理过的依赖快照,并保留模块原有文件位置。
|
||||
/// 回写已更新的模块依赖快照,并保留模块原有文件位置。
|
||||
/// </summary>
|
||||
public ModuleDefinition SaveDependencyCleanup(ModuleDefinition module)
|
||||
public ModuleDefinition SaveDependenciesInPlace(ModuleDefinition module)
|
||||
{
|
||||
Normalize(module);
|
||||
lock (_gate)
|
||||
@@ -501,6 +501,8 @@ public sealed class ModuleStore
|
||||
_modules.Remove(existing);
|
||||
_modules.Add(module.Clone());
|
||||
_modules = SortModules(_modules).ToList();
|
||||
_rejectedModuleIds.Remove(module.Id);
|
||||
_importIssueModuleIds.Remove(module.Id);
|
||||
return module.Clone();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,11 @@ using System.Globalization;
|
||||
|
||||
namespace Shigure;
|
||||
|
||||
public sealed record ClassConfigPostSaveResult(
|
||||
string? AddonSyncIssue,
|
||||
int SavedModuleCount,
|
||||
IReadOnlyList<string> ModuleWarnings);
|
||||
|
||||
/// <summary>
|
||||
/// 图形化编辑 Fuyutsui class/*.lua 的 ClassBlocks(states / auras / spells / group),
|
||||
/// 并编辑同文件中的 spellsList。
|
||||
@@ -10,7 +15,7 @@ namespace Shigure;
|
||||
public sealed class ClassConfigEditorControl : UserControl
|
||||
{
|
||||
private readonly Func<string?> _resolveClassDirectory;
|
||||
private readonly Func<string, Task<string?>> _updateConfigAsync;
|
||||
private readonly Func<string, int, Task<ClassConfigPostSaveResult>> _updateConfigAsync;
|
||||
|
||||
private readonly ListBox _classList = new();
|
||||
private readonly ListBox _specList = new();
|
||||
@@ -75,7 +80,7 @@ public sealed class ClassConfigEditorControl : UserControl
|
||||
|
||||
public ClassConfigEditorControl(
|
||||
Func<string?> resolveClassDirectory,
|
||||
Func<string, Task<string?>> updateConfigAsync)
|
||||
Func<string, int, Task<ClassConfigPostSaveResult>> updateConfigAsync)
|
||||
{
|
||||
_resolveClassDirectory = resolveClassDirectory;
|
||||
_updateConfigAsync = updateConfigAsync;
|
||||
@@ -2759,29 +2764,33 @@ public sealed class ClassConfigEditorControl : UserControl
|
||||
localSaved = true;
|
||||
SetDirty(false);
|
||||
_statusLabel.Text = "本地 Lua 已保存,正在更新配置并同步游戏…";
|
||||
var syncIssue = await _updateConfigAsync(_currentDocument.FilePath);
|
||||
var updateResult = await _updateConfigAsync(_currentDocument.FilePath, _currentClassId.Value);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
_statusLabel.Text = "已保存并更新配置";
|
||||
_statusLabel.Text = $"已保存配置及该职业的 {updateResult.SavedModuleCount} 个模块";
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -123,6 +123,11 @@ public sealed class MainForm : Form, IMessageFilter
|
||||
FuyutsuiKeymapConverter.UpdateResult? Keymap,
|
||||
FuyutsuiAddonSyncResult AddonSync);
|
||||
|
||||
private sealed record ClassModuleSaveResult(
|
||||
int SavedCount,
|
||||
IReadOnlyList<string> Warnings,
|
||||
IReadOnlyList<string> Errors);
|
||||
|
||||
internal MainForm(
|
||||
AppOptions initialOptions,
|
||||
string baseDirectory,
|
||||
@@ -175,7 +180,7 @@ public sealed class MainForm : Form, IMessageFilter
|
||||
_statusForm.AttachModuleEditor(_moduleEditor);
|
||||
_classConfigEditor = new ClassConfigEditorControl(
|
||||
() => Path.Combine(_addonSyncService.SourceRoot, "class"),
|
||||
UpdateConfigAfterSaveAsync);
|
||||
UpdateClassConfigAfterSaveAsync);
|
||||
_statusForm.AttachConfigEditor(_classConfigEditor);
|
||||
_classConfigEditor.DirtyStateChanged += dirty => _statusForm.SetPageDirty(SettingsPage.Config, dirty);
|
||||
_classMacrosEditor = new ClassMacrosEditorControl(
|
||||
@@ -310,7 +315,7 @@ public sealed class MainForm : Form, IMessageFilter
|
||||
{
|
||||
try
|
||||
{
|
||||
_moduleStore.SaveDependencyCleanup(module);
|
||||
_moduleStore.SaveDependenciesInPlace(module);
|
||||
cleanedModuleCount++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -1494,6 +1499,69 @@ public sealed class MainForm : Form, IMessageFilter
|
||||
return DescribeAddonSyncIssue(result.AddonSync);
|
||||
}
|
||||
|
||||
private async Task<ClassConfigPostSaveResult> UpdateClassConfigAfterSaveAsync(
|
||||
string savedAddonFilePath,
|
||||
int classId)
|
||||
{
|
||||
var moduleResult = SaveModulesForClass(classId);
|
||||
var result = await QueueProjectConfigUpdateAsync(savedAddonFilePath);
|
||||
if (moduleResult.Errors.Count > 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"配置已更新,但该职业有 {moduleResult.Errors.Count} 个模块保存失败;"
|
||||
+ $"已成功保存 {moduleResult.SavedCount} 个模块。详情见日志。");
|
||||
}
|
||||
|
||||
return new ClassConfigPostSaveResult(
|
||||
DescribeAddonSyncIssue(result.AddonSync),
|
||||
moduleResult.SavedCount,
|
||||
moduleResult.Warnings);
|
||||
}
|
||||
|
||||
private ClassModuleSaveResult SaveModulesForClass(int classId)
|
||||
{
|
||||
var modules = _moduleStore.GetModulesForDisplay()
|
||||
.Where(module => module.Match.ClassId == classId)
|
||||
.ToList();
|
||||
var warnings = new List<string>();
|
||||
var errors = new List<string>();
|
||||
var savedCount = 0;
|
||||
|
||||
foreach (var module in modules)
|
||||
{
|
||||
try
|
||||
{
|
||||
module.Version = AppInfo.Version;
|
||||
var warning = _moduleDependencyService.Capture(module);
|
||||
_moduleStore.SaveDependenciesInPlace(module);
|
||||
savedCount++;
|
||||
if (!string.IsNullOrWhiteSpace(warning))
|
||||
{
|
||||
warnings.Add($"{module.Name}: {warning}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errors.Add($"{module.Name}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
var className = ClassNames.GetClassAndSpecName(classId, null).ClassName ?? $"职业{classId}";
|
||||
AppendLog($"保存{className}配置时已同步保存 {savedCount}/{modules.Count} 个该职业模块。");
|
||||
foreach (var warning in warnings)
|
||||
{
|
||||
AppendLog($"模块依赖保存提示: {warning}");
|
||||
}
|
||||
foreach (var error in errors)
|
||||
{
|
||||
AppendLog($"模块依赖保存失败: {error}");
|
||||
}
|
||||
|
||||
RefreshModuleSelector(_lastSnapshot, forceRefresh: true);
|
||||
RefreshDefaultModuleSelector();
|
||||
return new ClassModuleSaveResult(savedCount, warnings, errors);
|
||||
}
|
||||
|
||||
private Task<ProjectConfigUpdateResult> QueueProjectConfigUpdateAsync(string? savedAddonFilePath)
|
||||
{
|
||||
lock (_configUpdateSync)
|
||||
|
||||
Reference in New Issue
Block a user