test(dev-save): 支持从测试归档恢复阶段存档

This commit is contained in:
2026-07-15 19:27:53 +08:00
parent c38c2f75be
commit 161fe6ac7d
3 changed files with 84 additions and 10 deletions
@@ -288,7 +288,8 @@ namespace AibisDream.EditorTools
section.entries = HuoshanCheckpoints.Select(checkpoint => new CatalogEntryDto
{
label = checkpoint.Label,
path = $"{HuoshanSectionId}/{checkpoint.FolderName}"
path = $"{HuoshanSectionId}/{checkpoint.FolderName}",
anchorNode = checkpoint.NodeName
}).ToList();
}
@@ -370,6 +371,7 @@ namespace AibisDream.EditorTools
{
public string label;
public string path;
public string anchorNode;
}
}
}
+65 -1
View File
@@ -131,7 +131,7 @@ namespace AibisDream
{
GUI.Label(
new Rect(0f, y, MenuWidth - 32f, RowHeight),
"(empty — promote saves first)",
"(empty — run Test Mode or promote saves)",
statusStyle);
y += RowHeight;
}
@@ -442,6 +442,11 @@ namespace AibisDream
if (explicitEntries != null && explicitEntries.Count > 0 && root != null)
{
var latestTestArchives = BuildLatestTestArchiveIndex(
expectedSceneName,
expectedYarnProjectId,
allowedNodes);
foreach (var entryDto in explicitEntries)
{
if (string.IsNullOrWhiteSpace(entryDto.path))
@@ -462,6 +467,26 @@ namespace AibisDream
allowedNodes);
if (!entry.TryLoadSnapshot(out _, out var error))
{
if (error == "file missing"
&& !string.IsNullOrWhiteSpace(entryDto.anchorNode)
&& latestTestArchives.TryGetValue(entryDto.anchorNode, out var archiveSnapshot))
{
entry = new DevSaveEntry(
label: string.IsNullOrWhiteSpace(entryDto.label)
? entryDto.anchorNode
: entryDto.label,
snapshotPathWithoutExtension: archiveSnapshot,
expectedSceneName,
expectedYarnProjectId,
allowedNodes);
if (entry.TryLoadSnapshot(out _, out _))
{
entries.Add(entry);
continue;
}
}
Debug.LogWarning($"[DevSaveJumpTool] 跳过无效存档 {entryDto.path}: {error}");
continue;
}
@@ -494,6 +519,44 @@ namespace AibisDream
return new DevSaveSection(id, title, entries);
}
private static Dictionary<string, string> BuildLatestTestArchiveIndex(
string expectedSceneName,
string expectedYarnProjectId,
List<string> allowedNodes)
{
var result = new Dictionary<string, string>(StringComparer.Ordinal);
var savedAtByNode = new Dictionary<string, string>(StringComparer.Ordinal);
var archiveRoot = ConstRef.TestAutoSaveArchivePath;
if (!Directory.Exists(archiveRoot) || allowedNodes == null || allowedNodes.Count == 0)
return result;
foreach (var archiveDir in Directory.GetDirectories(archiveRoot))
{
var snapshotPath = Path.Combine(archiveDir, ConstRef.SaveSnapshotFileName);
var candidate = new DevSaveEntry(
string.Empty,
snapshotPath,
expectedSceneName,
expectedYarnProjectId,
allowedNodes);
if (!candidate.TryLoadSnapshot(out var snapshot, out _))
continue;
var nodeName = snapshot.anchor.nodeName;
var savedAt = snapshot.savedAt ?? string.Empty;
if (savedAtByNode.TryGetValue(nodeName, out var currentSavedAt)
&& string.CompareOrdinal(savedAt, currentSavedAt) <= 0)
{
continue;
}
savedAtByNode[nodeName] = savedAt;
result[nodeName] = snapshotPath;
}
return result;
}
private static string FormatFolderLabel(string folderName)
{
if (string.IsNullOrEmpty(folderName))
@@ -524,6 +587,7 @@ namespace AibisDream
{
public string label;
public string path;
public string anchorNode;
}
}
@@ -26,35 +26,43 @@
"entries": [
{
"label": "Stage1 开场",
"path": "Huoshan1/01_Stage1"
"path": "Huoshan1/01_Stage1",
"anchorNode": "开头对话"
},
{
"label": "Stage2 初检",
"path": "Huoshan1/02_Stage2"
"path": "Huoshan1/02_Stage2",
"anchorNode": "Stage2就绪"
},
{
"label": "Stage3 滤波器",
"path": "Huoshan1/03_Stage3"
"path": "Huoshan1/03_Stage3",
"anchorNode": "Stage3就绪"
},
{
"label": "Stage4 表达深入",
"path": "Huoshan1/04_Stage4"
"path": "Huoshan1/04_Stage4",
"anchorNode": "Stage4就绪"
},
{
"label": "Stage5 中场对话",
"path": "Huoshan1/05_Stage5"
"path": "Huoshan1/05_Stage5",
"anchorNode": "Stage5就绪"
},
{
"label": "Stage6 LOG 释放",
"path": "Huoshan1/06_Stage6"
"path": "Huoshan1/06_Stage6",
"anchorNode": "Stage6就绪"
},
{
"label": "Stage7 最终检查",
"path": "Huoshan1/07_Stage7"
"path": "Huoshan1/07_Stage7",
"anchorNode": "Stage7就绪"
},
{
"label": "Stage8 结束",
"path": "Huoshan1/08_Stage8"
"path": "Huoshan1/08_Stage8",
"anchorNode": "结束对话"
}
]
},