驅動真實客戶端(BeDD)
通常情況下 bedboo 本身就是客戶端:它通過 RakNet 或 NetherNet 登錄基岩版專用服務器,並親自發送每一個數據包。使用
transport: 'bedd' 時,它改為驅動一個真實的 Minecraft 基岩版 1.26.51.01 客戶端,該客戶端由
Be.D.D.(Bedrock Deep Dive,一個 LeviLamina 客戶端模組)託管。於是同一個腳本會作用於你桌面上的
遊戲窗口:你能看到本地玩家按照腳本的指示行走、轉頭、挖掘、放置和聊天。
const bedboo = require('bedboo')
const bot = bedboo.createBot({ transport: 'bedd', bedd: { pipe: '\\\\.\\pipe\\BeDD' } })
bot.once('spawn', () => bot.chat('hello from bedboo'))兩種模式之間的切換隻取決於 transport;直連 BDS 的模式(raknet、nethernet)保持不變。該模式的差異逐條列在
BeDD 模式中。
安裝配置
僅支持 Windows(BeDD 的管道是 Windows 命名管道);需要 Node 24 或更高版本。
-
將 BeDD 安裝到一個 Minecraft 基岩版 1.26.51.01 實例中(見 BeDD 文檔;
clone-instance.ps1可以創建一個獨立實例,Start-BeDDGame.ps1 -Instance <name>用於啟動它)。 -
在實例的
mods\BeDD\config\config.json中開啟 bedboo 所需的功能。這些功能全部默認關閉:鍵 默認值 啟用的內容 bedboo 用它來 pipeNameBeDD控制管道 \\.\pipe\<pipeName>;tap 管道為\\.\pipe\<pipeName>-tapbedd.pipe(tap 管道名由此推導)tapfalsetap 管道:所有客戶端方向(clientbound)的數據包、所有服務端方向(serverbound)數據包的回顯、標記,以及一份加入日誌 一切功能(沒有它 bedboo 無法附加) tapLoopbacktrue監聽單人 / 局域網主機世界(迴環鏈路,數據包經重新序列化) 單人遊戲 tapJournalMiB128回放給後附加客戶端的加入日誌的大小上限 在會話中途附加(超過上限時為 complete:false)gameHooksfalseworld、look和input操作(掛鉤到遊戲自身的輸入管線)精確的移動和視角(沒有它:使用虛擬按鍵和鼠標) allowSendfalse針對白名單中數據包 ID 的 send操作(sendAllow,默認[9, 77]= text、command_request)bot.chat、私聊、命令allowStackfalsestack操作:通過客戶端自身的 ItemStackNetManager 提交 item_stack_request物品欄:clickWindow、transfer、craft、deposit/withdraw、從主物品欄裝備、創造模式 pipeInstances4同時允許連接的控制管道客戶端數量 讓 bedboo 與 BeDD.psm1 及其他測試工具並存 一份適用於 bedboo 的配置:
json{ "pipeName": "BeDD-1.26.51.01-hi20", "tap": true, "tapLoopback": true, "gameHooks": true, "allowSend": true, "allowStack": true, "pipeInstances": 4, "loopbackOnly": true }loopbackOnly(BeDD 自己的配置項)讓客戶端只連接本機(127.0.0.1)上的服務器。客戶端通過 NetherNet 加入 BDS 1.26.51,因此請以transport=nethernet啟動服務器;NetherNet 加入要經過 Minecraft 的在線信令服務,所以在客戶端加入和 遊戲期間,這臺電腦上不能再啟動其他 Minecraft 遊戲(後續的登錄會把當前會話擠掉:"Multiplayer Connection Failed … NetherNet")。 -
啟動遊戲,讓玩家進入一個世界(服務器、局域網世界或單人遊戲):bedboo 附加到一個已經在遊戲中的客戶端上,它不負責登錄。
-
createBot({ transport: 'bedd', bedd: { pipe: '\\\\.\\pipe\\BeDD-1.26.51.01-hi20' } })。加入日誌回放完成後觸發spawn; 從此bot.*反映的就是客戶端的狀態。
bedd_follow.js 示例讓客戶端跟隨最近的其他玩家:
node examples/bedd_follow.js --pipe \\.\pipe\BeDD-1.26.51.01-hi20工作原理
真實客戶端對它發送的一切保持權威:登錄、資源包、加載界面、區塊請求、每 tick 的 player_auth_input(包括物理)、方塊操作、
物品欄事務和物品堆疊請求。bedboo 從不偽造這些數據包。它的整個棧依然運行,而它原本要發送的內容會變成交給客戶端的意圖:
script → mineflayer API → plugins → _client.queue → router ──(JSON ops)──────→ \\.\pipe\<pipeName> → the game's input pipeline
bot.* state ← plugins ← decoder ← tap reader ←──(binary frames)──── \\.\pipe\<pipeName>-tap ← every packet the client gets / sends- 狀態輸入: tap 管道傳送客戶端收到的每一個客戶端方向數據包、它發送的每一個服務端方向數據包的回顯,以及 JSON 標記
(
HELLO、LINK_UP/LINK_DOWN、REPLAY_BEGIN/REPLAY_END、DROPPED)。bedboo 用 bedrock-protocol 解碼它們,方式與直連 模式完全相同,因此bot.entities、世界、物品欄、聊天以及每一個事件都來自真實會話。一份加入日誌(從start_game開始, 經過壓縮:每個位置只保留最新的區塊,每個實體只保留最新的屬性,已移除的實體會被剔除)會回放給每個新的 tap 客戶端,因此 bedboo 可以在會話中途附加。如果 bedboo 落後超過 32 MiB,BeDD 會發送DROPPED並關閉連接;bedboo 會重新連接並獲得完整回放。 - 自身狀態:
bot.entity的位置、速度、偏航角、俯仰角和 onGround 跟隨回顯的player_auth_input(眼睛高度 − 1.62)。physicsTick和move每個客戶端 tick 觸發一次;bedboo 自己的物理引擎不會步進。 - 意圖輸出: 路由器對比 bedboo 原本要發送的內容,並調用 BeDD 的控制操作:
input(移動向量、跳躍、潛行、疾跑,帶有失效保護 TTL)、look(絕對偏航角/俯仰角)、slot、button(攻擊/使用/選取,挖掘時方塊變化即釋放)、action(丟棄、物品欄……)、send(白名單內的 text/command_request 字節)以及stack(通過客戶端的 ItemStackNetManager 發送 item_stack_request)。 只有在遊戲佔有鼠標且沒有打開菜單時,輸入才會生效。 - 協商: 附加時,bedboo 會 ping 控制管道,並以不帶參數的方式探測每個操作:
unknown op→ 不存在(absent),code:'disabled'→ 存在但在 config.json 中被關閉,ok→ 存在(present)。bot.bedrock.bedd.caps保存探測結果,bot.bedrock.bedd.supports(name)按 mineflayer API 逐項給出答案。
權威歸屬表
| 類別 | 數據包 | 處理方式 |
|---|---|---|
| clientOwned | login, client_to_server_handshake, request_network_settings, resource_pack_client_response, client_cache_status, client_cache_blob_status, request_chunk_radius, subchunk_request, serverbound_loading_screen, set_local_player_as_initialized, network_stack_latency, tick_sync, player_skin, emote_list, respawn, player_action (dimension_change_ack / start_item_use_on / stop_item_use_on), animate, interact mouse_over_entity | 被路由器丟棄(客戶端會自己發送);計入統計 |
| translated | player_auth_input(move_vector 和標誌 → input;yaw/pitch → look;block_actions start_break / abort_break / stop_break → button attack)、mob_equipment(→ slot)、inventory_transaction(item_use click_block / click_air、item_release、item_use_on_entity → look + button)、interact open_inventory(→ action inventory)、container_close(→ ESC)、item_stack_request(→ stack) | 轉換為控制操作 |
| shared | text, command_request | 以字節形式通過 send 發送(保留命令 uuid,因此 command_output 能對應上);兜底方案:T / SLASH 鍵、text、ENTER |
| unsupported | book_edit, block_pick_request, crafting_event, set_default_game_type,以及其他所有數據包 | BeddUnsupportedError(code: 'ERR_BEDD_UNSUPPORTED') |
支持範圍
“Caps” 列出該 API 所需的 BeDD 操作;缺少它們時 bot.bedrock.bedd.supports(name) 為 false,調用會拋出或以
ERR_BEDD_UNSUPPORTED 拒絕(或使用所列的兜底方案)。
| API | 是否可用 | caps(兜底方案) |
|---|---|---|
spawn、login、遊戲事件、bot.game、時間、天氣、生命值、飢餓值、經驗 | 可用,來自 tap | tap |
bot.entities、bot.players、方塊與世界(blockAt、findBlocks、射線檢測、waitForChunksToLoad) | 可用,來自 tap | tap |
| chat / message / messagestr 事件、標題、Boss 欄、計分板、Tab 列表、聲音、粒子、爆炸 | 可用,來自 tap | tap |
bot.inventory、heldItem(讀取) | 可用 | tap |
bot.entity 的位置 / 速度 / 偏航角 / 俯仰角 / onGround | 可用,來自回顯的 player_auth_input(落後 1-2 tick) | tap |
setControlState、getControlState、clearControlStates | 可用 | input(虛擬 W/A/S/D/SPACE/SHIFT/CTRL 鍵) |
| mineflayer-pathfinder、collectblock、pvp | 可用,通過控制狀態、視角和攻擊實現 | input、look |
look、lookAt | 可用;回顯收斂(< 0.5°)時完成 | look(閉環 raw 鼠標) |
setQuickBarSlot、裝備(equip)快捷欄中的物品 | 可用 | slot(按鍵 1-9) |
chat、whisper、命令 | 可用,保留 uuid | send(T/SLASH + text + ENTER,丟失 uuid) |
dig、stopDigging | 可用;客戶端上顯示裂紋動畫,在 update_block → air 時完成 | look、button(mouse) |
placeBlock、activateBlock、activateItem、deactivateItem、consume、弓 | 可用(先轉向,再使用) | look、button |
attack、activateEntity、mount、dismount | 可用 | look、button、input |
用 toss 丟出手持物品 | 可用 | action(drop / dropAll) |
openContainer、openChest、openFurnace、closeWindow | 可用(關閉 = ESC) | look、button |
clickWindow、moveSlotItem、transfer、deposit、withdraw、putAway、craft、從主物品欄 / 盔甲欄 / 副手 equip、unequip、tossStack、creative.setInventorySlot、鐵砧 / 附魔臺 / 村民 / 鍛造臺 | 可用,通過客戶端的 ItemStackNetManager | stack(無兜底:ERR_BEDD_UNSUPPORTED) |
writeBook、updateSign、respawn、床界面的睡覺 / 起床 | 不可用(界面層面) | — |
bot.end、quit | 僅斷開附加;客戶端留在原世界 | — |
auth、username、host、port、viewDistance 選項 | 忽略並給出警告(由客戶端決定) | — |
說明:activateItem(true)(副手)會使用主手,因為客戶端沒有副手使用鍵;對不需要按住使用的物品(投擲物、釣魚竿)調用
activateItem 相當於單擊一次;bot.respawn() 不做任何事並給出警告(由用戶點擊重生,因此 respawn: true 永遠不會從生命值監聽器中
拋出);bot.craft 保留了上游的 new Error(err) 包裝,因此在界面層沒有先拒絕的情況下,請檢查那裡的 err.message。
降級之處:pathfinder 會感受到 1-2 tick 的延遲(預測會被回顯覆蓋);點擊命中什麼由客戶端自己的射線檢測決定,因此操作可能落在相鄰
的方塊或實體上(bedboo 會通過 update_block / 實體事件看到);飛行通過雙擊跳躍實現;打開界面時輸入暫停;後附加依賴加入日誌
(complete:false → 缺失的區塊要重新進入才會出現);客戶端切換世界會結束機器人(LINK_DOWN)。
單人遊戲與局域網世界
開啟 tapLoopback(tap 開啟後默認即開啟)時,BeDD 還會監聽客戶端自己託管的世界:單人遊戲或局域網世界。這些數據包從不經過
網絡,因此 BeDD 會將它們重新序列化(Packet::write,幀標誌 reserialized),並過濾為只與本地玩家相關的內容,這樣局域網訪客的
流量不會混入。支持範圍表中的一切都照常工作;HELLO 標記中為 link.type: 'local'。
安全性
- tap 會暴露整個會話。 tap 客戶端可以讀取已登錄玩家看到和做的一切:聊天、位置、物品欄、世界。tap 管道只接受當前 Windows
用戶的一個本地客戶端(
PIPE_REJECT_REMOTE_CLIENTS,當前用戶 DACL),並且只在tap開啟時存在。 send和stack以該賬號的身份行事。send以已登錄玩家的身份發送聊天和命令,stack移動其物品。兩者都默認關閉 (allowSend、allowStack);send僅限sendAllow中的 ID([9, 77]),login、player_auth_input、物品堆疊等 ID (1、30、144、147)始終被拒絕。- 只在用於自動化的實例中開啟這些功能,並且絕不要讓管理器或遠程工具切換它們。
選項與 bot.bedrock.bedd
createBot({ transport: 'bedd', bedd: { pipe, tapPipe?, connect?, timeoutMs?, modules? } }):
| 選項 | |
|---|---|
bedd.pipe | 控制管道,\\.\pipe\<pipeName>(默認為 $BEDBOO_BEDD_PIPE,否則為 \\.\pipe\BeDD) |
bedd.tapPipe | tap 管道(默認為 <pipe>-tap) |
bedd.connect | (path) => Duplex,用於通過其他方式連接(例如 unix socket) |
bedd.timeoutMs | 控制請求超時(默認 5000 ms;操作自帶的 timeoutMs 會再多給 2 秒) |
bedd.modules | 要附加的 lib/bedd 模塊(默認按以下順序:authority、router、router_actions、follower、surface、inventory) |
bot._bedrock.mode === 'bedd'。bot.bedrock.bedd.caps:{ [op]: 'present' | 'disabled' | 'absent' },涵蓋tap、world、look、input、slot、button、action、send、stack(以及ping應答後的 protocol-1 操作key、text、mouse、raw……)。 沒有控制管道時,所有操作都是absent,機器人只能觀察。bot.bedrock.bedd.supports(name):在當前 caps 下,某個 mineflayer API('dig'、'craft'、'creative.setInventorySlot') 或 BeDD 操作是否可用。bot.bedrock.bedd.observed:最近一次回顯的player_auth_input的{ yaw, pitch, tick },在第一次回顯之前為null。- 錯誤:
BeddUnsupportedError(code: 'ERR_BEDD_UNSUPPORTED'、bedd: true、feature、missing);不支持的數據包還會在bot上發出'bedd_unsupported_packet'{ name, feature },每個名稱只發一次。 - 除常規事件外的客戶端事件:
'serverbound'{ name, params, reserialized }(客戶端發送的內容)、'bedd_marker'(tap 標記) 和'warning'(某個數據包解碼失敗;數據流繼續)。
路線圖
- 駕駛 / 傀儡模式(抑制、注入並鎖定姿態),前提是證明鎖定能在客戶端的狀態校正中保持住。
- 界面層面的操作:重生按鈕、告示牌和書。
- 一個
connect操作,讓 bedboo 可以使客戶端加入指定服務器。 - 第二個分屏子客戶端。