跳到正文
本頁目錄

聊天、命令與 HUD

本頁說明聊天消息、命令、Tab 補全以及 HUD(標題、動作欄、Boss 欄、計分板、聲音、粒子)在 Java 版與 Bedrock 版之間的差異, 以及 bedboo 如何將它們映射到 mineflayer API。觀察環境為 BDS 1.26.51.1(protocol 2193,bedrock-protocol 3.60.1), 下文涉及的每條命令都在實際服務器上做過數據包探測。

聊天消息與文本類型

  • 影響: message、messagestr、chat、whisper、actionBar(位置與渲染)。
  • Java: 玩家聊天(帶簽名)和系統聊天均為 JSON 組件;/tellraw 屬於系統聊天;動作欄是帶 overlay 的系統聊天。
  • Bedrock: 使用 text 數據包:chat / whisper(source_name + § 格式文本)、announcement(/say: "[name] text")、raw / system / tip(§ 文本)、translation / popup / jukebox_popup(%key + 參數)、 json / json_whisper / json_announcement(rawtext JSON)。/tellraw 以 json_whisper 到達;/me 以 chat 到達,source_name 為空,消息為 "* name action";/tell 對目標是 whisper,對發送者是一條 commands.message.display.outgoing 的 command_output。
  • bedboo: 所有文本都轉換為 prismarine-chat 的 ChatMessage(lib/bedrock/text.js):
    • chat → { translate: 'chat.type.text', with: [name, text] }("<name> text");whisper → commands.message.display.incoming("name whispers to you: text");/me → 原樣的消息;
    • %key 和 rawtext 的 translate 通過 registry.language 解析(rawtext 中的字面格式:%%s / %1 佔位符;見 語言格式);
    • 位置:chat / whisper / announcement → chat;raw / system / translation / json / json_whisper(tellraw)/ json_announcement → system;tip / popup / jukebox_popup → game_info(並觸發 actionBar);
    • verified 始終為 null(Bedrock 沒有聊天簽名)。當 bot.players 認識發送者時會傳入其 uuid。

§ 格式代碼

  • 影響: 所有 Bedrock 文本的 ChatMessage 樣式(toMotd、toAnsi、color 等);toString() 不變。
  • Java: §0–§f 顏色,§k §l §m(刪除線)§n(下劃線)§o,§r;顏色代碼會重置格式。
  • Bedrock: 額外的材質顏色 §g §h §i §j §m §n §p §q §s §t §u §v(因此 §m 和 §n 是顏色, 沒有刪除線/下劃線),且顏色代碼不會重置粗體/斜體/亂碼。
  • bedboo: lib/bedrock/text.js 自行解析 § 代碼(不修補 prismarine-chat):材質顏色轉為十六進制顏色 (§g → #DDD605 等),格式在顏色代碼之後保持,§r 重置,未知代碼被丟棄。

語言格式

  • 影響: Bedrock 翻譯鍵對應的每個 ChatMessage 的 toString()。
  • Java: %s / %1$s 格式。
  • Bedrock: en_US 語言文件還使用 %1$d、%d、%.2f 以及裸的 %1。
  • bedboo: bot.registry.language 被規範化為 prismarine-chat 能替換的 %s / %N$s 形式(lib/registry.js), 例如 commands.time.set "Set the time to %1$s"。

默認聊天模式(chat / whisper 事件)

  • 影響: chat、whisper、bot.chatAddPattern、bot.addChatPattern、bot.removeChatPattern。
  • Java: mineflayer 註冊三個已棄用的正則模式(兩種私聊格式和舊版 "<name> text" 聊天格式),當 messagestr 匹配時 觸發 chat / whisper(username、message、translate、jsonMsg)。
  • Bedrock: 玩家聊天、私聊和 /say 公告(source_name: name, message: '[name] text')都在數據包中給出發送者; Bedrock 的玩家代號可以包含空格,(\w+) 無法捕獲。
  • bedboo: 註冊同樣的三個默認模式(名稱和索引相同,可移除,defaultChatPatterns: false 可禁用)。對於帶發送者的 chat / whisper / announcement 數據包,它們直接從數據包取 username 和 message(每個數據包一個事件);公告的消息為 { translate: 'chat.type.announcement', with: [name, text] }("[name] text"),其 chat 事件攜帶該 translate, 與 Java 的 say_command 聊天類型一致。其他所有消息都走上游的正則(例如 /tellraw "<U9G> Hello")。用戶模式始終使用 自己的正則。模式的管理邏輯(repeat、parse、集合、按名稱/編號移除、返回值)沿用上游代碼。

unmatchedMessage

  • 影響: unmatchedMessage 事件。
  • Java: 在 mineflayer 4.39.0 的 index.d.ts 中聲明((stringMsg, jsonMsg)),但其插件從不觸發。
  • Bedrock: 協議層面無差異。
  • bedboo: 對每條未被任何聊天模式匹配的消息觸發(即該聲明事件在 4.x 之前的 mineflayer 中的含義),在 messagestr 之後。

bot.whisper

  • 影響: bot.whisper(username, message)。
  • Java: chatWithHeader('/tell <username> ', message)。
  • Bedrock: /tell <target> <message>(別名 /w、/msg);含空格的目標必須加引號。
  • bedboo: 使用上游的 /tell 前綴(以命令請求發送),玩家名不是普通單詞時加引號;選擇器(@p、 @a[r=5] 等)與上游一樣原樣發送(帶引號的 "@p" 在 BDS 上匹配不到任何目標)。當僅前綴就達到 chatLengthLimit 時, 上游會無限拆分;bedboo 則拋出異常。

命令

  • 影響: bot.chat('/…')。
  • Java: 聊天命令(chat_command 數據包)。
  • Bedrock: command_request { command, origin: { type: 'player', uuid, request_id, player_entity_id }, internal, version } → command_output(回顯 origin uuid)。
  • bedboo: bot.chat('/…') 發送一個帶新 origin uuid 的 command_request(絕不作為聊天消息發送);每一行 command_output 都成為一條 message(位置 system,translate = 其消息 id)。bot._bedrock.commands.request(cmd) (內部)以匹配的輸出 resolve;成功但沒有輸出的命令以空輸出 resolve(無輸出的命令)。

無輸出的命令

  • 影響: bot._bedrock.commands.request(command, { timeout })(內部鉤子)、bot.chat('/…')(發出即不管,行為 不變)。
  • Java: mineflayer 中沒有對應的鉤子。
  • Bedrock: /say、/me、成功的 /tellraw——以及 sendcommandfeedback 遊戲規則關閉時的所有命令——完全沒有 command_output。對於每條成功的命令,BDS 會發送 event { event_type: 'command_executed', event_data: 08 02 00 <len> <name> 00 },若命令有 command_output,則緊挨在它之前(同一批次);失敗的命令從不產生該事件,但總會有 command_output(即使關閉反饋:output_type: 'silent')。
  • bedboo: 該事件與同名命令中最早的請求匹配;若 100 ms 內沒有 command_output 跟隨,請求以 { origin, output_type: 'none', success_count: 1, output: [], has_data: false } resolve。若兩者都未到達,請求仍會在 timeout(10 s)後 reject。

玩家執行 /op

  • 影響: bot.chat('/op …') 以及等待 commands.op.success 的代碼(例如 mineflayer 的示例)。
  • Java: 管理員玩家可以給其他人 op;機器人會看到 "Opped" 聊天消息。
  • Bedrock: 對於 operator 權限級別的玩家,BDS 回覆 commands.generic.error.permissions;/op 需要控制台或更高 的權限級別。BDS 從不在聊天中告知玩家控制台執行的 op;被 op 的玩家只會收到一條宣告此事的 update_abilities。
  • bedboo: 錯誤輸出仍是一條 message。請通過服務器控制台給機器人 op,如有需要,等待 update_abilities (abilities 事件)而不是聊天消息。

bot.tabComplete

  • 影響: bot.tabComplete(str, assumeCommand, sendBlockInSight, timeout)。
  • Java: 由服務器響應的 tab_complete 請求(對最後一個詞給出 brigadier 建議,方塊座標會用到準星所指的方塊)。
  • Bedrock: 沒有 Tab 補全數據包;客戶端根據 available_commands 樹進行補全(枚舉、由 update_soft_enum 更新的 軟枚舉、/execute 的鏈式子命令、命令別名)。
  • bedboo: 在客戶端根據 available_commands 補全(lib/bedrock/commands.js),結果形狀與上游一致 (tabCompleteHasAToolTip → [{ match, tooltip: undefined }]):命令名/別名、枚舉值、軟枚舉、目標參數的玩家名 + 選擇器(@a @e @initiator @p @r @s)、座標的 ~ 形式,並遞歸處理 /execute … run <command>;普通聊天補全在線 玩家名。最多等待 timeout 以獲得 available_commands(超時時與上游一樣 reject)。sendBlockInSight 無效果。結果遵循 Bedrock 的命令集:/weather → clear、query、rain、thunder。

標題

  • 影響: title、title_times、title_clear。
  • Java: set_title_text / set_title_subtitle(JSON 組件)、set_title_time、clear_titles。
  • Bedrock: set_title { type: set_title | set_subtitle | set_title_json | set_subtitle_json | set_durations | clear | reset | action_bar_message(_json), text, fade_in_time, stay_time, fade_out_time }(/title 將該行剩餘部分 作為文本發送,/titleraw 發送 rawtext)。
  • bedboo: set_title / set_subtitle → title(parseTitle(text), 'title'|'subtitle'),使用上游的 parseTitle(因此 /title @a title {"text":"Test Title"} 得到 "Test Title";純文本與上游的原始文本一樣保留 § 代碼);*_json → 渲染為純文本的 rawtext;set_durations → title_times;clear 和 reset → title_clear;動作欄 → actionBar (見下)。

動作欄

  • 影響: actionBar 事件。
  • Java: 帶 overlay 的系統聊天 → message + messagestr(game_info)+ actionBar;/title … actionbar (set_action_bar_text)在 mineflayer 4.39.0 中不觸發任何事件。
  • Bedrock: text 的 tip / popup / jukebox_popup 以及 set_title 的 action_bar_message(_json) 都顯示在動作欄上。
  • bedboo: 它們各自 → game_info 位置的 message + messagestr,然後 actionBar(jsonMsg, null)。

Boss 欄

  • 影響: bot.bossBars、bossBarCreated、bossBarUpdated、bossBarDeleted、BossBar 字段。
  • Java: /bossbar 創建服務器端的欄(uuid、標題、血量、顏色、樣式、標誌);boss_bar 動作用於添加 / 移除 / 更新。
  • Bedrock: 沒有 /bossbar;Boss 欄屬於 Boss 實體(凋靈、末影龍)。boss_event { target_entity_id, type, title, progress, color, overlay }:BDS 在 Boss 出现时发送 show_bar,之後大約每秒再發送一次當前進度;在我們的探測中從未 發送 hide_bar——客戶端隨實體一起丟棄 Boss 欄(死亡動畫後的 remove_entity,或 Boss 離開視野時)。未命名 Boss 的標題 是翻譯鍵(entity.wither.name);命名牌會替換它(末影龍除外)。顏色:pink、blue、red、green、yellow、purple、 rebecca_purple(凋靈)、white。凋靈在和平難度下會消失。
  • bedboo:
    • 每個 Boss 的第一條 show_bar → bossBarCreated;之後改變了某個字段的 show_bar(每秒一次的重複通常不改變, 正如 Java 只發送變化)以及 set_bar_progress / set_bar_title / update_properties / texture → bossBarUpdated; hide_bar、Boss 的 remove_entity 以及維度切換 → bossBarDeleted;
    • entityUUID = Boss 的 unique id(字符串),title 為 ChatMessage(已翻譯),health = progress,dividers 來自 overlay(0、6、10、12、20),color = Bedrock 顏色名(BossBar 子類;已在 index.d.ts 中聲明類型), 已知實體時標誌取自 Boss 類型(凋靈:天空變暗;末影龍:龍欄 + 霧),否則為 0。

計分板

  • 影響: bot.scoreboards、bot.scoreboard、scoreboardCreated、scoreboardDeleted、 scoreboardTitleChanged、scoreUpdated、scoreRemoved、scoreboardPosition。
  • Java: 每個目標都會發送給每個客戶端(scoreboard_objective),分數按實體名記錄,顯示位置 0 list / 1 sidebar / 2 belowName(+ 隊伍側邊欄)。
  • Bedrock: 客戶端只知道正在顯示的目標:set_display_objective { display_slot: list | sidebar | belowname, objective_name, display_name, criteria_name, sort_order }(名稱為空表示清空該位置),然後是帶該目標分數的 set_score;set_score 條目以計分板 id 為鍵(玩家 / 實體:unique id;虛擬玩家:自定義名;remove 條目只攜帶 id); remove_objective。只有 dummy 準則;沒有隊伍側邊欄。
  • bedboo:
    • 目標在首次顯示時出現在 bot.scoreboards 中(scoreboardCreated;title = 純文本顯示名,即使它看起來像 JSON, 例如 "2024");顯示名改變 → scoreboardTitleChanged;scoreboardPosition(position, scoreboard, previous) 使用 Java 的位置編號;清空位置只是將其置空(不觸發事件);
    • 以升序顯示(sort_order 0)的目標,其 items 按從低到高排列,與 Bedrock 客戶端一致(Java 只有降序);
    • 分數:scoreUpdated / scoreRemoved,使用上游的 ScoreBoard 條目;條目名 = 虛擬玩家名、玩家用戶名(自身、 player_list、bot.players)或實體的 unique id;
    • remove_objective → scoreboardDeleted 並清空其佔用的顯示位置。

聲音

  • 影響: soundEffectHeard、hardcodedSoundEffectHeard。
  • Java: sound_effect(註冊表 id 或命名聲音、類別、位置 × 8、音量、音調)。
  • Bedrock: /playsound 使用 play_sound { name, coordinates (× 8), volume, pitch }(BDS 轉發任意名稱,例如 note.harp、gui.button.press);遊戲自身的聲音使用 level_sound_event { sound_id (name, e.g. 'armor.equip_iron'), position, extra_data, entity_type, … },沒有音量和音調。
  • bedboo: play_sound → soundEffectHeard(name, position, volume, pitch);level_sound_event → soundEffectHeard(name, position, 1, pitch)(音調為 1,音符盒則為 Java 的音符音調);無法命名的 id → hardcodedSoundEffectHeard(id, 'master', position, 1, pitch)(Bedrock 沒有聲音類別)。noteHeard 來自方塊事件:見 方塊動作。

粒子

  • 影響: particle 事件、Particle 導出。
  • Java: world_particles(粒子類型、位置、偏移、數量、速度、遠距離渲染);/particle <name> x y z dx dy dz speed count force。
  • Bedrock: 只有 /particle <effect> [x y z] → spawn_particle_effect { dimension, entity_id, position, particle_name, molang_variables }(BDS 转发任意效果名);游戏自身生成的粒子使用 level_event add_particle_<type>(0x4000 | type)。協議中沒有偏移、數量、速度或遠距離標誌。粒子類型 id 從 1 開始。
  • bedboo: Particle(導出和事件)是 mineflayer 的類,擴展了 Bedrock 的 fromNetwork:
    • spawn_particle_effect → id = 效果名;若它是粒子類型名,則通過 registry.particles 解析(bubble → id 1), 否則標識符保留為 id 並同時作為 name(minecraft:heart_particle);
    • level_event add_particle_* → 類型 id 和名稱(0x4000 範圍之外的兩個粒子事件 add_particle_smash_attack_ground_dust / add_particle_creaking_heart_trail 以名稱作為 id);
    • offset (0, 0, 0)、count 1、movementSpeed 0、longDistanceRender false。

沒有隊伍

  • 影響: bot.teams、bot.teamMap、teamCreated、teamRemoved、teamUpdated、teamMemberAdded、 teamMemberRemoved。
  • Java: /team(或 /scoreboard teams)以及 teams 數據包。
  • Bedrock: 完全沒有隊伍:/team 是未知命令,/scoreboard teams 是語法錯誤,沒有隊伍數據包。
  • bedboo: bot.teams = {} 和 bot.teamMap = {} 永遠為空;從不觸發隊伍事件。ScoreBoard 條目的 displayName 退化為純名稱(上游的無隊伍路徑)。

沒有 Tab 列表頁眉 / 頁腳

  • 影響: bot.tablist.header、bot.tablist.footer。
  • Java: playerlist_header 設置 Tab 列表的頁眉和頁腳。
  • Bedrock: 玩家列表沒有頁眉或頁腳(protocol 2193 中沒有此類數據包)。
  • bedboo: bot.tablist = { header, footer } 始終是空的 ChatMessage。