140 lines
5.1 KiB
C#
140 lines
5.1 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using AibisDream.Framework;
|
|
using AibisDream.Kit;
|
|
using AibisDream.UI;
|
|
using Newtonsoft.Json.Linq;
|
|
using UnityEngine;
|
|
|
|
namespace AibisDream.SaveSystem
|
|
{
|
|
/// <summary>
|
|
/// 存读档流程编排层:连接 UI、<see cref="SnapshotService"/> 与槽位系统。
|
|
/// <para>
|
|
/// 对外入口:<see cref="TryAutoSave"/>(节点进入事件触发)、
|
|
/// <see cref="CreateManualSlot"/>(手动存档)、
|
|
/// <see cref="RestoreFromSlot"/>(读档)、
|
|
/// <see cref="RestoreFromFile"/>(旧档/调试)。
|
|
/// </para>
|
|
/// </summary>
|
|
public static class SaveRestoreOrchestrator
|
|
{
|
|
/// <summary>是否正在读档还原中;为 true 时禁止自动存档覆盖 slot_0。</summary>
|
|
public static bool IsRestoring { get; private set; }
|
|
|
|
/// <summary>捕获快照并写入自动档(slot 0);含保存 Loading UI。</summary>
|
|
public static void TryAutoSave()
|
|
{
|
|
var host = YarnVariableStorage.Instance;
|
|
if (host == null)
|
|
{
|
|
Debug.LogError("[SaveRestoreOrchestrator] YarnVariableStorage 未初始化");
|
|
return;
|
|
}
|
|
|
|
if (!SavePointEvaluator.CanAutoSave(out var reason))
|
|
{
|
|
Debug.LogWarning($"[SaveRestoreOrchestrator] 当前不是可存点,跳过自动存档:{reason}");
|
|
return;
|
|
}
|
|
|
|
ActionKit.Sequence()
|
|
.Callback(() => UIManager.Instance.GetPanel<InfoPanel>().ShowSaveLoading())
|
|
.Delay(1f)
|
|
.Callback(() => UIManager.Instance.GetPanel<InfoPanel>().HideSaveLoading())
|
|
.Start(host);
|
|
|
|
using (new CodeTimer("SaveSnapshot"))
|
|
{
|
|
var snapshot = SnapshotService.Capture();
|
|
var thumbnail = SlotThumbnailCapture.CapturePng();
|
|
SlotManager.SaveToAutoSlot(snapshot, thumbnail);
|
|
}
|
|
}
|
|
|
|
/// <summary>将当前自动档复制到指定手动档。</summary>
|
|
public static void CreateManualSlot(int slotIndex)
|
|
{
|
|
if (!SavePointEvaluator.CanManualSave(out var reason))
|
|
{
|
|
Debug.LogWarning($"[SaveRestoreOrchestrator] 当前不可手动存档:{reason}");
|
|
return;
|
|
}
|
|
|
|
SlotManager.CopyAutoToManual(slotIndex);
|
|
}
|
|
|
|
/// <summary>从指定槽位读档并还原。</summary>
|
|
public static IEnumerator RestoreFromSlot(int slotIndex)
|
|
{
|
|
IsRestoring = true;
|
|
try
|
|
{
|
|
var snapshot = SlotManager.LoadSnapshot(slotIndex);
|
|
if (snapshot == null)
|
|
{
|
|
Debug.LogError($"[SaveRestoreOrchestrator] 槽位 {slotIndex} 不存在或读取失败");
|
|
yield break;
|
|
}
|
|
|
|
yield return RestoreSnapshot(snapshot);
|
|
}
|
|
finally
|
|
{
|
|
IsRestoring = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>从文件读档并还原;自动区分新快照格式与 legacy 格式。</summary>
|
|
public static IEnumerator RestoreFromFile(string savePath)
|
|
{
|
|
IsRestoring = true;
|
|
try
|
|
{
|
|
if (SnapshotPersistence.IsLegacyFormat(savePath))
|
|
{
|
|
Debug.LogWarning("[SaveRestoreOrchestrator] 检测到旧格式存档,请使用新快照格式重新保存。");
|
|
yield return RestoreLegacy(savePath);
|
|
yield break;
|
|
}
|
|
|
|
SaveSnapshot snapshot;
|
|
using (new CodeTimer("LoadSnapshot"))
|
|
{
|
|
snapshot = SnapshotPersistence.Load(savePath);
|
|
}
|
|
|
|
yield return RestoreSnapshot(snapshot);
|
|
}
|
|
finally
|
|
{
|
|
IsRestoring = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>旧档:Yarn 变量 + DeepRepairDataRegistry systemData。</summary>
|
|
private static IEnumerator RestoreLegacy(string savePath)
|
|
{
|
|
var saveData = SnapshotPersistence.ReadLegacySaveRoot(savePath);
|
|
var floatDict = saveData["floatDict"]?.ToObject<Dictionary<string, float>>();
|
|
var stringDict = saveData["stringDict"]?.ToObject<Dictionary<string, string>>();
|
|
var boolDict = saveData["boolDict"]?.ToObject<Dictionary<string, bool>>();
|
|
YarnVariableStorage.Instance.SetAllVariables(floatDict, stringDict, boolDict);
|
|
|
|
if (saveData["systemData"] is JObject systemDataJson)
|
|
{
|
|
yield return DeepRepairDataRegistry.LoadByJson(systemDataJson);
|
|
}
|
|
|
|
// 旧档还原后自动固化为新格式,方便后续使用槽位系统
|
|
var snapshot = SnapshotService.Capture();
|
|
SlotManager.SaveToAutoSlot(snapshot, null);
|
|
}
|
|
|
|
private static IEnumerator RestoreSnapshot(SaveSnapshot snapshot)
|
|
{
|
|
yield return SnapshotService.Restore(snapshot);
|
|
}
|
|
}
|
|
}
|