消耗
技能、修炼、阵法、锻造、契约、符箓和品质升级共用一份消耗数组。每条费用先确定目标和数量,再执行模拟与实际扣除;公式在本次报价时只求值一次,实扣不重新求价。
报价与改价
报价固定每条费用的目标、数量和脚本参数,不扣除库存。事件改价直接替换本次费用,缩放也作用于这份固定报价;删掉的费用不会在实扣时恢复原价。
报价汇总只用于展示。数值或灵气的汇总金额不表示执行时会合并条目,也不表示已经扣款。不同上下文提供的费用可以追加到同一笔付款中,统一模拟和实扣。
一次付款的三步
- 检查重复扣除目标。开发环境记录 WARN,运行环境记录 DEBUG;诊断不拒绝付款。只报价时不输出这条诊断。
- 按数组顺序逐条模拟,只读地检查当前余额、库存和通道。任意一条失败,整笔付款不进入实扣,也不执行业务效果。
- 全部模拟通过后,按相同顺序逐条实扣。某条返回失败或抛出运行时异常,始终记录 WARN,继续后续费用和业务效果;不抛出、不回滚、不取消,也不自动重试。
两遍都保持数组顺序,脚本在它写入数组的位置执行。同一笔付款再次提交时返回缓存结果,不会再次扣款。脚本在实际 consume 前会再检查自身条件,该检查失败也遵循实扣阶段只 WARN 的规则。
付款成功表示模拟通过且实际扣除尝试已经结束,不保证所有费用全额收齐。 实际支出只按已知扣除凭据报告,失败条目返回的部分支出也会保留。某条写入后抛异常且没有返回扣量时,该条支出未知,不能推断为零或全额。JVM 致命错误不属于此处可恢复的失败。
一个目标尽量只写一条
重复目标不合并金额、不合并事务、不预留余额。余额 5、依次收费 4 和 3 时,两条模拟都能通过;实扣第一条后余额为 1,第二条失败只 WARN,最终付款成功,已知支出为 4。
目标按真实存储区分:
- 同一账户中的
mxt:resource与以它度量的mxt:aura是同一个目标。 - 世界灵气池以维度、区块和 section 区分;同一 section 内不同位置仍是同一份存量。
- 账户、世界池与方块银行互相独立,同一灵气身份不会让它们变成同一目标。
- 物品只识别同一容器且相同匹配需求的重复,不检查任意匹配器之间的交叠。
- 同一付款者的同一个脚本 id 会被诊断为重复,但每条调用仍独立执行。
因此应按共享数据类型的建议,为一个目标一次性写完费用,并避免交叠的物品需求。诊断不保证识别所有间接重复,脚本内部使用哪些存储也无法自动推断。
各通道的扣除
| 通道 | 模拟 | 实扣与凭据 |
|---|---|---|
| 数值账户 | 检查余额与使用权限 | 单条全额扣除或拒绝,报告实际数值 |
| 世界灵气池 | 检查指定 section 的灵气 | 单条全额扣除或拒绝,报告实际灵气 |
| 方块银行 | 请求 exact 检查 | 实扣也要求 exact;实现违约只提供部分时,该条失败并报告已知实取量,整笔仍继续 |
| 物品 | 只读规划该条需求的槽位 | 复核后集中写入,凭据保留实际离开物品的数量与组件 |
| 脚本 | 调用只读 check | 再 check 后调用 consume;完成凭据只表示脚本声明完成,不推断内部资源扣量 |
数值必须有限且为正。物品与银行数量向上取整,超出整数范围会在实扣前拒绝。各物品条目独立规划,不共享跨条目的槽位预留;后条可能因前条已用掉库存而在实扣失败。
脚本每次回调收到独立的参数副本,模拟修改参数不会改变实际 consume 的输入。check 必须只读,consume 不会自动退款;模拟成功也不承诺实际执行必然成功。