UltiTrade - 玩家交易系统
安全的玩家间交易模块,支持物品、金币和经验交换,具备双方确认机制、BossBar 倒计时、交易日志、玩家黑名单和 PlaceholderAPI 集成。
功能概述
UltiTrade 为 Minecraft 服务器提供完整的玩家间交易功能。两名玩家通过命令或 Shift+右键点击对方发起交易请求,对方在聊天中收到可点击的 [接受]/[拒绝] 按钮,同时屏幕顶部出现 BossBar 倒计时。接受后双方各自打开一个 54 格的交易界面(GUI),左侧放自己要交出的物品,右侧实时显示对方放入的物品。除了物品交换,还支持金币交易(需要 Vault 插件)和经验值交易,点击 GUI 中的金币/经验图标在聊天中输入数额即可。双方都确认后交易自动完成,按校验和结算顺序转移,失败与恢复边界见升级说明。如果涉及大额金币或经验(超过可配置的阈值),系统会弹出一个额外的确认界面,防止误操作。启用日志时,完成和取消的交易记录到数据库中,过期日志自动清理。每位玩家可以单独开关自己的交易功能,也可以将特定玩家加入黑名单拒绝交易请求。
安装
有两种安装方式:
方式一:通过 UPM 在线安装
/upm install UltiTrade方式二:手动安装
- 安装前置插件:
- UltiTools-API 6.3.0+(必需)
- Vault(金币交易需要,可选)
- PlaceholderAPI(交易统计变量,可选)
- 将
UltiTrade-2.0.0.jar放入plugins/UltiTools/plugins/目录 - 重启服务器
安装完成后,配置文件会自动生成在 plugins/UltiTools/pluginConfig/UltiTrade/config/trade.yml。
升级到 2.0.0
备份配置、交易日志与待返还数据,安装 UltiTools-API 6.3.0 或更高版本,替换 UltiTrade-2.0.0.jar 后完整重启。目录身份 ultitrade 用于框架更新检查及 /upm update;框架重载/卸载使用 UltiTrade。Vault、PlaceholderAPI 都是可选依赖,缺少它们不再导致整模块加载失败;金币仍需实际 Vault 经济提供者,变量仍需 PAPI。
共享数据库的所有服务器应全部停服、一起升级再启动:旧版不认识待返还物品的 CLAIMED 状态,混用可能重复发还。已保存的运维值不自动换成新默认值。删除从未生效的 trade-timeout 与六项 messages.toggle-on/toggle-off/block-success/unblock-success/already-blocked/not-blocked 可消除启用及重载时逐键警告,框架不会替你删键。打开的交易窗口没有自动超时;request-timeout 只管尚未接受的请求。
距离策略:发送与接受都检查
allow-cross-world: false 始终拒绝跨世界请求,即使 max-distance: 0。0 只取消同世界的距离上限;设为 true 时跨世界不比较距离,不论 max-distance 是零还是正数。同世界的正数距离仍生效。发送、聊天按钮接受、/trade accept 和反向请求自动接受都按双方当前位置及当前配置检查;接受被拒会消费请求、清掉 BossBar,不会开始交易。重载不清空待处理请求,已发请求保持原超时,但接受采用新策略;交易开始后没有持续距离/世界检查。只关同世界距离但禁止跨世界可以这样写:
allow-cross-world: false
max-distance: 0保存后 /ul reload UltiTrade;不要把它解释成允许跨世界。
输入、确认与重载
金币/经验输入 0 撤回出价,cancel 只取消本次输入,10 秒无输入会返回交易窗口;NaN、Infinity 拒绝。出价真正变化才清除双方确认并刷新两个窗口,空格点击、打开输入或重复同额不会清确认。金币合计或经验合计 达到 confirm-threshold 就需要大额确认(不是只有超过才需要)。确认页只确认当时显示的出价,期间对方改动则要求重新检查;四件以上显示三个预览与单独的剩余数量。确认页 Esc/返回回到交易窗口,死亡、断线、其他插件关闭/覆盖等终止性关闭取消交易;普通交易窗口 Esc 则取消,输入和模块自有切页不算取消。其他插件拒绝打开窗口时回退,无法恢复交易窗口则取消并返还,不会永久占着出价无界面。
/ul reload UltiTrade 会重新读取配置/语言、重新查找经济提供者、调整日志清理任务、撤回新配置禁用的金币/经验出价并通知双方,保留其余出价、清确认并重画窗口,大额确认页退回交易窗口重新确认。部分步骤或某玩家窗口重绘失败时回复部分重载并列原因;旧窗口可能仍显示旧条款,先取消/重新打开并修复错误,不照旧确认。金额/经验不可用时输入仍允许 0 撤回,完成时若仍残留不可用出价则取消。
物品、结算与保存边界
从自己的背包正常提起物品再点左侧格;手持新物品点已有出价格会交换,玻璃板本身也可出价。自己背包内整理可用,但 Shift、双击收集及未知操作仍拒绝;右侧预览、禁用图标与空格占位不能拿走,第三人不能操作。取回、取消/完成时装不下会掉在脚下。日志记录实际出价数量,不被堆叠合并改小。
完成前先检查双方经验与余额,先扣双方金币,再付款;明确拒绝扣款/付款时取消并尝试退已扣款,不转移物品/经验、不收税。退款失败会写双方 UUID、金额、货币的 SEVERE,需服主处理;这是跨插件结算,不是数据库原子事务。若经济调用已生效后才抛异常,按拒绝处理但实际结果未知,可能多钱/少钱;请结合“结果未知”日志先核对实际经济流水,不要盲目重复退款;没有明确的退款失败日志不代表退款尚未发生。极高经验在 21,863 级以内精确读取,超过 2,147,483,647 点不能出价经验,已有出价会在转移前取消。经验税按十进制向下取整,NaN 或不大于零不收经验税;Paper 自身在约 411,616 点以上重建经验可能偏差数点至约 100 点。
取消时找不到的玩家,其押入物品写入 trade_pending_returns,下次进服只发背包装得下的部分,剩余保留,腾空间重进领取,不在这一步掉落。存储失败才掉到最后位置并写日志。SQLite/MySQL 先条件占用再发还,保存后删除;崩溃/保存失败留下的 CLAIMED 条目不会自动再次发,进服提示待管理员核对。JSON 在 datasource.flushRate 前还没落盘,崩溃可能重复返还;Paper saveData 失败可能只记日志而正常返回,本模块无法检测。
服主核对待返还物品
以下命令同时需要 ultitrade.use 和 ultitrade.admin,玩家与控制台均可用;普通命令仍需 ultitrade.use,仅玩家使用。先列出记录,再核对玩家背包和末影箱,确认是否已收到后才操作:
| 命令 | 含义 | 示例 |
|---|---|---|
/trade pending list | 显示暂扣条目的 ID、玩家 UUID、物品、占用时间、服务器 | /trade pending list |
/trade pending redeliver <id> | 解除该条暂扣,在线于本服立即尝试,否则下次进服发还 | 用 list 输出的真实 ID 替换 <id> |
/trade pending void <id> | 作废删除,不发还 | 用已核对已收到的真实 ID 替换 <id> |
不要反复 redeliver 代替核对,也不要手工改运行中的内部表。SQLite 手写布尔/数字的非标准形式可能使设置持续 busy;只用模块写出的形式或停服备份后修复。交易设置只在线缓存,每次 toggle/block/unblock/统计重新读写自己那项、最多重试三次,退出/关服不整份写缓存。busy 提示就稍后重试,not_saved 不是成功;MySQL 命令需等两到八次数据库往返,join 一次读取,离线变量每次查库,保持数据库低延迟。50 毫秒只限制同玩家在途写入的等待,不是全部数据库调用的总期限。
自定义文本与卸载
gui-title 和七项有效 messages 仍为内置文本时会在启动/重载后随 language 写入,自己改的值保留;要冻结内置文本至少改一个字符,直接编辑 trade.yml。toggle/block/unblock 的六条回复另从 lang 文件读取,请复制本模块 lang/zh.yml 为 lang/zh-myserver.yml,迁移 ASCII 键,在框架 config.yml 设置 language: zh-myserver 后完整 /ul reload。官方文件启动/模块重载恢复,保留 .bak;缺键按官方前缀语言回退,无官方前缀缺键回退英文并警告。24 项框架注释随启动/不带参数重载更新,手写注释保留。卸载 /upm uninstall UltiTrade 先取消并返还各笔出价、清理服务和 PAPI,再注销命令与监听器;停服不能调度日志时直接写入。
快速开始
安装完成后,任何有 ultitrade.use 权限的玩家都可以交易。最简单的使用方式:
/trade Steve # 向玩家 Steve 发起交易请求Steve 会在聊天中看到可点击的 [接受]/[拒绝] 按钮。接受后双方打开交易界面:
- 在左侧的绿色区域放入你想交出的物品
- 点击左下角的金币图标输入要交易的金币数额
- 点击左下角的经验瓶图标输入要交易的经验值
- 右侧显示对方放入的物品、金币和经验
- 确认无误后点击底部的"确认交易"按钮
- 双方都确认后交易自动完成
快捷方式:按住 Shift 键右键点击另一名玩家,也可以直接发起交易请求。
命令
玩家交易命令的别名为 /trade 和 /t,需要 ultitrade.use,仅限玩家。上方待返还管理命令另需 ultitrade.admin 且支持控制台;两节点未声明,默认 OP。
| 命令 | 说明 | 示例 |
|---|---|---|
/trade <玩家名> | 向指定玩家发起交易请求。如果对方已经向你发送了请求,会自动匹配并开始交易 | /trade Steve |
/trade accept | 接受收到的交易请求 | /trade accept |
/trade deny | 拒绝收到的交易请求 | /trade deny |
/trade cancel | 取消当前正在进行的交易,物品会退回 | /trade cancel |
/trade toggle | 开启或关闭自己的交易功能。关闭后其他玩家无法向你发送交易请求 | /trade toggle |
/trade block <玩家名> | 将指定玩家加入交易黑名单,该玩家将无法向你发送交易请求(玩家必须在线) | /trade block Griefer123 |
/trade unblock <玩家名> | 将指定玩家从交易黑名单中移除(玩家必须在线) | /trade unblock Griefer123 |
配置文件
配置文件路径:plugins/UltiTools/pluginConfig/UltiTrade/config/trade.yml
# ==================== 基础设置 ====================
request-timeout: 30 # 交易请求超时时间(单位:秒,范围:5-600)
max-distance: 50 # 交易最大距离(单位:格,范围:0-1000,0 仅取消同世界距离限制)
allow-cross-world: false # 是否允许跨世界交易
# ==================== 交易功能 ====================
enable-money-trade: true # 启用金币交易(需要 Vault 插件)
enable-exp-trade: true # 启用经验交易
enable-shift-click: true # 启用 Shift+右键点击玩家发起交易
# ==================== 税收设置 ====================
trade-tax: 0.0 # 金币交易税率(范围:0-1,0 表示不收税,0.05 表示 5%)
exp-tax-rate: 0.0 # 经验交易税率(范围:0-1,0 表示不收税)
# ==================== 确认设置 ====================
confirm-threshold: 10000 # 大额交易确认阈值(双方金币合计或经验合计达到此值需二次确认)
# ==================== 日志设置 ====================
enable-trade-log: true # 启用交易日志记录
log-retention-days: 30 # 日志保留天数(范围:1-365)
cleanup-interval-hours: 24 # 日志清理间隔(单位:小时,范围:1-168)
# ==================== 效果设置 ====================
enable-sounds: true # 启用交易音效(发送请求、接受、完成、取消等)
enable-particles: true # 启用交易粒子效果(完成/取消时的视觉反馈)
enable-bossbar: true # 启用 BossBar 请求倒计时(收到请求时屏幕顶部的进度条)
enable-clickable-buttons: true # 启用可点击的聊天按钮(收到请求时的 [接受]/[拒绝])
# ==================== GUI 设置 ====================
gui-title: "&6与 {PLAYER} 交易" # 交易界面标题({PLAYER} 会替换为对方玩家名)
# ==================== 消息设置 ====================
messages:
request-sent: "&a已向 &f{PLAYER} &a发送交易请求!"
request-received: "&e{PLAYER} &f请求与你交易!输入 /trade accept 接受"
request-timeout: "&c交易请求已超时!"
trade-complete: "&a交易完成!"
trade-cancelled: "&c交易已取消!"
trade-disabled: "&c对方已关闭交易功能!"
player-blocked: "&c对方已将你加入黑名单!"配置项速查
| 键 | 类型 | 默认值(当前语言) | 约束 |
|---|---|---|---|
request-timeout | number | 30 | 5–600 s |
max-distance | number | 50 | 0–1000 格; 0 = 仅同世界不限距离 |
allow-cross-world | bool | false | 开启/关闭 |
enable-money-trade | bool | true | 开启/关闭 |
enable-exp-trade | bool | true | 开启/关闭 |
enable-shift-click | bool | true | 开启/关闭 |
trade-tax | number | 0.0 | 0–1 |
exp-tax-rate | number | 0.0 | 0–1 |
confirm-threshold | number | 10000 | 0–1000000000; >= |
enable-trade-log | bool | true | 开启/关闭 |
log-retention-days | number | 30 | 1–365 天 |
cleanup-interval-hours | number | 24 | 1–168 小时 |
enable-sounds | bool | true | 开启/关闭 |
enable-particles | bool | true | 开启/关闭 |
enable-bossbar | bool | true | 开启/关闭 |
enable-clickable-buttons | bool | true | 开启/关闭 |
gui-title | text | "&6与 {PLAYER} 交易" | 非空文本 |
messages.request-sent | text | "&a已向 &f{PLAYER} &a发送交易请求!" | 非空文本 |
messages.request-received | text | "&e{PLAYER} &f请求与你交易!输入 /trade accept 接受" | 非空文本 |
messages.request-timeout | text | "&c交易请求已超时!" | 非空文本 |
messages.trade-complete | text | "&a交易完成!" | 非空文本 |
messages.trade-cancelled | text | "&c交易已取消!" | 非空文本 |
messages.trade-disabled | text | "&c对方已关闭交易功能!" | 非空文本 |
messages.player-blocked | text | "&c对方已将你加入黑名单!" | 非空文本 |
消息占位符说明
| 占位符 | 说明 |
|---|---|
{PLAYER} | 对方玩家名 |
使用教程
场景一:基础物品交易
玩家 A 想用 10 个钻石跟玩家 B 换一把附魔钻石剑:
- 玩家 A 执行
/trade B(或按住 Shift 右键点击 B) - 玩家 B 在聊天中点击绿色的 [接受] 按钮
- 交易界面打开,玩家 A 在左侧区域放入 10 个钻石
- 玩家 B 在左侧区域放入附魔钻石剑
- 双方可以在右侧看到对方放入的物品(悬浮可查看附魔、耐久等详情)
- 双方分别点击"确认交易"
- 交易完成,物品互换
场景二:金币交易
如果你的服务器安装了 Vault 经济插件,可以交易金币:
- 发起交易并打开交易界面
- 点击左下角的金币图标(金粒)
- 在聊天中输入金额,例如
5000(输入cancel取消) - 金额会显示在 GUI 中
- 如果配置了税率,GUI 中会显示税金和对方实际收到的金额
场景三:经验交易
- 在交易界面中点击左下角的经验瓶图标
- 系统会提示你当前拥有的总经验值
- 在聊天中输入要交易的经验值
- 确认无误后确认交易
场景四:大额交易确认
当交易中涉及的金币合计或经验合计达到配置的 confirm-threshold(默认 10000)时:
- 点击"确认交易"后会自动弹出确认界面
- 确认界面显示完整的交易摘要:你给出/收到的物品、金币、经验,以及税金明细
- 点击绿色"确认交易"完成确认
- 点击红色"取消"返回交易界面(不会取消整个交易)
- 双方都在确认界面确认后交易才会完成
场景五:管理黑名单
如果某个玩家经常骚扰你发交易请求:
/trade block Griefer123 # 把这个玩家加入黑名单
/trade unblock Griefer123 # 以后想移除可以这样被加入黑名单的玩家向你发起交易时会看到"对方已将你加入黑名单"的提示。
如果你暂时不想接收任何人的交易请求:
/trade toggle # 关闭交易功能
/trade toggle # 再次执行开启交易功能场景六:设置交易税
服务器腐竹想收取 5% 的金币交易税和 3% 的经验交易税:
trade-tax: 0.05 # 5% 金币税
exp-tax-rate: 0.03 # 3% 经验税税金在交易完成时自动扣除。例如玩家 A 给出 1000 金币,税金 50,玩家 B 实际收到 950 金币。
场景七:禁止跨世界交易
如果你不希望不同世界的玩家交易:
allow-cross-world: false # 禁止跨世界
max-distance: 50 # 最大 50 格距离PlaceholderAPI 变量
安装 PlaceholderAPI 后可以使用以下变量(标识符前缀为 ultitrade):
| 变量 | 说明 | 示例输出 |
|---|---|---|
%ultitrade_total_trades% | 玩家完成的总交易次数 | 42 |
%ultitrade_total_money% | 玩家交易过的总金额(给出) | 15000.00 |
%ultitrade_total_exp% | 玩家交易过的总经验值(给出) | 8500 |
%ultitrade_trade_enabled% | 玩家的交易功能是否开启 | true / false |
%ultitrade_enabled_display% | 交易功能状态(中文显示) | 开启 / 关闭 |
%ultitrade_is_trading% | 玩家是否正在交易中 | true / false |
%ultitrade_last_trade_time% | 上次交易时间 | 2026-02-13 14:30 |
%ultitrade_last_trade_ago% | 距离上次交易多久 | 3天前 / 2小时前 / 刚刚 |
%ultitrade_blocked_count% | 黑名单中的玩家数量 | 2 |
常见问题
1. 安装后不生效怎么办?
检查以下几点:
- 确认 JAR 文件放在了
plugins/UltiTools/plugins/目录(不是plugins/根目录) - 确认服务器安装了 UltiTools-API 6.3.0 或更高版本
- 重启服务器(不是
/ul reload,新模块需要完整重启) - 查看控制台是否有 "UltiTrade 已启用!" 日志
- 如果金币交易不工作,检查是否安装了 Vault 和一个经济插件(如 EssentialsX)
2. 改了配置文件没效果?
保存配置文件后,使用 /ul reload 命令重载配置。注意检查 YAML 格式是否正确(缩进必须用空格,不能用 Tab)。检查重载结果:部分失败时对应任务可能保留旧状态,已发请求保留旧超时;窗口与确认规则见升级说明。
3. 权限怎么设置?
普通交易使用 ultitrade.use(含 Shift+右键);待返还管理使用 ultitrade.admin。使用 LuckPerms 等权限插件设置:
/lp group default permission set ultitrade.use true建议给所有普通玩家组开放此权限,让大家都能交易。
4. 金币交易显示"未启用"怎么办?
金币交易需要两个前置条件:
- 安装 Vault 插件
- 安装一个实际提供经济功能的插件(如 EssentialsX、CMI 等)
只安装 Vault 但没有经济插件是不行的。
5. 交易时关闭界面会怎样?
关闭交易界面(按 Esc 或打开其他界面)会自动取消交易。你放入交易界面的物品会退回到你的背包。如果背包满了,物品会掉落在你脚下。
6. 一方离线了会怎样?
交易进行中如果一方离线,交易会自动取消。双方放入的物品都会退回(在线玩家退回背包,找不到的玩家存为待返还,下次进服领取;存储失败才掉最后位置)。金币和经验只在交易完成时才会实际转移。
7. 交易日志存在哪里?
交易日志通过 UltiTools-API 的 DataOperator 存储,具体位置取决于 UltiTools 的存储配置(默认 SQLite 数据库在 plugins/UltiTools/ 目录下)。日志会按 log-retention-days 配置自动清理过期记录。
更新日志
v2.0.0
新增
- 为
config/trade.yml中仍保留的每个已移除设置项输出一条控制台警告。本版本移除的七个设置项(trade-timeout, 以及messages.toggle-on、messages.toggle-off、messages.block-success、messages.unblock-success、messages.already-blocked、messages.not-blocked,见### Removed)会保留在从旧版本升级的服务器的文件中, 因为框架从不删除运维文件中的键。只要其中任何一个还在且带有值,本模块会在启用时以及每次重载本模块时 (/ul reload或/ul reload UltiTrade)为每个键记录一条警告,指出文件、键名以及该设置的去向;直接删除该键即可。 没有值的键(trade-timeout:或~)不会被报告:Bukkit 读取文件时会丢弃它,读回时与不存在相同 (UltiKits/UltiTrade#17、UltiKits/UltiTrade#18)。
变更
本版本需要 UltiTools 6.3.0 或更高版本,并在
plugin.yml中声明api-version: 630,上一个发布版本 1.0.0 声明的是620。更早的框架无法加载本版本;请先升级框架再安装。加载本模块需要重启服务器 (/ul reload不会加载新的模块 JAR)(UltiKits/UltiTools-Reborn#544)。plugin.yml现在声明identify-string: ultitrade,即本模块在 UltiCloud 模块目录中的条目键。框架的更新检查和/upm update会跳过未声明该键的模块,因此本模块现在会参与两者:带有同一键的更高发布版本会在启动时提示, 并可用/upm update安装(UltiKits/UltiTools-Reborn#474)。config/trade.yml中的消息与标题设置——交易界面标题(gui-title)与七条消息(messages.request-sent、request-received、request-timeout、trade-complete、trade-cancelled、trade-disabled、player-blocked)—— 在模块启动时按服务器语言写入,文件内容即模块显示的内容;此前它们是写死的中文,language: en对它们不起作用。 仍为内置文本(任一语言的内置文本,或旧版本的出厂默认值)的设置会跟随language:模块启动或执行/ul reload后改写为当前语言的文本。你改过的设置保持不变。若想保留内置文本又不让它跟随语言,请至少改动一个字符。在language: zh下它们都与旧版本出厂的中文文本完全相同。不再有代码读取的语言条目request_sent、request_received、trade_disabled_target、player_blocked已删除;写入trade.yml的文本来自message_request_sent、message_request_received、message_trade_disabled、message_player_blocked(UltiKits/UltiTrade#16)。写入的是本模块的内置文本:请在config/trade.yml中修改这些设置;修改已解压的语言文件不会改变它们(旧版本同样从不从语言文件读取它们)。/trade toggle、/trade block和/trade unblock的回复——开启或关闭交易、把玩家加入或移出交易黑名单, 以及对方已在或不在黑名单时的拒绝提示——现在来自本模块的语言文件,即config文件夹旁的lang/<语言>.yml(条目trade_toggle_on、trade_toggle_off、block_success、unblock_success、already_blocked、not_blocked),因此会跟随服务器的language设置:language: en下为英文,language: zh下为中文。此前无论哪种设置,这些回复都是固定的中文句子。措辞现以语言文件为准,六条中文回复中有五条 的措辞也随之改变:开关交易的两条回复不再附带第二句关于其他玩家能否向你发送交易请求的说明;"已经在你的交易黑名单中" 改为"已在黑名单中","不在你的交易黑名单中"改为"不在黑名单中";"从交易黑名单中移除"改为"从交易黑名单移除"。 只有拉黑成功的回复与之前完全相同。该命令的其余文本同样跟随language,见### Fixed(UltiKits/UltiTrade#17)。
修复
接受请求时按双方当前位置和当前配置复查跨世界及距离策略,包括聊天按钮和反向请求自动接受;拒绝时清除请求及 BossBar,不开始交易。重载后的策略在接受时生效,无须在重载时清空请求(维护者决定在 UltiKits/UltiTrade#79 内修复)。
即使
max-distance: 0,allow-cross-world: false现在也会拒绝不同世界之间的交易请求。 世界限制与距离限制独立检查;0只取消同世界的距离限制。显式允许的跨世界请求在距离限制为零或正数时 仍然允许(UltiKits/UltiTrade#78)。交易中的金币现在只在经济插件确认后才转移。此前交易先检查余额,再扣款和付款,却不读取扣款是否成功,因此检查之后余额发生变化(例如共享经济数据库的另一台服务器上的操作) 导致扣款被拒绝时,对方仍会收到金币,物品也照常转移。现在先从双方扣款;任一方扣款被拒绝或出错时,已扣除的金额会退还,整笔交易取消:金币、经验与物品都不转移, 不收税,并告知双方余额已变化、未转移任何东西。付款被拒绝或出错时同样取消交易;退款失败时记录一条 SEVERE,写明双方玩家、其 UUID、金额与货币,并告知玩家有余额未能恢复、已通知管理员。 所有余额与经验检查现在也都在任何转移之前进行:此前经验不足会在金币已经转移之后才取消交易(UltiKits/UltiTrade#58)。
多台服务器共享数据库时,待返还给玩家的物品只会发还一次,不再在每次换服时重复发还。此前进服时通过本服务器上的玩家数据判断之前的发还是否已送达, 而另一台服务器看不到这份数据,因此在服务器之间移动的玩家会在每台服务器上再次收到同样的物品。现在进服会先用一次条件写入在
trade_pending_returns中记录每次发还的状态:进服先以一次条件写入将条目标记为「已占用」(只有一台服务器能成功),玩家数据保存完成后再删除条目;装不下的部分在同一事务中成为新的未占用条目。 因崩溃或保存失败而停留在「已占用」状态的条目不会再自动发还:服务器启动及每次重载时控制台会提示此类条目的数量,新增的/trade pending list、/trade pending redeliver <id>与/trade pending void <id>命令(权限ultitrade.admin,可在控制台使用)会列出每个条目(玩家名与 UUID、物品、占用时间、服务器), 供服主检查玩家后选择重新发还或作废;在此期间玩家每次进服都会收到正在等待管理员核对的提示。共享数据库的所有服务器必须一起升级(见 README 的已知限制)。升级时,旧版本已标记为发还中的条目会先依据玩家数据结算,单台服务器上既不会重复发还也不会丢失(UltiKits/UltiTrade#55)。待返还给玩家的物品条目若在玩家加入时被读取后、写入前被删除(管理员删除,或共享数据库的另一台服务器删除),不再照常交付。此前对该条目的写入没有命中任何行、 什么也没写,物品却仍交给玩家,条目也被当作已更新。现在进服对条目的占用不会作用于已删除的行:撤销本次交付,并记录一条写明玩家与条目的日志(UltiKits/UltiTrade#53)。
玩家交易设置的存储行已不存在时,保存现在在所有存储类型上都报告为失败。模块在服务器运行期间一直缓存每位玩家的设置,因此若其
trade_player_settings行在运行中被删除,之后的开关交易、拉黑、取消拉黑、交易后统计更新或关服时的保存在 SQLite 与 MySQL 上什么也没写却当作已保存(只有 JSON 后端会报告)。 现在未命中任何行的修改会记录保存玩家设置失败:<玩家>,与写入出错时的日志行相同;关服时已不再保存(UltiKits/UltiTrade#52、UltiKits/UltiTrade#54)。玩家的交易设置存储行在服务器运行期间被删除后,其设置修改不再在下次重启时丢失。此前这种保存匹配不到任何行、什么也没写(自 UltiKits/UltiTrade#52 起至少会记录为失败),玩家聊天栏却显示修改成功。现在下一次修改会用当前设置(该玩家在线于本服期间本服最后持有的设置)重建该行,并记录一条指名该玩家的 WARNING。若共享数据库的另一台服务器已为该玩家创建了行, 则写入那一行;玩家设置行现在以玩家 UUID 作为 id,因此两台服务器同时创建或重建时只会留下一行(UltiKits/UltiTrade#57)。
多台服务器共享同一数据库时,另一台服务器上修改的交易设置与交易统计不再被还原或丢失。此前模块在服务器运行期间一直在内存中保留每位玩家的设置,并在每次修改和关服时整份写回, 因此另一台服务器期间所做的设置修改会被改回旧值,另一台服务器上完成的交易也会从
total_trades及金币、经验累计中丢失。现在玩家设置只在该玩家在线于本服期间缓存 (进服时加载、退出时丢弃),且从不写回:退出与关服时都不写入。每次修改——/trade toggle、/trade block、/trade unblock、进服时的新玩家名,以及交易完成后的统计—— 都会重新读取存储的设置、只应用这一项修改,并且仅当存储的设置仍是读取时的值时才写入;否则重新读取并再次应用,最多三次。开关交易翻转的是存储中的状态, 因此两台服务器上的两次开关都会生效。若另一台服务器持续修改,模块会记录保存玩家设置失败:<玩家>:重试写入期间存储行一直在变化……并提示玩家重试(settings_busy); 存储拒绝的修改不再提示成功——玩家会收到settings_not_saved,控制台日志写明玩家与错误。随之而来的三项开销:/trade toggle、/trade block、/trade unblock现在在回复前于主线程写入(此前在后台写入),使用 MySQL 时每条命令需等待两到八次数据库往返;每次进服在主线程进行一次数据库读取;离线玩家的占位符每次求值都会查询数据库 (此前离线玩家会在服务器运行期间一直被缓存)。同一服务器对同一玩家的设置写入逐个进行;玩家不会等待其他玩家的写入。主线程上的命令、进服或设置读取最多等待约 50 毫秒(一个 tick)该玩家正在进行的写入 (交易统计):需要更久的命令回复settings_busy且不做任何修改;进服则既不读取也不缓存——新的玩家名会在该玩家下一次设置写入时写入(每次写入都带有当前玩家名)——未缓存的读取则直接读取存储的设置而不缓存(UltiKits/UltiTrade#54)。交易的扣款或付款在经济插件中抛出异常时,现在记录一条服主可据以处理的 SEVERE 日志:
结果未知:交易扣除 <金额>(来自 <玩家>)时出错,交易按未扣除处理, 但经济插件可能已经扣除。请检查 <玩家> 的余额是否有 <金额> 的变动(付款同理),金额完整显示(12345678.9,而非1.23456789E7)。此前是一条只说明 「按拒绝处理」的 WARNING。交易仍将此类调用视为被拒绝;已生效后才抛出异常的调用作为已知限制记录在文档中。退款或收回付款抛出异常时,现在只记录这一条, 不再同时记录确定性的「请手动退还 / 手动收回」日志,以免服主对实际已生效的调用再更正一次;被拒绝的退款或收回仍保留那条日志(UltiKits/UltiTrade#60)。等级极高的玩家不再读到负数的经验总量。此前从 15,466 级起(例如执行
/xp set <玩家> 16000 levels后)经验总量会溢出,经验输入提示和交易界面显示负数, 所有经验报价都被判为经验不足而拒绝。现在经验总量在 21,863 级以内精确计算;更高等级的总量超过 2,147,483,647 点,无法精确计算,因此这类玩家不能出价经验: 点击经验栏位与经验数量输入都会提示exp_total_unreadable,交易界面显示该提示而非总量;若出价在玩家达到此等级之前已设置,交易会在任何东西转移之前取消 (cancel_reason_exp_unreadable)。若从封顶后的数值中扣除报价,会使玩家的经验比实际少数亿点。超出 int 范围的经验合计现在完整计算:两笔大额报价仍需大额交易确认, 记录的经验税与total_exp_traded不再变为负数。Paper 自身经验计算在约 411,616 点以上的偏差 作为已知限制记录在文档中(UltiKits/UltiTrade#65)。exp-tax-rate: .nan不再导致经验交易出错:任何不大于零的税率(包括 NaN)都不收取经验税。此前 NaN 会在计算税额时抛出异常——在完成交易时发生于金币已转移之后, 两个交易界面也会出错(UltiKits/UltiTrade#65)。本模块的重载有部分失败时,
/ul reload UltiTrade(以及不带参数的/ul reload)不再回复单纯的成功。若重新安排交易日志清理任务、应用enable-money-trade、 或作废进行中交易的确认并重绘其窗口失败,或某位玩家打开的交易窗口未能重绘,模块仍记录该错误并继续执行其余部分,同时回复与框架的重载日志行会说明重载不完整,并列出未完成的每个步骤及其原因,或窗口仍显示旧条款的玩家(UltiKits/UltiTrade#50)。config/trade.yml的注释现在跟随服务器语言。此前文件中全部二十四条注释(每个设置一条)只有中文,language: en的全新安装得到的文件注释是中文。 现在每条注释都是一个语言文件键,框架每次写入文件时按服务器的language解析,lang/en.yml与lang/zh.yml各有英文和中文条目。 已有服务器上框架在这些设置上写下的注释(包括旧版本写下的中文注释)会在下次启动时、以及你修改language并执行不带参数的/ul reload后 切换为服务器语言;设置值不受影响,你自己写的注释保持原样(UltiKits/UltiTools-Reborn#611)(UltiKits/UltiTrade#51)。现在有其他插件拒绝大额交易确认页面自身的
InventoryOpenEvent时,不会再让玩家完全没有交易界面,同时交易仍在进行、 双方出价被一直占用。该页面原本要替换的交易窗口此时已经关闭,而HumanEntity#openInventory在打开被拒绝时会返回null而不是抛出异常,因此此前这一失败不会被察觉。现在会像点击该页面自身的取消按钮一样把玩家送回交易窗口——不会 直接取消交易,因为玩家的出价并未发生任何变化(UltiKits/UltiTrade#47 复查)。现在重载时若未能为已打开的大额交易确认页面构建或打开替换窗口,会取消该笔交易并返还双方出价,而不是让该页面 保持已失效状态(其按钮和 Esc 此时均不再产生任何效果),同时交易仍在进行、双方出价被一直占用,只能靠有人发现 后手动取消。重载原有的、按玩家记录的重绘失败错误日志保持不变(UltiKits/UltiTrade#47 复查)。
现在其他插件关闭玩家的大额交易确认页面,或在其上打开自己的窗口时,不会再让交易悄悄保持进行、双方都没有窗口, 直到有人手动取消。此前无论是本模块自身的关闭(点击按钮、完成或取消交易、重载重绘)还是其他插件造成的关闭, Paper 报告的都是同一个
PLUGIN/OPEN_NEW原因,仅凭原因无法区分两者;现在本模块自身的每一次关闭都会先标记 该页面,一个未被标记就到达的PLUGIN/OPEN_NEW关闭会被当作终止性原因处理,与死亡、断线的处理方式一致 (UltiKits/UltiTrade#47 复查)。玩家刚输入的金额或经验数量,现在不会再因一个 tick 后交易被取消而丢失。输入答案会立即被认领(从待处理提示映射中移除), 但只会稍后在服务器线程上应用;而关闭守卫自身的延迟检查——在提示本身关闭交易窗口的那一刻就已排定,早于提示被登记之前—— 可能恰好在这段间隙运行,看到没有待处理的提示,就会像玩家从未回答一样取消交易。现在会单独跟踪这个「已认领但尚未应用」 的答案,使关闭守卫仍能识别它(UltiKits/UltiTrade#47 复查)。
两条控制台日志现在按原样给出文件路径或世界名:已不再读取的配置项警告,以及无法保存而掉落的交易物品的错误。此前路径或世界名先于
{KEY}、{REASON}、{ITEMS}占位符插入,含这些占位符时会被改写。现在同一行的所有占位符一次性替换(与 UltiKits/UltiMail#37 相同的修复)。当
/ul reload UltiTrade使金币交易不可用(关闭金币交易或找不到经济提供者)时,所有进行中交易里出价的金币会被撤回并通知双方,交易的其余内容仍可完成; 关闭经验交易时,经验出价也同样撤回。不可用期间,对应的聊天提示接受0以撤回出价。此前这样的出价无法撤回,只能取消交易(UltiKits/UltiTrade#28)。已取消交易遗留的金币或经验输入提示不再影响玩家之后开启的交易:其 10 秒超时不再重新打开旧交易的窗口(此前会导致新交易被取消并通知双方), 也不再关闭在新交易中打开的提示,也不再阻止关闭新交易窗口时取消新交易;为它输入的数额会提示「交易已结束」,不会被应用到新交易(UltiKits/UltiTrade#40)。
金币或经验达到
confirm-threshold的交易,在双方都通过确认页面确认后即完成,与较小的交易一致。此前确认页面只记录确认,这样的交易永远无法完成(UltiKits/UltiTrade#21)。当交易的金币或经验达到
confirm-threshold时,点击确认现在会打开确认页面,交易继续进行。此前为打开该页面而关闭交易窗口时会先取消交易并退回全部物品, 页面随后打开的是已不存在的交易(UltiKits/UltiTrade#23)。确认页面的取消按钮或按 Esc 关闭页面会回到交易窗口; 因交易取消或完成、重载或其他窗口覆盖而被关闭的确认页不算作取消;只有该页面所属的玩家能作答。确认按钮只确认页面所显示的出价—— 页面打开期间任一方改动了出价,则不会确认,并提示玩家重新检查交易。金币、经验输入提示中输入的数额在服务器主线程上生效, 不会插进这一检查与确认之间。在交易窗口中,空手点击自己的空格子,或打开金币、经验输入提示,不再清除双方的确认。只有出价真正变化时才清除确认,并同时刷新双方窗口; 在输入提示中再次输入已出价的数额不算变化。此前这样的点击会清除确认却不刷新,玩家看起来仍已确认,交易却无法完成(UltiKits/UltiTrade#36)。
金币和经验的聊天输入提示会以「无效的数额」拒绝
NaN和Infinity。此前NaN会被接受为金币出价,完成交易时金币转账被跳过而物品照常交换, 对方看到的是NaN(UltiKits/UltiTrade#29)。大额交易确认页面上,一方放入四个及以上物品时,会显示三个物品预览,并在单独的格子中显示「还有 N 个物品」; 此前该提示覆盖了第三个预览,只能看到两个物品(UltiKits/UltiTrade#22)。
大额交易确认页面中预览的物品现在在描述中带有「交易物品」标记行;此前该行被生成后又被丢弃(UltiKits/UltiTrade#43)。
交易窗口始终显示双方已放入的内容。此前七种打开交易窗口的方式中有五种——金币或经验输入提示超时后、对提示回复
cancel后,以及大额交易确认的两条路径——会显示空的交易,而双方的物品实际仍在交易中,玩家可能在看不到内容的情况下确认交易(UltiKits/UltiTrade#35)。修复:交易取消时若服务器找不到一方,其押入的物品会被保存,并在其下次进服时发还,不再被销毁。物品保存在新表
trade_pending_returns中;无法保存时掉落在该玩家最后所在的位置,两种情况下控制台都会写明玩家与物品。 进服发还时只发背包装得下的部分,其余继续保存,并告知玩家还有多少物品保留、腾出空间后重新进服领取,不会掉落在地。 使用 SQLite 或 MySQL 存储时,发还过程中服务器崩溃不会重复物品,该次发还会被暂扣交由服主处理(见上文 UltiKits/UltiTrade#55 条目);使用 JSON 存储时列表要到下次写盘 (datasource.flushRate)才落盘,在此窗口内崩溃可能导致重复发还(UltiKits/UltiTrade#32)。language: en现在对本模块显示或记录的全部内容生效:/trade的所有回复与帮助,交易请求(可点击按钮、按钮的悬停 提示与倒计时 BossBar),请求、接受、拒绝与取消的回复及每一种取消原因,交易界面与大额交易确认页(标题、物品名称、 说明、按钮、税费行),金币与经验的输入提示及回复,PlaceholderAPI 的显示值(enabled_display、last_trade_time、last_trade_ago),命令描述以及控制台日志。其中大部分原先在任何语言下都是写死的中文,而语言文件中其实已有其中许多 内容的无人读取的英文文本;控制台日志原先写死为英文,现在也跟随language: zh(UltiKits/UltiTrade#16)。语言键已改名: 少数以中文句子作为语言键的行现在改用 ASCII 键。如果你在自己的语言文件中自定义过本模块的消息——即把官方文件复制一份,文件名以该文件的语言代码加连字符开头 (例如lang/zh-myserver.yml),并在plugins/UltiTools/config.yml中设置language: zh-myserver选择它——请把这些修改重新应用到新键上; 在此之前,改名的行显示文件名开头那种官方语言的文本。文件名不以官方语言代码加连字符开头的副本仍会被读取,但其中缺少的消息 都显示英文,并记录一条警告。 直接在官方语言文件(lang/en.yml、lang/zh.yml)中做的修改不会保留:框架会在每次启动以及每次模块重载时恢复官方文件,并把修改过的文件保留为.bak(UltiKits/UltiTools-Reborn#616)。重载本模块(
/ul reload UltiTrade)现在会重新读取config/trade.yml并刷新语言文件,修改后的max-distance等配置无需重启即可生效。此前本模块的重载方法替换了框架的重载方法且只输出一行日志, 这两步都不会执行。UltiTools 6.3.0 还会在此时报告@ConditionalOnConfig漂移并输出框架自身的 模块重载日志(UltiKits/UltiTrade#15)。/ul reload UltiTrade现在还会应用enable-money-trade、enable-trade-log和cleanup-interval-hours。 本模块新增的重载钩子会重新查找 Vault 经济提供者,使开启或关闭金币交易无需重启即可生效;并重新调度旧日志 清理任务,使关闭enable-trade-log后该任务停止、开启后启动一个任务、修改间隔后以新间隔替换。此前经济 提供者查找与清理任务只在模块启动时设置,因此开启金币交易以及对清理任务的任何修改都要重启后才生效。已发出的 待处理交易请求保持其发出时的超时时间;修改后的request-timeout只对重载之后发出的请求生效(UltiKits/UltiTrade#26)。若交易中任一方仍有金币出价,而在交易完成的那一刻金币交易不可用,该交易现在会被取消。这一完成阶段的保护 只适用于届时仍有不可用金币出价的情况;重载会改为撤回此类出价(见下文)。不转移任何金币,双方各自 取回自己放入的物品,并被告知金币交易当前不可用,而不是在不支付所出金币的情况下交换物品与经验。金币交易 不可用时,聊天输入金额提示也会拒绝金币数额,而不是接受它(UltiKits/UltiTrade#26)。
/ul reload UltiTrade现在会清除所有已有确认的进行中交易的确认状态,并提示双方重新确认,因此交易不会再按 玩家确认后被重载修改的条款(如trade-tax、exp-tax-rate、confirm-threshold)完成。同样,若任一方仍有 经验出价,而交易完成时enable-exp-trade已关闭,该交易会被取消,而不是在不转移经验的情况下交换物品;enable-exp-trade关闭时,聊天输入提示也会拒绝经验数额(UltiKits/UltiTrade#26)。/ul reload UltiTrade现在会按重载后的配置重绘所有已打开的交易界面,使其标题、金币与经验交易的可用状态和税率 与交易实际收取的一致。重载使之不可用的金币与经验出价会被撤回,双方的确认被清除;其余出价保留,交易继续, 双方需重新确认。已打开的大额交易确认页会被替换为交易界面,交易继续进行, 玩家需在该界面重新确认(UltiKits/UltiTrade#27)。玩家不再能通过点击,在金币交易关闭时从交易界面的金币栏、在经验交易关闭时从经验栏取走展示物品,或从空物品栏 取走玻璃板。交易界面中的每次点击现在都会先被取消,再执行对应操作(UltiKits/UltiTrade#25)。
/upm uninstall UltiTrade现在会先执行本模块自身的清理(关闭交易服务、注销 PlaceholderAPI 扩展), 再由框架注销命令,最后注销监听器,因此卸载后本模块的命令会被真正移除,其监听器也不再触发。此前本模块 的卸载方法替换了框架的卸载方法,因此其命令和监听器都会一直保持生效,直到服务器重启 (UltiKits/UltiTrade#15)。从交易界面取回已放入的物品时,若操作玩家的背包已完全装满,该物品不再被销毁:装不下的部分现在会掉落在该玩家 脚下,与取消或完成交易时返还物品所用的溢出处理一致。此前该物品会被静默销毁,而双方交易界面中的该格子仍会恢复 为玻璃板占位符,仿佛取回成功(UltiKits/UltiTrade#20)。
玩家放入自己交易格的染色玻璃板,在其上放置其他物品时不再被销毁,并且现在可以被取回。点击自己的物品格时执行 哪种操作,现在依据交易会话中记录的出价判断,而不再依据该格所绘制物品的材质,因此玩家出价的玻璃板不会再被误认 为空格占位符。手持物品点击自己已有出价的格子现在会交换:手持物品放入该格,原有出价返还给玩家,装不下则掉落在 其脚下。此前这一点击会直接销毁存放的玻璃板;对其他物品则是取回该物品、而手持物品仍留在光标上 (UltiKits/UltiTrade#31)。
关闭服务器或卸载本模块,不再销毁仍在进行中的交易里已放入的物品。现在每份出价都会先返还给玩家(放不下则掉落 在其脚下),之后才执行其他步骤,并且每笔进行中的交易互相独立地关闭。此前取消交易的第一步是调度交易日志写入, 而正在关闭的服务器会拒绝该调度:这一异常使取消在任何物品返还之前就结束,并跳过其余所有交易,而控制台只报告 本模块注销失败,而非物品丢失。取消记录仍会保留:在无法调度后台任务时,日志条目会直接写入而不是被丢弃 (UltiKits/UltiTrade#34)。
交易日志现在记录实际放入的数量。此前将一组物品交付到已有同材质零散堆叠的背包时,该合并会改写这组物品本身, 因此向已有 60 个钻石的背包交易 64 个钻石会被记录为 60(UltiKits/UltiTrade#37)。
交易界面中来自两名交易者以外任何人的点击都会被拒绝。此前这类点击会被当作第二名交易者的点击处理,因此被其他 插件展示了该界面的第三名玩家会拿到该交易者已放入的物品(UltiKits/UltiTrade#38)。
现在终于可以把物品放入交易。此前所有落在操作玩家自身背包内的点击都会被拒绝,而在交易界面打开时,点击自身背包是 玩家把物品提到光标上的唯一途径,物品格恰恰只读取光标。因此自本模块首个版本起,任何玩家都无法放入任何物品。仅在 玩家自身背包内进行的拖拽也因同样的原因(只是层级不同)被拒绝,使玩家在交易期间无法整理自己的背包。交易界面与确认 预览界面现在只管辖各自窗口内的格位。以下三种操作从自身背包格发起时仍会被拒绝,因为它们并不局限于所点击的那一格, 会伸进窗口内:Shift 点击、双击收集,以及服务器报告为未知的操作(UltiKits/UltiTrade#39)。
本模块现在可以在没有安装 PlaceholderAPI 的服务器上加载。此前模块主类的一个字段直接以
TradePlaceholderExpansion(一个 PlaceholderAPI 类型)声明,框架容器在自动装配本模块时会抛出NoClassDefFoundError,导致整个模块加载失败—— 不仅是变量功能,交易功能本身也一并不可用;此缺陷自本模块首个提交起就存在(UltiKits/UltiTrade#48)。本模块现在可以在没有安装 Vault 的服务器上加载。此前
TradeService的经济字段与getEconomy()的返回值类型都直接 声明为net.milkbowl.vault.economy.Economy,而本模块的plugin.yml从未把 Vault 声明为依赖(甚至连软依赖都没有), 因此没有任何机制保证缺少 Vault 时的行为——与 #48 崩溃形状相同,只是软依赖不同,由针对同一缺陷类的普查发现 (UltiKits/UltiTrade#49)。现在在查看大额交易确认页面时死亡会取消交易,下文所述的其他终止性关闭也一样。按 Esc 或点击页面的取消(返回)按钮 只会回到交易窗口,交易和押入物品均保留。此前 Paper 以
InventoryCloseEvent.Reason.DEATH关闭该页面时,会被当作模块自身的关闭(重载、完成、取消)处理,交易会悄悄保持进行、双方都没有窗口,两方的出价也一直 被占用,直到有人手动运行取消命令。现在服务器(而非本模块)出于其他任何原因关闭大额交易确认页面时,都会像
DEATH一样取消交易:断线、传送(仅限仍会 发送该原因的旧版本服务端——Paper 自 1.21.10 起已弃用该原因,普通传送不再触发关闭)、所在区块被卸载、 服务器出于其他原因收回了访问权限,或是一个未识别的原因。此前只有DEATH会取消交易;以上任何一种都会让交易悄悄保持进行、双方都没有窗口、两方出价被一直占用,直到有人手动运行 取消命令。本模块自身或重载引发的关闭(PLUGIN、OPEN_NEW)行为不变——它们从不取消交易,因为引发关闭的代码 本身已经掌管了会话的下一个状态(其他插件引发的未标记关闭则会取消交易,见上文)。本模块中打开交易窗口的其余每一处,现在都采用大额交易确认页面已经使用的同一种恢复方式:
InventoryOpenEvent被拒绝时,HumanEntity#openInventory返回的是null而不是抛出异常,此前其余六处调用均未检查这一点,导致其他 插件可能让玩家完全没有窗口,而其会话仍在继续运行——六处中有三处发生在双方都尚未压上任何出价时,且都只能靠手动 取消才能恢复。现在,若开始一笔交易时第一位玩家自己的窗口被拒绝,会立即取消这个仍为空的会话,不会再让第二位 玩家看到一个对方从未真正加入的交易窗口;超时后的重新打开、回答金额提示后的重新打开,以及会话转移后双方窗口的 重绘,若被拒绝也都会同样地取消该笔交易(UltiKits/UltiTrade#47 复查)。plugin.yml现在声明softdepend: [ PlaceholderAPI, Vault ]。两项集成仍为可选;未安装其中任一插件时, 本模块仍可加载(UltiKits/UltiTrade#48、#49)。
移除
移除七个从未有代码读取的语言条目:
confirm_required、confirmed、confirmation_cancelled、request_expired、trade_started、gui_status_confirmed、gui_status_pending。移除它们不会改变玩家看到的任何内容。移除本模块在
/ul reload UltiTrade时输出的"UltiTrade 配置已重载!"控制台行,以及未被使用的trade_reloaded语言键。UltiTools 6.3.0 会为每个模块输出一行重载日志(UltiKits/UltiTrade#15)。移除
config/trade.yml中的trade-timeout设置项。它在任何版本中都从未生效:没有任何代码读取它,而已打开的 交易窗口根本没有时间限制——只有玩家取消、双方确认、一方退出或关闭窗口时才会结束。待处理的交易请求仍会在request-timeout秒后过期,该设置项不变。移除该设置项并不代表否决它所描述的功能:为已打开的交易窗口设置时间 限制已作为功能请求 UltiKits/UltiTrade#41 留档(UltiKits/UltiTrade#18)。移除
config/trade.yml中的六个设置项messages.toggle-on、messages.toggle-off、messages.block-success、messages.unblock-success、messages.already-blocked和messages.not-blocked。它们在任何版本中都从未生效: 它们所描述的命令一直发送自己固定的文本,修改这些设置项从未改变玩家看到的内容。这些回复现在来自语言文件 (见### Changed)。要自定义这些回复,请把官方语言文件复制为以其语言代码加连字符开头的文件(例如lang/zh-myserver.yml), 在副本中修改,并在plugins/UltiTools/config.yml中设置language: zh-myserver;直接修改官方文件的改动会在下次启动或模块重载时被恢复 (UltiKits/UltiTools-Reborn#616)。其余七个messages.*设置项会被读取,保持不变(UltiKits/UltiTrade#17)。
v1.0.0 (2026-02-13)
初始发布。
新增:安全的双方确认交易机制 新增:GUI 交易界面(54 格大箱子布局,左侧放入/右侧预览) 新增:金币交易功能(需要 Vault),支持交易税 新增:经验值交易功能,支持经验税 新增:BossBar 倒计时显示交易请求剩余时间 新增:聊天中可点击的 [接受]/[拒绝] 按钮 新增:Shift+右键点击玩家快捷发起交易 新增:大额交易二次确认界面(金币或经验超过阈值) 新增:玩家交易开关(/trade toggle) 新增:玩家黑名单功能(/trade block、/trade unblock) 新增:交易日志记录(完成和取消的交易都记录),自动清理过期日志 新增:交易统计(总交易次数、总金额、总经验、上次交易时间) 新增:PlaceholderAPI 集成(9 个变量) 新增:交易音效反馈(发送请求、接受、物品放入、完成、取消) 新增:交易粒子特效(完成时绿色粒子,取消时烟雾粒子) 新增:物品详情悬浮预览(对方物品显示附魔、耐久度、物品标志等) 新增:交易距离限制和跨世界交易控制 新增:双方互发请求时自动匹配开始交易 新增:所有消息可自定义,支持颜色代码
Ling Bao