Files
Genarrative/docs/technical/PUZZLE_FAILURE_EXTENSION_AND_SAVE_ARCHIVE_2026-05-01.md
2026-05-01 00:33:39 +08:00

4.3 KiB
Raw Blame History

拼图失败续时与存档投影设计 2026-05-01

背景

拼图运行时已经有倒计时失败态、道具确认扣费、下一关推荐和个人存档页,但失败后的玩家选择与拼图作品存档投影还没有闭环:

  1. 倒计时结束后只能返回,不能重新开始或付费继续。
  2. 进入拼图作品后,存档页没有稳定出现一条可恢复的拼图游戏存档。
  3. 每通过一关后,存档应该更新到下一关入口,而不是停留在旧关卡。

本轮只补齐拼图运行态与存档投影,不迁移旧 server-node,不新增平行存档页。

目标

  1. 限定时间内未完成时弹出失败面板。
  2. 失败面板提供两个选择:
    • 重新开始:重新开启当前拼图关卡,不扣陶泥币。
    • 继续1分钟:先弹出确认窗口,确认后消耗 1 陶泥币,并把当前失败关卡恢复为 playing,剩余时间固定为 60000ms
  3. 进入拼图作品后立即写入 profile_save_archive,存档页显示拼图存档。
  4. 每次进入下一关后更新同一条拼图存档,使存档恢复时指向最新可继续的关卡。

运行态规则

失败续时

PuzzleRuntimePropKind 增加 extendTime,沿用现有道具确认与扣费接口:

  1. 前端只在 runtimeStatus = failed 时开放 继续1分钟
  2. 点击后打开独立确认弹窗,文案只显示短标题和 消耗 1 陶泥币
  3. 正式 run 继续走 POST /api/runtime/puzzle/runs/:runId/props
  4. api-serverextendTime 映射为账单 asset_kind = puzzle_prop_extend_time
  5. SpacetimeDB 侧只允许失败关卡续时;续时成功后:
    • status = playing
    • remaining_ms = 60000
    • elapsed_ms = None
    • cleared_at_ms = None
    • 清空暂停与冻结生效点
    • 调整 paused_accumulated_ms,保证从确认成功那一刻开始完整倒计时 60

本地调试 run 没有真实钱包,沿用本地道具兜底:仍弹确认窗,但不扣真实陶泥币。

重新开始

重新开始不复用旧失败棋盘,而是重新创建当前关卡的 run

  1. 前端从当前 currentLevel.profileIdcurrentLevel.levelId 调用 startPuzzleRun
  2. 新 run 的棋盘重新打乱、倒计时重置。
  3. 如果当前关卡来自作品内部第 N 关,必须携带 levelId,避免重开误回作品第 1 关。
  4. 旧失败 run 保留为历史运行记录,不在前端继续使用。

为支持第 3 点,PuzzleRuntimeLevelSnapshot 增加 levelId: string | null

存档投影规则

复用现有 profile_save_archive 表,不新增拼图专属存档表。拼图存档固定规则:

  1. world_key = puzzle:{entry_profile_id}
  2. world_type = PUZZLE
  3. profile_id = entry_profile_id,保证同一个作品链只覆盖一条存档。
  4. world_name 使用当前关卡名。
  5. subtitle 使用 第 N 关
  6. summary_text 使用当前状态:
    • playing拼图进行中
    • failed关卡失败
    • cleared关卡已完成
  7. cover_image_src 使用当前关卡正式图。
  8. game_state_json 保存最小拼图恢复载荷:
    • runtimeKind = "puzzle"
    • runId
    • entryProfileId
    • currentProfileId
    • currentLevelIndex
    • currentLevelId
    • status

写入时机

SpacetimeDB 拼图运行态每次持久化 run 时同步刷新存档:

  1. start_puzzle_run:创建 run 后立即写入拼图存档。
  2. advance_puzzle_next_level:进入下一关后更新同一条存档。
  3. use_puzzle_runtime_prop(extendTime):续时成功后更新状态。
  4. get_puzzle_run 导致失败态落库时,也同步更新为失败存档。

排行榜提交只负责成绩与通关态,不新增存档规则;如果它把 run 状态更新为通关,也跟随 run 持久化刷新存档。

验收

  1. 倒计时归零后失败弹窗有 重新开始继续1分钟
  2. 点击 继续1分钟 后先出现扣费确认,确认成功后失败弹窗关闭并恢复 60 秒倒计时。
  3. 陶泥币余额不足时确认弹窗保留,并展示错误。
  4. 点击 重新开始 后当前关卡重新打乱并重置倒计时。
  5. 进入拼图作品后,存档页出现 worldType = PUZZLE 的拼图存档。
  6. 通过一关进入下一关后,同一条存档更新到新关卡。
  7. 定向前端测试、Rust 拼图模块测试与编码检查通过。