聊天、命令與 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。
- chat →
§ 格式代碼
- 影響: 所有 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。
- 每個 Boss 的第一條
計分板
- 影響:
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_order0)的目標,其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_eventadd_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)、count1、movementSpeed0、longDistanceRenderfalse。
- spawn_particle_effect →
沒有隊伍
- 影響:
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。