# M4 Runtime Item Treasure SpacetimeDB 基座记录(2026-04-21) 更新时间:`2026-04-21` ## 0. 文档目标 本文件只记录一件事: **把 `module-runtime-item` 从“只有 README 占位”推进到“SpacetimeDB 侧已有 `treasure_record` 真相表、`resolve_treasure_interaction` reducer/procedure,以及可桥接 `inventory_slot` 的奖励 contract”的真实落地结果。** 本轮目标不是一次性迁完 Node 版所有 runtime item 玩法,而是先把宝藏奖励记录、奖励字段口径与后续背包接入边界固定下来。 --- ## 1. 本轮落地范围 本轮只落实下面 5 件事: 1. 新增 `server-rs/crates/module-runtime-item/` 真实 crate,而不是继续停留在 README 占位。 2. 在 `module-runtime-item` 中冻结 `TreasureResolveInput / TreasureRecordSnapshot / RuntimeItemRewardItemSnapshot` 的首版领域类型与校验 helper。 3. 在 `server-rs/crates/spacetime-module/` 中新增 `treasure_record` 表。 4. 在 `spacetime-module` 中新增 `resolve_treasure_interaction` reducer 与 `resolve_treasure_interaction_and_return` procedure。 5. 把宝藏奖励物品字段扩到可无损映射 `inventory_slot` 的粒度,并在聚合层接通宝藏奖励到背包真相表的最小发物链。 --- ## 2. 当前冻结的数据口径 ### 2.1 `treasure_record` 当前首版字段冻结为: 1. `treasure_record_id` 2. `runtime_session_id` 3. `story_session_id` 4. `actor_user_id` 5. `encounter_id` 6. `encounter_name` 7. `scene_id` 8. `scene_name` 9. `action` 10. `reward_items` 11. `reward_hp` 12. `reward_mana` 13. `reward_currency` 14. `story_hint` 15. `created_at` 16. `updated_at` 当前策略: 1. `treasure_record` 保持 private 真相表口径。 2. `Inspect / Secure / Leave` 都会留下正式记录,避免宝藏交互继续散落在 runtime snapshot 大 JSON 或 story 文本里。 3. `Leave` 允许不发物;`Inspect / Secure` 的奖励字段当前已经通过聚合层同步写入 `inventory_slot`。 4. 同一 `treasure_record_id` 重放时直接返回既有记录,不重复执行发物,保证宝藏奖励幂等。 ### 2.2 `RuntimeItemRewardItemSnapshot` 当前奖励物品字段冻结为: 1. `item_id` 2. `category` 3. `item_name` 4. `description` 5. `quantity` 6. `rarity` 7. `tags` 8. `stackable` 9. `stack_key` 10. `equipment_slot_id` 当前策略: 1. 奖励物品不再只保留 `item_id + item_name + quantity` 的轻量占位结构。 2. 当前字段已经与 `inventory_slot` 的首版真相字段对齐到可桥接程度,避免后续发物时再回头猜品类、堆叠策略和装备位。 3. `build_inventory_item_snapshot_from_reward_item(...)` 负责把宝藏奖励快照稳定映射为 `module-inventory::InventoryItemSnapshot`。 --- ## 3. 当前 reducer / procedure 口径 ### 3.1 `resolve_treasure_interaction` 当前负责: 1. 校验 `TreasureResolveInput` 2. 校验 `story_session_id / runtime_session_id / actor_user_id` 作用域一致 3. 同一 `treasure_record_id` 重放时直接返回已落库快照 4. 初次落库时写入 `treasure_record` 5. 初次落库后把 `reward_items` 同步发放到 `inventory_slot` ### 3.2 `resolve_treasure_interaction_and_return` 当前负责: 1. 复用同一套 `treasure_record` upsert 规则 2. 返回最终 `TreasureRecordSnapshot` 3. 避免 Axum facade 再额外读取 private table --- ## 4. 当前刻意未做 本轮明确没有扩到以下范围: 1. 还没有把 `reward_hp / reward_mana / reward_currency` 接到运行时资源真相表 2. 还没有把 runtime item director 的完整物品导演链迁到 Rust 3. 还没有新增 Axum 的 runtime treasure facade 4. 还没有把前端 `treasureInteractions.ts` 主链切到 `server-rs` 也就是说,本轮只是把宝藏结算真相表和奖励 contract 立起来,不宣称已经完成完整宝藏奖励迁移。 --- ## 5. 本轮新增的真实工程落点 ### 5.1 新增 crate 1. `server-rs/crates/module-runtime-item/Cargo.toml` 2. `server-rs/crates/module-runtime-item/src/lib.rs` ### 5.2 workspace 与主工程聚合 1. `server-rs/Cargo.toml` - 已把 `crates/module-runtime-item` 纳入 workspace members 2. `server-rs/crates/spacetime-module/Cargo.toml` - 已接入 `module-runtime-item` 依赖 3. `server-rs/crates/spacetime-module/src/lib.rs` - 已接入 `module-runtime-item` 类型 - 已新增 `treasure_record` - 已新增 `resolve_treasure_interaction` - 已新增 `resolve_treasure_interaction_and_return` --- ## 6. 下一步建议 按当前节奏,后续应继续按下面顺序推进: 1. 先把 `treasure / quest / battle` 的奖励发物 helper 继续收敛,减少 `spacetime-module` 聚合层的重复映射代码。 2. 再补 runtime 资源恢复、货币与 story projection 的跨域聚合写入。 3. 最后再接 Axum facade 与前端真实 treasure 主链切换。