Files
Genarrative/docs/technical/M4_RPG_RUNTIME_INVENTORY_SPACETIMEDB_BASELINE_2026-04-21.md
kdletters cbc27bad4a
Some checks failed
CI / verify (push) Has been cancelled
init with react+axum+spacetimedb
2026-04-26 18:06:23 +08:00

5.4 KiB
Raw Permalink Blame History

M4 RPG Runtime Inventory SpacetimeDB 基座记录2026-04-21

更新时间:2026-04-21

0. 文档目标

本文件只记录一件事:

module-inventory 从“只有 README 占位”推进到“已有首版背包领域契约、SpacetimeDB inventory_slot 真相表与 apply_inventory_mutation reducer”的真实落地结果。

本轮目标不是一次性迁完 Node 版所有背包玩法,而是先把后续 story / quest / runtime-item / npc 都能稳定复用的最小背包真相源立起来。


1. 本轮落地范围

本轮只落实下面 4 件事:

  1. 新增 server-rs/crates/module-inventory/ 真实 crate而不是继续停留在 README 占位。
  2. module-inventory 中冻结 inventory_slotapply_inventory_mutation 的首版领域类型、输入输出和字段校验 helper。
  3. server-rs/crates/spacetime-module/ 中新增 inventory_slot 表。
  4. spacetime-module 中新增 apply_inventory_mutation reducer形成最小可编译背包主链。

2. 当前冻结的数据口径

2.1 inventory_slot

当前首版字段冻结为:

  1. slot_id
  2. runtime_session_id
  3. story_session_id
  4. actor_user_id
  5. container_kind
  6. slot_key
  7. item_id
  8. category
  9. name
  10. description
  11. quantity
  12. rarity
  13. tags
  14. stackable
  15. stack_key
  16. equipment_slot_id
  17. source_kind
  18. source_reference_id
  19. created_at
  20. updated_at

当前策略:

  1. inventory_slot 采用“单槽位即单真相行”的口径,不再把背包塞回 runtime snapshot 大 JSON。
  2. Backpack / Equipment 统一进同一张表,通过 container_kind + slot_key 区分容器和装备位。
  3. 首版堆叠不再依赖 Node 版的隐式 heuristic统一冻结为 stackable + stack_key 显式口径。

2.2 apply_inventory_mutation

当前首版只支持 4 类 mutation

  1. GrantItem
  2. ConsumeItem
  3. EquipItem
  4. UnequipItem

当前策略:

  1. GrantItem 负责发放新物品,并在 Backpack 内按 stack_key 合并可堆叠物品。
  2. ConsumeItem 负责安全扣减堆叠数量,数量归零时删除槽位。
  3. EquipItem 负责把背包中的可装备物品移动到目标装备位,并自动把原装备挪回背包。
  4. UnequipItem 负责把装备位物品退回背包。

3. 当前刻意未做

本轮明确没有扩到以下范围:

  1. 还没有落 UseItem / Craft / Dismantle / Reforge 这类更高阶背包动作。
  2. quest_turn_in 奖励物品链当前已进入聚合 reducer 接线,但 npc_tradenpc_gift 仍未落专属 reducer。
  3. 当前已经补上最小同步查询切片 GET /api/runtime/sessions/:runtimeSessionId/inventory 但还没有落背包 public view也没有让前端直读 inventory_slot
  4. 还没有把 Node 版 inventoryMutationService.ts 整体迁到 Rust只先冻结首版真相表和最小规则。

也就是说,本轮只是把 module-inventory 的基座立起来,不宣称已经完成完整背包玩法迁移。


4. 关键规则冻结

4.1 非堆叠物品固定单槽位单数量

当前规则:

  1. stackable = false 的物品必须固定 quantity = 1
  2. 可装备物品固定 equipment_slot_id != None 且必须 stackable = false
  3. 后续如果要支持“同名但独立词缀装备”,继续沿用“一件装备一条 inventory_slot”。

4.2 装备切换不引入新真相副本

当前规则:

  1. 装备和卸下都只是在同一条 inventory_slot 上切换 container_kind + slot_key
  2. 遇到同装备位冲突时,原装备直接回到 Backpack,不额外创建临时副本。
  3. 这样后续做 Axum façade 或前端 view 时,可以稳定用 slot_id 追踪同一件物品。

4.3 背包真相优先,展示读模型后置

当前规则:

  1. module-inventory 只负责状态真相与 mutation 规则。
  2. 若后续需要“前端背包列表”“装备面板读模型”,优先通过 view 或 Axum façade 暴露。
  3. 不新增第二份背包真相副本,也不回退到多个 service 各自改 JSON。

5. 本轮新增的真实工程落点

5.1 新增 crate

  1. server-rs/crates/module-inventory/Cargo.toml
  2. server-rs/crates/module-inventory/src/lib.rs

5.2 workspace 与主工程聚合

  1. server-rs/Cargo.toml
    • 已把 crates/module-inventory 纳入 workspace members
  2. server-rs/crates/spacetime-module/Cargo.toml
    • 已接入 module-inventory 依赖
  3. server-rs/crates/spacetime-module/src/lib.rs
    • 已接入 module-inventory 类型
    • 已新增 inventory_slot
    • 已新增 apply_inventory_mutation

6. 验证目标

本轮应至少验证:

  1. module-inventory crate 可以独立 cargo check / cargo test
  2. spacetime-module 能成功编译并接入新表与 reducer
  3. 不会把现有中文内容写坏,编码检查继续通过

7. 下一步建议

按当前节奏,后续应继续按下面顺序推进:

  1. module-inventory 中继续补 UseItem / Craft / Dismantle / Reforge 对应的纯规则契约。
  2. 继续把 npc_trade / npc_gift / runtime-item 发物链改成显式调用 apply_inventory_mutation,并补齐 quest / treasure 之外的奖励入口。
  3. 在最小同步查询切片稳定后,再评估是否继续补 inventory view、旧前端背包读模型兼容或 public subscription。
  4. 最后再把 Node 版 inventoryMutationService.ts 的玩法细节逐步迁走。