Files
Genarrative/docs/technical/PUZZLE_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-22.md
kdletters f8ea3b704f
Some checks failed
CI / verify (push) Has been cancelled
清理spacetimedb绑定生成
2026-04-26 20:41:11 +08:00

12 KiB
Raw Blame History

拼图玩法创作与运行态最小落地技术方案

日期:2026-04-22

1. 文档目的

本文件承接 PRD《AI 原生拼图玩法创作工具与玩法系统》,冻结本轮拼图玩法在当前平台内的最小完整闭环。

本轮目标不是抽象一个通用拼图编辑器,也不是额外搭建一个脱离平台的新小游戏站点,而是在现有平台壳层内新增独立 puzzle 玩法域,跑通下面这条主链:

  1. 平台创作入口选择拼图玩法
  2. Agent-first 对话收束 5 个高杠杆视觉锚点
  3. 编译结果页草稿
  4. 在结果页编辑关卡名、标签并生成候选拼图图片
  5. 发布作品进入拼图广场
  6. 玩家从广场进入第 1 关
  7. 后端初始化 3x3 / 4x4 棋盘
  8. 后端裁决交换、合并、拖动、拆分与通关
  9. 通关后根据“标签相似度 70% + 同作者 30%”推荐下一关

2. 本轮明确不做

  1. 不做异形拼块、旋转拼块、道具、体力、倒计时。
  2. 不做新的平台站点或新的全局导航系统。
  3. 不做前端本地推荐、前端本地裁决、前端本地持久化真相。
  4. 不做复杂图片模型编排;首版图片生成沿用 api-server 的占位资产生成方式,保证完整链路可跑通。
  5. 不把拼图玩法继续挂在 customWorldrpgWorld 或 RPG runtime 旧语义下。
  6. 不扩到拼图排行榜、社交评论、收藏、复盘系统。

3. 分层边界

3.1 前端

前端继续使用当前 React + TypeScript + Vite 平台壳层,只负责:

  1. 展示拼图创作中心、Agent 工作区、结果页、广场、运行时画布。
  2. 发起聊天、结果页编辑、发布、开始游戏、交换与拖动请求。
  3. 基于后端快照渲染棋盘、HUD、选中态与合并反馈。

前端禁止:

  1. 自行判断下一关推荐。
  2. 自行判断拼块是否应当合并。
  3. 自行判断合并块是否应当拆分。
  4. 自行判断通关。

3.2 Axum

server-rs/crates/api-server 负责:

  1. 对外暴露 /api/runtime/puzzle-* HTTP 接口。
  2. 鉴权、请求上下文、错误 envelope。
  3. 结果页占位图片生成与静态资产落盘。
  4. 调用 spacetime-client 读写拼图玩法真相态。

3.3 SpacetimeDB

server-rs/crates/spacetime-module 负责:

  1. 存储拼图 Agent session / message。
  2. 存储已发布拼图作品 profile。
  3. 存储拼图运行态 run snapshot。
  4. 通过 procedure 同步返回 session / works / gallery / runtime 快照。

3.4 纯领域 crate

新增 server-rs/crates/module-puzzle,承载:

  1. 5 个锚点与会话阶段的纯领域模型。
  2. 草稿编译、标签规范化、发布校验。
  3. 3x3 / 4x4 棋盘初始化。
  4. 交换、合并、拖动、拆分、通关与下一关推荐算法。

4. 共享契约

4.1 TypeScript shared contracts

packages/shared/src/contracts/ 新增:

  1. puzzleAgentSession.ts
  2. puzzleAgentDraft.ts
  3. puzzleAgentActions.ts
  4. puzzleResultPreview.ts
  5. puzzleWorkSummary.ts
  6. puzzleRuntimeSession.ts

这些文件分别承载:

  1. Agent session / message / anchor pack
  2. 结果页草稿与候选图片
  3. Agent actions 与 works/gallery mutation request
  4. 结果页 publish gate / preview
  5. owner-only works 与 gallery card
  6. runtime run / board / swap / drag / next-level contract

4.2 Rust shared contracts

server-rs/crates/shared-contracts/src/ 新增:

  1. puzzle_agent.rs
  2. puzzle_works.rs
  3. puzzle_gallery.rs
  4. puzzle_runtime.rs

Rust DTO 只承载对前端公开的 HTTP contract不直接泄露 module-puzzle 内部实现细节。

5. Spacetime 表与 procedure

本轮保持“最小闭环优先”,作品与运行时仍以结构化字段 + snapshot_json 组合持久化,不额外拆出更多高耦合表。

5.1 puzzle_agent_session

字段:

  1. session_id
  2. owner_user_id
  3. seed_text
  4. current_turn
  5. progress_percent
  6. stage
  7. anchor_pack_json
  8. draft_json
  9. last_assistant_reply
  10. published_profile_id
  11. created_at
  12. updated_at

5.2 puzzle_agent_message

字段:

  1. message_id
  2. session_id
  3. role
  4. kind
  5. text
  6. created_at

5.3 puzzle_work_profile

字段:

  1. profile_id
  2. owner_user_id
  3. source_session_id
  4. author_display_name
  5. level_name
  6. summary_text
  7. theme_tags_json
  8. cover_image_src
  9. cover_asset_id
  10. anchor_pack_json
  11. publication_status
  12. play_count
  13. updated_at
  14. published_at

5.4 puzzle_runtime_run

字段:

  1. run_id
  2. owner_user_id
  3. entry_profile_id
  4. current_profile_id
  5. cleared_level_count
  6. current_level_index
  7. current_grid_size
  8. played_profile_ids_json
  9. previous_level_tags_json
  10. snapshot_json
  11. updated_at
  12. created_at

5.5 Procedure

本轮全部使用 procedure 同步返回快照,避免 Axum 再次读 private table

  1. create_puzzle_agent_session
  2. get_puzzle_agent_session
  3. submit_puzzle_agent_message
  4. compile_puzzle_agent_draft
  5. save_puzzle_generated_images
  6. select_puzzle_cover_image
  7. publish_puzzle_work
  8. list_puzzle_works
  9. get_puzzle_work_detail
  10. update_puzzle_work
  11. list_puzzle_gallery
  12. get_puzzle_gallery_detail
  13. start_puzzle_run
  14. get_puzzle_run
  15. swap_puzzle_pieces
  16. drag_puzzle_piece_or_group
  17. advance_puzzle_next_level

6. 结果页图片生成策略

本轮后续已经接入 api-server 统一资产链路:拼图候选图由 api-server 调用图像服务生成,再以 OSS 对象作为持久化真值SpacetimeDB 只保存候选图 URL、assetId 与 prompt snapshot。

  1. 每次生成 2 张候选图。
  2. 候选图通过 api-server 写入 OSS兼容展示路径统一为 /generated-puzzle-assets/...,禁止再落到仓库 public/ 目录。
  3. Axum 把候选图 URL、assetId、prompt snapshot 回写到 Spacetime session draft。
  4. 创作者在结果页选择其中 1 张作为正式图。

这样可以保证:

  1. 结果页图片生成、重生、应用正式图完整可用。
  2. 发布链有正式图片可校验。
  3. 不再依赖本地 public/ 占位目录,避免开发工作区混入运行时生成文件。

6.1 发布前编辑真相补充

结果页允许创作者在发布前直接编辑:

  1. 关卡名
  2. 摘要
  3. 题材标签

这 3 个字段不能只停留在前端临时态。

本轮冻结为:

  1. publish_puzzle_work 允许直接携带 levelName / summary / themeTags
  2. spacetime-module 在发布事务内先把这些字段覆盖回 session draft 真相
  3. 覆盖后的 draft 再参与发布校验与 profile 持久化

这样可以避免额外新增一条“草稿轻量编辑 procedure”同时确保结果页编辑内容会真实进入广场作品与后续运行时 HUD。

7. 运行态规则冻结

7.1 难度推进

function resolvePuzzleGridSize(clearedLevelCount: number): 3 | 4 {
  return clearedLevelCount >= 3 ? 4 : 3;
}

7.2 棋盘初始化

  1. 根据正式图片与网格规格生成 pieceId -> correctRow/correctCol
  2. 随机打乱到非完成态。
  3. 生成初始 mergedGroups = [],再执行一次正确连接检查。

7.3 正确连接

若两个拼块在当前棋盘中四向相邻,且它们在原图上的正确位置也以同方向相邻,则视为正确连接。

所有正确连接链通过并查集合并为 mergedGroup

7.4 拖动与拆分

  1. 单块拖到单块位置:执行交换。
  2. 合并块拖到任意目标锚点:保持内部相对布局整体重排。
  3. 单块拖到合并块占据位置:先拆分目标合并块,再执行交换,最后重算合并。

7.5 通关

当所有拼块回到正确位置,或全盘只剩一个覆盖全部拼块的合并组时,标记当前关卡 cleared

7.6 下一关推荐

固定公式:

finalScore = tagSimilarityScore * 0.7 + sameAuthorScore * 0.3;

标签相似度首版使用规范化标签集合的 Jaccard。

同分裁决顺序:

  1. tagSimilarityScore 更高
  2. 当前 run 未出现过
  3. play_count 更低
  4. updated_at 更近

8. 前端接入

8.1 平台入口

只改现有平台壳层:

  1. 在创作类型弹层新增“拼图玩法”。
  2. 新增拼图专属 stage不改 RPG runtime 主链。

8.2 组件目录

新增:

  1. src/components/puzzle-agent/
  2. src/components/puzzle-result/
  3. src/components/puzzle-gallery/
  4. src/components/puzzle-runtime/

8.3 服务目录

新增:

  1. src/services/puzzle-agent/
  2. src/services/puzzle-works/
  3. src/services/puzzle-gallery/
  4. src/services/puzzle-runtime/

本轮全部走 HTTP facade不引入新的前端 Spacetime 直连。

8.4 当前前端最小落地补充

当前实现固定走下面这条最小链路:

  1. PlatformEntryCreationTypeModal 选择 puzzle
  2. PuzzleAgentWorkspace 收束锚点并触发 compile_puzzle_draft
  3. PuzzleResultView 编辑 levelName / summary / themeTags
  4. 图片生成通过独立 PuzzleImageStudioModal 触发,不在结果页内联堆叠
  5. 发布后跳转 PuzzleGalleryDetailView
  6. 从详情进入 PuzzleRuntimeShell

创作中心作品展示冻结为:

  1. 拼图作品也是平台作品,和其他创作作品共用同一套列表项样式。
  2. 创作中心不再保留独立“拼图玩法作品模块”。
  3. 拼图作品仅通过 拼图 标签与题材标签区分,不额外拆出第二块作品区。
  4. 创作中心仍保留统一“新建作品”入口,由创建类型弹层继续分流到 RPG / 拼图玩法。

运行时前端表现冻结为:

  1. 使用正式封面图按 correctRow / correctCol 做真实网格切片渲染
  2. 点击两块时仅前端维护轻量选中态,真正交换以后端返回快照为准
  3. 拖动统一采用 pointer 事件,兼顾网页端与移动端
  4. 不在前端计算合并、拆分、通关与下一关推荐

9. 验收与检查

完成后至少执行:

  1. npm run check:encoding
  2. npm run typecheck
  3. npm run test
  4. cargo check -p module-puzzle
  5. cargo check -p shared-contracts
  6. cargo check -p spacetime-module
  7. npm run spacetime:generate
  8. cargo check -p spacetime-client
  9. cargo check -p api-server

如果检查中发现拼图主链缺口,继续补齐;如果已经满足 PRD 主链和上述检查,不再追加额外玩法能力。

10. 2026-04-22 最终验收记录

本轮已按“最小完整闭环、禁止超出需求过度实现”完成拼图玩法主链落地,并补齐收尾检查。

10.1 已落地主链

  1. 平台创作中心可选择 puzzle 玩法入口。
  2. PuzzleAgentWorkspace 已接入 Agent-first 锚点收束与草稿编译。
  3. PuzzleResultView 已支持最小结果页编辑与独立图片生成弹层。
  4. 发布后作品可进入拼图广场与详情页。
  5. PuzzleRuntimeShell 已按正式封面图真实切片渲染 3x3 / 4x4 关卡。
  6. 交换、拖动、拆分、合并、通关、下一关推荐真相全部以后端快照为准。

10.2 本轮额外修复的验收阻塞

在最终验收阶段,补齐了与拼图主链无直接业务耦合、但会阻塞仓库整体检查的基线问题:

  1. typecheck 基线类型不兼容。
  2. AccountModal 测试 mock 字段落后于最新鉴权契约。
  3. customWorld 存档归一化中场景连接方向未收敛到强类型。
  4. 结果页生成资源在签名 URL 尚未返回时会短暂空白,已调整为先展示原路径占位,再异步替换签名读地址。

10.3 实际通过的检查

  1. npm run check:encoding
  2. npm run typecheck
  3. npm run test
  4. cargo check -p module-puzzle
  5. cargo check -p shared-contracts
  6. cargo check -p spacetime-module
  7. cargo check -p spacetime-client
  8. cargo check -p api-server

10.4 冻结说明

截至本次验收,拼图玩法已满足 PRD 要求的最小产品闭环;未继续扩展排行榜、提示、体力、异形拼块、倒计时、前端本地裁决等超出本轮需求的能力。