Skip to content

Restoration

woctordho edited this page Jan 16, 2022 · 36 revisions

存档系统

(TODO:下个大版本中存档系统可能会大改)

设计目标

  • 保存和读取各种前端组件(图片、BGM等)的状态
  • 支持在对话中设置变量,用变量控制剧情分支,在读档时恢复变量
  • 支持随时跳转到任何一条对话,并且性能足够快(特别是文本回顾界面中的对话,以及一些重要的对话,比如每一章的开头和选项)
  • 占用的硬盘空间足够小
  • 读写文件的速度足够快

存档系统的底层

  • 每个有状态的前端组件实现IRestorable,它的状态表示成IRestoreData
  • CheckpointManager.WriteSave中,每个IRestoreDataBinaryFormatter序列化成二进制流,再用DeflateStream压缩,再写到文件
    • 存档的状态一般是很稀疏的,所以需要压缩
    • 目前我们没有存档加密功能
    • TODO:BinaryFormatter已经被微软官方deprecate了,以后我们可能会换成JSON

存档系统的中层

  • 游戏(在后端剧情层面上)的状态由全局变量(CheckpointManager.globalSave.data["global_variables"])、局部变量(GameState.variables)、节点名称(GameState.currentNode.name)和对话序号(GameState.currentIndex)唯一确定
    • 游戏的状态与分支选项无关,如果两个选项从同一个节点跳转到同一个节点,它们不会造成不同的状态
  • 每条对话都有一个restore entry,保存这条对话的代码块运行之前所有前端组件的状态,记录在CheckpointManager.globalSave.savedNodes
    • 读档时,先恢复目标对话的状态,再运行目标对话的代码块
  • 为了支持持续动画(详见演出系统),并减小存档大小,restore entry分为两类:
    • Checkpoint完整记录各种前端组件的状态
    • Simple entry不记录这些状态,只记录上一个checkpoint的相距步数和变量hash
      • 读档时先读取上一个checkpoint,再快进到simple entry的位置
    • 我们避免使用full/raw/real checkpoint之类的说法

存档系统的高层

  • 存档/读档界面中的每个存档称为Bookmark,记录一条对话的变量hash、节点名称和对话序号,提供这些信息就能跳转到那条对话
  • 自动存档/快速存档与手动存档的格式是一样的

文本回顾界面

  • Log界面中的每条对话(log entry)记录那条对话的变量hash、节点名称和对话序号,提供这些信息就能跳转到那条对话
  • 为了在读档时恢复log,每个checkpoint中保存上一个checkpoint到它之前的所有log entry的状态
    • TODO:理论上log界面不需要状态,我们也不需要把剧本的内容保存到存档里,可以直接通过FlowChartTree来恢复log
Clone this wiki locally