[MD]
# LotteryBox 更新日志
## 1.0.1 — 2026-07-10
本版本恢复“选择货币后直接扣款抽奖”,同时保留“一次性钥匙购买与持钥匙抽奖”,并将经济层改造为 PlayerCurrency、XConomy、Vault 并行加载。版本号与构建产物名称保持为 `1.0.1`。
### 一、每箱独立的双抽奖模式
- 新增 `DrawMode`:
- `DIRECT`:玩家选择货币,直接扣除单次价格并开始抽奖。
- `KEY`:玩家先选择货币购买一把绑定当前箱子的钥匙,再持钥匙抽奖。
- 新增管理员指令:
- `/lb setdrawmode direct`
- `/lb setdrawmode key`
- 抽奖模式按箱子独立保存;切换模式只改变玩家右键时的交互流程,不删除货币配置、价格或奖池。
- 新创建的箱子默认使用 `DIRECT`。
- 没有 `draw-mode` 字段的旧箱子在加载时自动迁移为 `DIRECT`。
- `setmode <wool|item>` 继续只控制动画显示类型,与新的 `setdrawmode` 明确分离。
### 二、直接扣款抽奖恢复
- DIRECT 模式下,未持 LotteryBox 钥匙右键抽奖箱会打开固定 27 格“选择抽奖货币”界面。
- 每页最多显示 9 种该箱已添加且当前可用的货币,并保留上一页、下一页和关闭按钮。
- 货币按钮显示货币名称、实际经济后端、单次抽奖价格和玩家当前余额。
- 点击货币后会锁定本次操作,并重新检查箱子、模式、奖池、每日次数、货币状态和玩家看到的价格。
- 所有前置检查通过后才异步扣款;扣款成功后打开原有 36 格动画界面。
- GUI 打开后若管理员修改价格、移除货币或切换模式,本次点击会取消并要求重新打开,不会按玩家未看到的新价格扣款。
- 零价格支付方式可以正常开始抽奖,不会调用经济扣款。
### 三、已有钥匙兼容与 KEY 模式
- 已购买且绑定正确箱子的历史钥匙不会因切换为 DIRECT 而失效。
- 玩家右键箱子时,主手中的 LotteryBox 钥匙始终优先处理:
- 正确箱子的钥匙在 DIRECT/KEY 两种模式下都能消耗一把并免费抽一次;
- 其他箱子的钥匙只提示不匹配,不会消耗,也不会进入扣款或购买流程。
- KEY 模式下,未持钥匙右键会打开固定 27 格钥匙购买界面。
- 购买界面只显示本箱已添加且当前可用的货币,删除原有“如何购买”说明书,保留钥匙预览、货币按钮、分页和关闭按钮。
- 购买成功后发放一把绑定当前箱子的钥匙;购买本身不计算每日抽奖次数。
- 堆叠钥匙每次只消耗一把。
### 四、三种经济后端并行加载
- PlayerCurrency、XConomy 与 Vault 不再通过单一全局 `backend` 互斥选择,而是同时探测、独立路由余额、扣款和退款。
- 固定支付 ID:
- `playercurrency:<货币类型>`
- `xconomy`
- `vault`
- PlayerCurrency 保持软依赖并通过反射调用官方 `findAllType`、`getDesc`、`look`、`take`、`give` API;当前 Long 金额 API 按整数金额处理。
- XConomy 使用原生 API;Vault 使用当前注册的 Economy 提供者。
- 如果 Vault 的提供者就是 XConomy,只暴露 `xconomy`,避免同一账户显示为两种支付方式。
- 检测到 PlayerCurrency 时,新箱只自动加入配置白名单内的 PlayerCurrency 类型;XConomy/Vault 仍保持可用,但需要管理员手动加入该箱。
- 未检测到 PlayerCurrency 时,新箱优先加入 XConomy;XConomy 不可用时加入 Vault。
- 没有任何经济插件时 LotteryBox 仍会启动,奖品预览和历史钥匙可继续使用;付费方式暂时隐藏。
- 某经济插件暂时不可用时不会删除箱内配置;后端恢复并执行 `/lb reload` 后可直接继续使用。
### 五、箱级支付方式与独立定价
- 新增管理员指令:
- `/lb addcurrency <货币>`
- `/lb removecurrency <货币>`
- `/lb setcurrency <货币> <金额>`
- 四条模式/货币指令均要求 `lottery.admin`,并操作玩家准星六格内指向的抽奖箱。
- `addcurrency` 只允许加入当前检测到的后端或有效 PlayerCurrency 类型,自动使用规范 ID,并阻止重复添加。
- `removecurrency` 只从当前箱移除支付方式;即使后端暂时不可用,仍可按已保存 ID 移除。
- `setcurrency` 只能设置已经加入当前箱的支付方式,金额必须是不小于零的有效数字。
- `addcurrency` 仅写入货币 ID,不立即创建独立价格;执行 `setcurrency` 后才保存该货币的箱级价格。
- 直接抽一次与购买一把钥匙共用同一支付方式和价格。
- 实际价格优先级固定为:
1. `/lb setcurrency` 设置的箱级货币独立价格;
2. `economy.player-currency.costs` 的对应价格;
3. 当前箱子的 `/lb setcost` 后备基础价格;
4. 全局 `lottery.cost`。
- `/lb info` 现在显示抽奖模式、动画模式、箱级后备价格、每日限制、已添加货币、实际价格、价格来源、经济后端和当前可用状态。
- 新指令已补充权限检查、帮助、Tab 补全、用法与错误提示。
### 六、箱数据格式与自动迁移
- 每个箱新增以下持久化字段:
```yaml
draw-mode: DIRECT
payment-methods:
- id: "playercurrency:point"
cost: 10
- id: "xconomy"
cost: 1000
```
- `payment-methods` 使用有序列表,而不是把货币 ID 拼接成 YAML 路径;PlayerCurrency 类型包含特殊字符时也不会破坏配置结构。
- 缺少 `payment-methods` 的旧箱会按当前经济环境生成默认支付方式并自动保存。
- 原有箱名、基础价格、每日限制、动画模式、奖池、稀有度和抽奖次数数据继续保留。
- 重启后保持支付方式顺序、独立价格和抽奖模式。
### 七、统一抽奖事务与并发安全
- 钥匙抽奖与直接扣款抽奖共享奖池检查、每日/额外次数、结果冻结、动画、发奖和播报代码。
- 每名玩家使用操作 token 锁定付款/抽奖,防止快速连点、重复扣款、旧异步回调释放新事务或重复发奖。
- 直接扣款在所有前置检查通过后才执行;扣款成功但无法提交抽奖时,原路退回同一后端、同一货币和同一金额。
- 价格变化、模式变化、支付方式删除、箱子删除、后端失效、每日次数竞争失败、动画启动失败或玩家退出都进入安全取消/退款流程。
- 退款失败会写入严重级别控制台日志并向在线玩家显示明确警告,便于管理员人工处理。
- 钥匙只在奖池、每日限制和奖品解析全部通过后消耗;动画启动失败时退还钥匙。
- 动画开始前已冻结最终奖品;关闭 GUI 不取消结算,也不会重新随机。
- 动画期间退出时,冻结奖品按安全逻辑投放到对应抽奖箱位置。
### 八、界面、全息和文案调整
- 左键抽奖箱始终打开固定 27 格奖品预览。
- `/lb open` 仍只打开奖品预览,保留奖品数量、稀有度和分页,不显示购买钥匙或如何购买的说明。
- DIRECT 箱顶全息:`左键预览 | 右键付费抽奖`。
- KEY 箱顶全息:`左键预览 | 右键购买/使用钥匙`。
- 抽奖动画状态改为通用“正在抽奖”,不再假定一定使用钥匙。
- 默认配置新增购买按钮 Lore、直接扣款界面标题与 Lore、两种全息提示,以及支付选项失效、支付方式不可用、未添加货币、退款失败等消息。
- 启动插件或执行 `/lb reload` 时,会把新版 JAR 中缺少的配置项自动补入旧 `config.yml`,并保留管理员已有自定义值,避免显示 `[缺少消息: ...]`。
- 原“钥匙价格”注释统一改为“单次抽奖/单把钥匙共用价格”。
[/MD]