4.4 KiB
4.4 KiB
M4 Combat Reward Inventory Integration(2026-04-22)
更新时间:2026-04-22
0. 文档目标
本文件只冻结一件事:
把 resolve_combat_action(Victory) 从“只发经验”推进到“经验与战利品可在同一事务内结算”的最小主链口径。
本轮不回收完整 runtime item 导演层,也不在 module-combat 内直接做 AI 语义生成;只承接已经编译好的 reward item 快照。
1. 本轮落地范围
本轮只落实下面 4 件事:
- 在
module-combat中为battle_state补充reward_items字段。 - 允许
BattleStateInput在初始化时携带已经编译好的战利品快照。 - 在
spacetime-module::resolve_combat_action中,当结果为Victory时同步把reward_items写入inventory_slot。 - 保持
module-combat仍然是纯规则 crate,不直接依赖module-inventory。
2. 当前冻结的战利品口径
2.1 battle_state.reward_items
首版字段固定复用 module-runtime-item::RuntimeItemRewardItemSnapshot。
原因:
- 宝箱链已经用这套 reward item contract 打通到
inventory_slot。 - 任务奖励当前仍有独立
QuestRewardItem,但战斗奖励更接近 runtime item 导演层。 - 先复用现有 reward item 快照,避免本轮再发明第三套 combat 专属掉落结构。
2.2 battle 初始化来源
当前 battle_state.reward_items 不在战斗 reducer 内生成,只允许由上游在创建 battle 时传入:
resolve_npc_battle_interaction_and_return- 后续 Axum façade / runtime story orchestration
- 其它明确的 battle create 聚合入口
也就是说:
module-combat只消费已确定的 reward item 快照- 不在 reducer 内做随机、提示词、外部世界图谱推导
当前已接通:
resolve_npc_battle_interaction_and_returnPOST /api/story/npc/battlePOST /api/story/battles
这几条入口都只负责透传已编译奖励,不负责现场生成掉落。
3. Victory 发物规则
当 resolve_combat_action 结算结果满足:
outcome == Victory
则 spacetime-module 需要继续执行:
experience_reward > 0时写player_progression / chapter_progressionreward_items.len() > 0时写inventory_slot
3.1 发物方式
当前固定规则:
- 每个 reward item 显式映射成一条
InventoryMutation::GrantItem source_kind = CombatDropsource_reference_id = battle_state_id- 同一
battle_state_id只允许发放一次
3.2 幂等约束
本轮先采用与 quest / treasure 一致的“按来源引用查重”思路:
- 若当前 actor 的
inventory_slot中已经存在source_reference_id = battle_state_id - 视为该 battle reward 已发放
- Victory 再次重放时跳过发物,但不影响 battle_state 已收束结果
4. 与既有链路的边界
4.1 与 module-combat
module-combat 继续只负责:
battle_state结构resolve_combat_action状态推进- 胜负结果收束
不负责:
- inventory 写表
- progression 写表
- runtime item 生成
4.2 与 module-runtime-item
本轮不把战斗奖励映射 helper 上提到 module-runtime-item。
原因:
- 当前
RuntimeItemRewardItemSnapshot -> InventoryItemSnapshot的 helper 语义固定为TreasureReward - 若直接复用,会把
source_kind写错成TreasureReward - 本轮先在
spacetime-module里补一个 combat 专用映射,后续再统一抽象
5. 当前刻意未做
本轮明确不做下面这些扩张:
- 不把 Node 版
monster_dropAI 导演层整体迁到 Rust - 不在
resolve_npc_battle_interaction_and_return里现场计算掉落 - 不处理 battle reward 的货币、好感、情报
- 不处理战斗内
inventory_use - 不把掉落展示或 Battle Reward 面板接到前端
6. 验证要求
本轮完成后至少执行:
npm run check:encodingcargo test -p module-combat --manifest-path D:\\Genarrative\\server-rs\\Cargo.tomlcargo check -p module-combat -p spacetime-module --manifest-path D:\\Genarrative\\server-rs\\Cargo.toml
7. 下一步建议
按当前节奏,后续应继续按下面顺序推进:
- 把 Node 侧
monster_dropruntime item 编译逻辑迁到 Rust 聚合层。 - 视复用收益决定是否把 battle / treasure 的 reward item 归一化 helper 上提到
module-runtime-item。 - 最后再把 battle reward 展示、story patch 和前端接口切到新后端。