尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Mineflayer 手动关闭容器确认机制:绕过 Spigot 插件缺失的 Transaction 确认包

Mineflayer 手动关闭容器确认机制:绕过 Spigot 插件缺失的 Transaction 确认包 游戏开发【免费下载链接】mineflayerCreate Minecraft bots with a powerful, stable, and high level JavaScript API.项目地址https://gitcode.com/gh_mirrors/mi/mineflayer点击查看免费下载本文围绕 Mineflayer 官方仓库中的进阶示例 examples/advanced/chest_confirm.md讲解当部分 Spigot 服务端插件不发送窗口交易确认包transaction 确认时如何通过window.requiresConfirmation false让机器人不再挂起等待确认。读完本文你将理解 Mineflayer 窗口点击的内部确认流程、Promise 永不 resolve 与事件监听器泄漏的根因并掌握一段可立即落地的修复代码。背景为什么机器人会卡死在点击上在 Minecraft 协议中客户端对容器窗口的每一次点击click都需要服务端回执确认。Mineflayer 在 lib/plugins/inventory.js 中封装了这一机制调用bot.clickWindow(slot, mouseButton, mode)后机器人会向服务端发送window_click包并挂起等待对应的确认事件直到收到服务端返回的transaction包才继续往下执行。这一点在源码中体现得很直接在 lib/plugins/inventory.js#L660-L671点击后通过once(bot, confirmTransaction${actionId})等待服务端确认确认包由 lib/plugins/inventory.js#L707-L710 的bot._client.on(transaction, ...)回调接收并派发若迟迟等不到确认withTimeout(response, WINDOW_TIMEOUT)会在 5 秒常量WINDOW_TIMEOUT 5000见 lib/plugins/inventory.js#L16后抛错Server didnt respond to transaction for clicking on slot ...。问题出在部分 Spigot / Paper 服务端插件例如一些作弊检测、GUI 菜单、商店插件拦截或改写了容器的点击处理却不会向客户端回发transaction确认包。原版客户端对此可以容忍而 Mineflayer 却会因此无限等待。问题的两个具体症状原文档用一段代码展示了两个典型症状原示例见 examples/advanced/chest_confirm.mdbot.on(windowOpen, async (window) { window.requiresConfirmation false // fix await bot.clickWindow(13, 0, 0) console.log(bot._events) // without the fix this code is unreachable, the promise never resolve }) bot.on(windowClose, () { console.log(bot._events) // without the fix there is a confirmTransaction1 listener that is never removed })症状一Promise 永不 resolve后续代码不可达bot.clickWindow内部会先执行windowClickQueue.push(click)把本次点击加入队列见 lib/plugins/inventory.js#L596-L597然后等待confirmTransaction${actionId}事件。当服务端不发送transaction包时这个事件永远不会触发await bot.clickWindow(...)后面的console.log(bot._events)将永远无法执行——注释中 without the fix this code is unreachable 说的正是这一点。症状二confirmTransaction 监听器泄漏更隐蔽的副作用是事件监听器泄漏。once(bot, confirmTransaction${actionId})注册的一次性监听器在没有收到对应事件前不会被自动移除。窗口关闭时windowClose事件触发见 lib/plugins/inventory.js#L751-L756残留的confirmTransaction1之类的监听器仍挂在bot._events上。如果机器人反复开关容器这类监听器会持续累积占用内存并拖慢事件派发。修复原理requiresConfirmation 标记Mineflayer 的窗口对象prismarine-windows的 Window 实例上有一个requiresConfirmation布尔属性。点击流程会读取它来决定是否等待确认包if (!window.transactionRequiresConfirmation(click)) { confirmTransaction(window.id, actionId, true) }在 lib/plugins/inventory.js#L662-L664 中当transactionRequiresConfirmation(click)返回false时Mineflayer 会立即模拟一次本地确认confirmTransaction(window.id, actionId, true)让confirmTransaction${actionId}事件马上触发await bot.clickWindow(...)随即返回无需等待服务端回包。因此在windowOpen回调中把window.requiresConfirmation设为false就等于告诉 Mineflayer这个窗口上的点击不要再等服务端确认了从而同时治愈上述两个症状。完整修复代码与使用要点将上文示例落到实际机器人脚本中一个可运行的修复形态如下const mineflayer require(mineflayer) const bot mineflayer.createBot({ host: localhost, username: Bot }) bot.on(windowOpen, async (window) { // 关闭该窗口的点击确认等待适配不发送 transaction 确认包的插件容器 window.requiresConfirmation false // 点击该窗口第 13 号槽位左键普通点击 await bot.clickWindow(13, 0, 0) console.log(点击完成监听器列表, bot._events) }) bot.on(windowClose, () { console.log(窗口关闭残留监听器检查, bot._events) })使用时有几个关键点在点击之前设置requiresConfirmation false必须在任何clickWindow调用之前执行因为它影响的是点击时读到的窗口状态。按窗口粒度生效该标记属于打开的窗口实例只对当前容器生效windowOpen每次触发时都需要重新设置。点击参数格式bot.clickWindow(slot, mouseButton, mode)中mouseButton0 表示鼠标左键点击mode0 表示普通点击稳定支持。关于 mode 的支持范围可参考 docs/api.md#botclickwindowslot-mousebutton-mode0 为稳定模式1Shift 点击、2数字键、3中键、4丢弃为实验模式5、6 尚未实现。不要误伤原版行为该修复只应在确认你确实连接到存在此类插件问题的服务器时使用。对原版服务端或行为正常的服务端保留确认机制反而更安全——它保证了点击与槽位状态的一致性。底层确认流程源码解读为了让读者知其所以然这里把 lib/plugins/inventory.js 中的完整确认链路梳理如下服务端打开容器bot._client.on(open_window, ...)创建窗口对象并触发windowOpenlib/plugins/inventory.js#L738-L744。机器人发起点击clickWindow生成actionId构造click对象并推入windowClickQueue随后写出window_click包lib/plugins/inventory.js#L572-L658。等待确认once(bot, confirmTransaction${actionId})挂起等待若窗口标记transactionRequiresConfirmation为假则立即调用confirmTransaction(window.id, actionId, true)模拟确认lib/plugins/inventory.js#L660-L664。接收确认服务端回发的transaction包进入bot._client.on(transaction, ...)调用confirmTransaction(packet.windowId, packet.action, packet.accepted)从队列中弹出对应点击并触发confirmTransaction${click.id}事件lib/plugins/inventory.js#L509-L556。超时兜底若 5 秒内无确认withTimeout抛出Server didnt respond to transaction ...错误lib/plugins/inventory.js#L665-L668。从代码结构看windowClickQueue的设计lib/plugins/inventory.js#L39是为了按序处理服务端可能乱序或缺失的确认包confirmTransaction中甚至对收到非 Mineflayer 发起的交易包做了拒收处理lib/plugins/inventory.js#L514-L523。这也解释了为什么缺失确认包会让队列头部点击一直滞留、监听器无法清理。相关 API 速查事件windowOpen (window)开始使用工作台、箱子、酿造台等容器时触发docs/api.md#windowopen-window。事件windowClose (window)不再能操作工作台、箱子等时触发docs/api.md#windowclose-window。方法bot.clickWindow(slot, mouseButton, mode)点击当前窗口的指定槽位返回 Promisedocs/api.md。仓库中的同类实战用例可参考 test/externalTests/useChests.js 与 test/externalTests/playerInventory.js它们展示了在真实服务器环境中对clickWindow的完整调用与断言方式。总结本修复的核心只有一行window.requiresConfirmation false。它通过让 Mineflayer 在 lib/plugins/inventory.js 的点击流程中跳过对服务端transaction确认包的等待解决了插件容器环境下clickWindowPromise 永不 resolve、以及confirmTransaction监听器泄漏两个问题。将此修复应用于windowOpen回调即可让机器人在兼容 Spigot 生态插件服务器的同时保持容器操作的流畅与稳定。赞分享游戏开发【免费下载链接】mineflayerCreate Minecraft bots with a powerful, stable, and high level JavaScript API.项目地址https://gitcode.com/gh_mirrors/mi/mineflayer点击查看免费下载相关推荐TVBoxOSC快速配置两个地址填好就能看TVBoxOSC快速配置两个地址填好就能看 TVBoxOSC 是电视盒子上的源管理工具把自己找到的直播、影视源地址填进去盒子就能放出频道和影片。刚装上不知SoS 系统诊断工具快速上手指南三步完成 Linux 日志收集与排障SoS 系统诊断工具快速上手指南三步完成 Linux 日志收集与排障 系统半夜报警、服务无故重启、日志刷屏却看不出头绪——这样的场景任何一个运维或开发者多少运维FastStream NATS JetStream 消费确认Acknowledgement完整指南自动确认、手动确认与流程中断FastStream NATS JetStream 消费确认Acknowledgement完整指南自动确认、手动确认与流程中断 导读 本文聚焦 FastS后端消息队列微服务上一篇Airbyte source-pylon 连接器增量同步设计解析基于 Pylon API 的流级增量能力评估与状态迁移实践下一篇终极指南container30容器备份恢复策略与灾难恢复最佳实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表