Files
main_plugin_farm/docs/03-business-rules.md
T
2026-10-15 14:14:58 +08:00

5.4 KiB
Raw Blame History

业务逻辑与一致性设计

状态:以下是建议约束。涉及用户资产归属、玩法与跨实例互通的选择, 需按 07-decisions.md 确认后进入正式规格。

身份与农场归属

框架(真寻/NoneBot/AstrBot)不等于消息平台(QQ/Telegram 等)。 玩家至少需要 deployment_id、realm_id、platform、platform_user_id; platform_user_id 保存字符串,禁止跨平台按相同数字自动认定同一人。

建议独立部署默认独立数据,realm 可配置群内或部署内共享。 各协议暴露的同平台 ID 也未必同义,官方 QQ 的开放标识与 OneBot 账号不能自动合并。迁移需要明确来源命名空间、人工确认映射与审计。

双人操作如偷菜必须确定双方处于同一允许交互的 realm, 检查自己偷自己、跨群目标、无农场目标和权限。@对象解析留在接入层。

货币与库存

  • 内部货币、数量使用整数;设置合理上限并检查乘法后的范围。
  • 增量和设置新值采用不同接口名称;应用层不能直接写余额缓存。
  • 扣款使用数据库条件更新,例如余额足够才扣减,检查实际影响行数。
  • 不足返回明确失败;不能静默把负余额截成零后继续发货。
  • 每次资产变动记录 operation_id、actor、realm、币种、增量、原因、 关联物品和提交时间;日志不代替可查询的账本。
  • 已锁定作物在单项出售、批量出售、交易与其他消耗入口采用一致规则。
  • 所有数量入口测试 0、负数、缺省、超大值、全部数量与库存不足; 命令层的默认参数不得被误当成任意合法业务值。

购买与出售

购买:读取有效目录→校验数量/等级→同一事务中校验和扣款→增加种子 →写操作流水→提交→生成展示数据。任一步失败整体回滚。

出售:按明确数量计算可出售库存→同一事务中检查锁定和库存版本 →扣库存→只增加本次收益→流水→提交。返回实际成交数量与新余额。 网络发送失败不回滚已成交交易;重试同一 operation_id 返回原结果。

播种与收获

播种:空地校验、种子消耗、星级选择、作物实例创建在同一事务中。 土地收益与生长速度采用已确认公式,记录规则或目录版本, 不能让资源更新悄悄改变已播种作物的结算契约。

收获:每块地独立计算产量和经验,再求和;不对累计经验反复加成。 每轮作物有可辨识的 cycle_id/harvest_index,防止重试和并发重复领奖。 作物入仓、经验增加、收获次数、下一成熟时间或枯萎状态、偷取记录 的结算必须在同一业务事务内完成。精确的事务批次由全收获与部分成功 策略决定,先定义用户可见结果,不能任意留半完成状态。

未种植、生长中、成熟、枯萎是明确状态;不要用多组互相冲突的布尔值 表示同一阶段。除草、虫害、施肥等独立属性另行建模。

签到、升级与确认

签到采用明确业务时区,(realm、player、business_date) 唯一; 签到记录、奖励发放、累计奖励领取标记在同一事务内。 “已签到”与“新签到成功”分开返回,防止重复展示发奖。 补签与连续签到规则分别定义,不从字段名猜测。

开垦和土地升级在用户确认后重新读取余额与地块状态,重新校验条件。 确认凭据绑定发起人、会话、动作、参数、过期时间和一次性标识; 不能把任何消息里的“是”当作任意待办操作的确认。 升级使作物成熟这一旧行为需明确保留或调整。

幂等与并发

operation_id 由框架事件标识与部署作用域产生;没有稳定事件标识时, 用已持久化的交互操作标识,而不是每次重试生成新的随机 ID。 同一操作不同参数应拒绝,不能错误复用第一次结果。

唯一约束、条件更新或状态版本是最终防线。 进程内锁只作辅助,跨进程不能共享这把锁。 单实例 SQLite 的连接/事务应由一个明确管理者协调; BEGIN 的锁等待、busy timeout、取消回滚、事务嵌套和连接关闭都要测试。 WAL 是部署选项,不能解决错误的业务事务边界。

外部金币兑换

真寻金币和本地农场币位于不同存储,不能承诺一个本地 SQLite 事务 同时回滚两边。先核对外部钱包是否支持 operation_id、条件扣款、 查询和退款;使用持久化兑换单与可重试状态机协调。 无法确认结果时进入待对账状态,禁止直接重复扣款或盲目发币。

普通 NoneBot、AstrBot 默认只支持内部农场货币; 外部经济系统通过能力配置接入,不导入真寻代码。 兑换比例、手续费、舍入、最小单位和失败恢复写入明确规格。

时间、事件与展示

保存 UTC 时间戳,业务日期按配置时区计算;日志记录时区语义。 时钟可注入,覆盖午夜、闰日、月切换和重启后的结算。

核心状态改变必须由事务内显式步骤完成。 提交后的消息、图片、统计等副作用失败不撤销已提交业务; 需要可靠重试时使用操作结果或持久化任务。事件槽捕获异常不能把 必需的资产更新失败隐藏成成功。首期不必新增通用事件总线。

展示读取业务结果,不在绘图过程中更新余额或土地; 图片失败回退文本,不重复执行业务。