Files
ichni_Official/Assets/Scripts/NewStorySystem/Save/StorySaveModule.cs
2026-07-05 16:08:23 -04:00

150 lines
5.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections.Generic;
using Ichni.Menu;
using Ichni.Story;
using UnityEngine;
namespace Ichni
{
/// <summary>
/// 剧情存档模块。
/// <para>故事树状态与对话选项 <b>按章节</b> 保存(单文件、单 ES3 key。</para>
/// <para>剧情变量 <b>全局</b> 保存,可跨章节引用,契合 Yarn 变量模型。</para>
/// </summary>
public class StorySaveModule
{
private const string ChapterStoryKey = "ChapterStory";
private const string VariablesKey = "StoryVariables";
// 已加载章节的内存缓存chapterIndex -> 章节存档)
private readonly Dictionary<string, ChapterStorySave> _chapterSaves =
new Dictionary<string, ChapterStorySave>();
// 全局剧情变量float / string / bool 三类型,匹配 Yarn 契约)
public StoryVariablesSave variables = new StoryVariablesSave();
private static string GetChapterSavePath(string chapterIndex) =>
Application.persistentDataPath + "/StorySaves/" + chapterIndex + ".json";
private static string VariablesPath =>
Application.persistentDataPath + "/StorySaves/StoryVariables.json";
// ── 故事树 + 选项(按章节)────────────────────────────────────────────────
/// <summary>
/// 判断某章节是否尚无存档(首次进入)。
/// </summary>
public bool IsNewChapter(string chapterIndex) =>
!ES3.FileExists(GetChapterSavePath(chapterIndex));
/// <summary>
/// 加载指定章节的存档容器;无存档时返回一个新的空容器。加载结果会写入内存缓存。
/// </summary>
public ChapterStorySave LoadChapter(string chapterIndex)
{
string path = GetChapterSavePath(chapterIndex);
ChapterStorySave save;
if (ES3.FileExists(path) && ES3.KeyExists(ChapterStoryKey, path))
{
save = ES3.Load<ChapterStorySave>(ChapterStoryKey, path);
}
else
{
save = new ChapterStorySave { chapterIndex = chapterIndex };
}
_chapterSaves[chapterIndex] = save;
return save;
}
/// <summary>
/// 保存整章存档blocks + connectors + choices单次 ES3 写入。
/// </summary>
public void SaveChapter(ChapterStorySave save)
{
_chapterSaves[save.chapterIndex] = save;
ES3.Save(ChapterStoryKey, save, GetChapterSavePath(save.chapterIndex));
}
/// <summary>
/// 获取内存中的章节存档;若未加载则从磁盘加载。
/// </summary>
public ChapterStorySave GetChapter(string chapterIndex)
{
return _chapterSaves.TryGetValue(chapterIndex, out ChapterStorySave save)
? save
: LoadChapter(chapterIndex);
}
// ── 对话选项(按章节)──────────────────────────────────────────────────────
/// <summary>
/// 记录某章节内一次对话选项的选择结果。
/// </summary>
public void SetChoice(string chapterIndex, string choiceKey, int optionIndex)
{
GetChapter(chapterIndex).selectedChoices[choiceKey] = optionIndex;
}
/// <summary>
/// 读取某章节内已记录的对话选项选择结果。
/// </summary>
public bool TryGetChoice(string chapterIndex, string choiceKey, out int optionIndex)
{
return GetChapter(chapterIndex).selectedChoices.TryGetValue(choiceKey, out optionIndex);
}
// ── 剧情变量(全局)──────────────────────────────────────────────────────
/// <summary>
/// 从磁盘加载全局剧情变量(启动时调用)。
/// </summary>
public void LoadVariables()
{
if (ES3.FileExists(VariablesPath) && ES3.KeyExists(VariablesKey, VariablesPath))
{
variables = ES3.Load<StoryVariablesSave>(VariablesKey, VariablesPath);
}
else
{
variables = new StoryVariablesSave();
}
}
/// <summary>
/// 将全局剧情变量写入磁盘。
/// </summary>
public void SaveVariables()
{
ES3.Save(VariablesKey, variables, VariablesPath);
}
// ── 清档 ────────────────────────────────────────────────────────────────
/// <summary>
/// 清除所有章节的故事树存档与全局剧情变量。
/// </summary>
public void ClearAllStoryline()
{
if (ChapterSelectionManager.instance != null)
{
foreach (ChapterSelectionUnit chapter in ChapterSelectionManager.instance.chapters)
{
string path = GetChapterSavePath(chapter.chapterIndex);
if (ES3.FileExists(path))
ES3.DeleteFile(path);
}
}
_chapterSaves.Clear();
if (ES3.FileExists(VariablesPath))
ES3.DeleteFile(VariablesPath);
variables = new StoryVariablesSave();
Debug.Log("Cleared all story saves (chapters + global variables).");
}
}
}