跳到正文
本頁目錄

實體與玩家

本頁說明實體、玩家、玩家列表、戰鬥事件、騎乘以及與實體相關的事件在 Java 版與 Bedrock 版之間的差異,以及 bedboo 如何通過 mineflayer API 呈現它們。觀察環境為 BDS 1.26.51.1(protocol 2193,bedrock-protocol 3.60.1),通過協議探測(兩個機器人、 /summon、/querytarget、/ride、/damage、/kill、setblock … destroy)得出。

協議中的實體位置

  • 影響: 除機器人自身外所有實體的 entity.position、entitySpawn、entityMoved。
  • Java: 生成 / 移動 / 傳送數據包攜帶腳部位置(或其增量)。
  • Bedrock(實測):
    • add_player 是腳部高度(站在 y = -59 上的玩家:add_player.position.y = -59,/querytarget 眼睛 -57.38), 但其他玩家的 move_player 是眼睛高度(腳部 + 1.62,潛行時也一樣);
    • add_entity、add_item_entity、move_entity 和 move_entity_delta 是腳部高度加上按類型的偏移:物品 0.125, 點燃的 TNT 和下落的方塊 0.49,船和運輸船 0.375,礦車(所有種類)0.35,所有生物、盔甲架、經驗球、箭、末地水晶 0;
    • move_entity_delta(1.26.40+)攜帶絕對座標,每個座標都可選(缺省 = 不變),旋轉為字節(×360/256:rot_x 俯仰、rot_y 偏航、rot_z 頭部偏航;對盔甲架執行 /tp … 90 30 → rot_x 21,rot_y 64);
    • move_entity.rotation 已經是角度,協議順序相同(俯仰、偏航、頭部偏航——PocketMine / gophertunnel / dragonfly), 儘管 bedrock-protocol 將這三個字節標為 yaw、pitch、head_yaw;在所有探測中 BDS 1.26.51.1 自身只發送了 move_entity_delta(被傳送的生物、盔甲架、礦車、船、箭);
    • Bedrock 客戶端在稀疏的更新(set_entity_motion)之間自行模擬物品,因此物品最後上報的位置可能與其靜止位置相差零點幾格。
  • bedboo: entity.position 始終是腳部位置:每個數據包都會去掉按類型的偏移(lib/plugins/entities.js 中的 POSITION_OFFSETS)和玩家眼高。Yaw / pitch / headYaw 為弧度(mineflayer 的 notchian 轉換);move_entity 中標為 yaw 的字節被讀作俯仰,pitch 被讀作偏航。

實體 id

  • 影響: entity.id、bot.entities 的鍵、所有實體事件。
  • Java: 每個實體一個 int 實體 id;針對未知 id 的數據包會即時創建實體(fetchEntity)。
  • Bedrock: 運行時 id(varint64,大多數數據包)和唯一 id(zigzag64;remove_entity、set_entity_link、 player_list、update_player_game_type;add_player.unique_id 是 li64,protodef 將其讀為 [high, low])。
  • bedboo: entity.id = Number(runtime id);entity.runtimeId / entity.uniqueId 為 BigInt,二者的對應關係記錄在 bot._bedrock.ids 中。針對從未添加過的運行時 id 的數據包會被忽略,而不是在 (0, 0, 0) 創建空實體。維度切換後所有其他 實體都會被丟棄(每個觸發 entityGone),與 Java 客戶端丟棄舊世界一致。

實體名稱、類型與元數據

  • 影響: entity.name、displayName、type、kind、entityType、entity.metadata、entity.uuid、 entity.getCustomName()。
  • Java: 註冊表名稱/id,元數據按數字索引,每個實體都有 UUID。
  • Bedrock: 標識符如 minecraft:villager_v2、minecraft:xp_orb;元數據鍵是名稱(flags、nametag、variant 等);協議中只有玩家有 UUID。
  • bedboo:
    • name / displayName / type / kind / entityType / width / height 來自 registry.entitiesByName(Bedrock 名稱,來自 Bedrock 數據;類型 hostile、animal、passive、ambient、mob、living、projectile、 other、player 與新版 Java 一致;未知標識符 → 類型 other,name/displayName 為 unknown,entityType = 該標識符);
    • entity.metadata[<Bedrock key>](元數據數組上的命名屬性,按數據包合併);
    • 只有玩家會設置 entity.uuid;
    • getCustomName() 讀取 nametag 鍵('' = 無)——這是對 prismarine-entity 的補丁;
    • 狐狸等 Bedrock 生物與玩家使用同一個潛行標誌:它們也會觸發 entityCrouch / entityUncrouch,但只有玩家會使用潛行 碰撞箱(高 1.5,眼睛在 1.27);
    • 額外字段:entity.health(生物的當前生命值,來自 minecraft:health)、經驗球的 entity.count (experience_value)、entity.sleeping。

機器人自身的元數據、屬性與效果

  • 影響: bot.entity.metadata、bot.entity.attributes、bot.entity.effects、entityUpdate、 entityAttributes、entityEffect / entityEffectEnd、entityCrouch / entityUncrouch、entityElytraFlew、 entitySleep / entityWake。
  • Java: 元數據按數字索引;屬性值為基礎值 + 修飾符。
  • Bedrock: 元數據鍵是名稱(flags、flags_extended、air、nametag 等);update_attributes 發送當前值 (已應用修飾符)以及 min/max/default;效果使用 Bedrock id。
  • bedboo:
    • bot.entity.metadata[<name>](prismarine-entity 元數據數組上的命名屬性);標誌驅動 crouching、sprinting、 swimming、onFire、elytraFlying 以及睡眠事件;
    • 屬性以 Java 資源名為鍵(來自 Bedrock 數據),value 是由 current 和修飾符反推出的基礎值(minecraft:health → minecraft:max_health = 其最大值),另有 current、min、max、default;Bedrock 獨有的屬性保留 Bedrock 名稱;
    • 效果:bot.entity.effects[<Bedrock id>] = { id, amplifier, duration };
    • set_health 設置 bot.entity.health。

機器人自身的玩家記錄

  • 影響: bot.player、bot.players[bot.username]。
  • Java: 來自 player_info(皮膚紋理、延遲、遊戲模式)。
  • Bedrock: player_list(在 start_game 之前),帶原始皮膚圖像,沒有延遲。
  • bedboo: { username, uuid, displayName, gamemode, ping: 0, entity, skinData: undefined }。其他玩家見 玩家列表。

玩家列表

  • 影響: bot.players、bot.player、bot.uuidToUsername、playerJoined、playerUpdated、playerLeft、 player.ping、player.gamemode。
  • Java: player_info 的 add / update_game_mode / update_latency / update_display_name / remove。
  • Bedrock: player_list 只有 add / remove——已在線的玩家在 start_game 之前到達,數據包的最後一條記錄可能被 截斷(maybeIncompleteArray);沒有延遲;遊戲模式變化以 update_player_game_type { gamemode, player_unique_id } 到達(BDS 發給每個玩家);重新發送的記錄(機器人自身加入後的完整列表)視為更新。
  • bedboo:
    • 在 start_game 之前收到的記錄在其重置之後應用(上游在登錄時重置列表),且在該次登錄的 login 和 game 事件處理 完之後(上游的順序:player_info 跟在登錄數據包之後,因此 bot.game 已設置)——每條都觸發 playerJoined,包括機器人 自己;
    • 被截斷的記錄被忽略;ping 為 0;
    • gamemode 從世界默認值開始(機器人:其 start_game 模式),並跟隨 update_player_game_type(playerUpdated); playerUpdated 從不因延遲 / 顯示名而觸發。

顯示名

  • 影響: player.displayName。
  • Java: player_info 攜帶可選的顯示名(隊伍前綴、update_display_name)。
  • Bedrock: player_list 沒有顯示名;名稱標籤屬於實體元數據。
  • bedboo: player.displayName 始終是用戶名(一個 ChatMessage,與上游默認值相同)。

皮膚

  • 影響: player.skinData。
  • Java: textures 屬性(base64 JSON 或 mojangson)→ { url, model, capeUrl }。
  • Bedrock: player_list 攜帶原始皮膚圖像(RGBA 緩衝區、幾何 JSON),沒有紋理 URL。
  • bedboo: 所有玩家的 skinData 都是 undefined;格式錯誤或被截斷的皮膚記錄不會拋出異常。

受傷與死亡

  • 影響: entityHurt、entityDead。
  • Java: 每次傷害都有 damage_event(1.20+;帶來源實體),死亡為 entity_status 3。
  • Bedrock: 非致命傷害為 entity_event hurt_animation(data = 傷害原因,沒有來源實體);致命一擊(以及 /kill) 只發送 death_animation。
  • bedboo: hurt_animation → entityHurt(entity)(沒有 source 參數:Bedrock 不告知是誰造成的傷害;見 誰打了誰);death_animation → 為致命一擊觸發 entityHurt(entity)(除非同一數據包批次,即同一服務器 tick 中已有對應的 hurt_animation——批次在 bedrock-protocol 的批次入口處計數,而不是按事件循環輪次,因此連續讀取的批次 仍會分開),然後 entityDead(entity),與 Java 的 damage_event + status 順序一致。本地玩家同樣會收到這兩個事件。

誰打了誰:entityHurt 沒有來源

  • 影響: 需要知道是否是自己的攻擊殺死了生物的戰鬥代碼(例如 @bedboo/agent 的戰鬥庫)。
  • Java: damage_event 攜帶來源實體(新版 mineflayer 中為 entityHurt(entity, source))。
  • Bedrock: entity_event hurt_animation / death_animation 不攜帶攻擊者(見受傷與死亡)。
  • bedboo: 事件不變。@bedboo/agent 的戰鬥庫在以下情況下把擊殺歸於機器人:目標的 entityDead 發生在機器人自身某次 attack() 之後 1.5 s 內(其箭矢則為 3 s 內),之前至少有一次 entityHurt,且周圍沒有其他傷害來源。

Bedrock 上的戰鬥

  • 影響: bot.attack、bot.activateItem / deactivateItem(弓、盾牌)、mineflayer-pvp 式的戰鬥。
  • Java: 自 1.9 起攻擊冷卻會按比例降低快速攻擊的傷害;舉盾是一次物品使用。
  • Bedrock: 沒有攻擊冷卻(每次攻擊都是滿傷害),但受傷的生物在 10 tick 內忽略傷害;玩家潛行時盾牌格擋;箭永遠傷不到 末影人(它們會傳送走);/summon slime … minecraft:spawn_large 只設置碰撞箱——分裂數量取決於體型變種(1、2 或 4)。
  • bedboo: API 不變(手持盾牌時 activateItem 會潛行:見物品使用和 物品使用減速)。@bedboo/agent 的戰鬥庫每 10 tick 攻擊一次,且從不射擊末影人。

實體事件

  • 影響: entityTaming、entityTamed、entityShakingOffWater、entityEatingGrass、entityEat、 entitySwingArm、entityWake、entityCriticalEffect、entityMagicCriticalEffect。
  • Java: entity_status 6/7/8/10 以及 animation 0/2/3/4/5。
  • Bedrock: entity_event 的 tame_fail / tame_success / shake_wet / eat_grass_animation / eating_item / arm_swing(生物攻擊),以及 animate 的 swing_arm / wake_up / critical_hit / magic_critical_hit。
  • bedboo: 一一對應。entityEat 來自 eating_item,BDS 在動物進食時發送(喂骨頭的狼)——上游的 entityEat (animation 3)在新版 Java 上同樣從不觸發。與 Java 一樣,機器人自身的揮手不會回顯為 entitySwingArm。entityWake 每次醒來只觸發一次(元數據或動畫)。

交換主副手

  • 影響: entityHandSwap。
  • Java: 玩家交換主手和副手時為 entity_status 55。
  • Bedrock: 沒有這樣的事件;交換表現為 mob_equipment 的變化。
  • bedboo: entityHandSwap 從不觸發;entityEquip 報告新的裝備。

睡覺的玩家

  • 影響: entitySleep、entityWake、entity.sleeping。
  • Java: 元數據 pose = sleeping;醒來時 animation 2。
  • Bedrock(實測): 睡覺的玩傢俱有 player_flags 第 1 位(值 2)和 player_bed_position;對玩家而言, flags_extended 的 "sleeping" 位(bedrock-protocol 的命名)保持清零。其他實體:flags_extended。
  • bedboo: 對玩家依據 player_flags 的變化、對其他實體依據 flags_extended.sleeping 的變化觸發 entitySleep / entityWake(不含該鍵的更新不改變任何東西)。機器人自身在見到一次 player_flags 後也會跟隨它 (lib/bedrock/entity_data.js)。

揮動手臂

  • 影響: bot.swingArm(arm, showHand)。
  • Java: 帶手(主手 / 副手)的 arm_animation,1.8 上不帶手。
  • Bedrock: 只有一個 animate swing_arm(沒有副手揮動動畫,也沒有隱藏揮動);1.21.130+ 增加了可選的揮動來源。
  • bedboo: swingArm() 對兩隻手都發送 animate swing_arm;接受 arm / showHand 但忽略它們。attack 與原版 客戶端一樣以來源 attack 揮手。

攻擊與使用實體

  • 影響: bot.attack、bot.useOn、bot.mount、bot.dismount。
  • Java: use_entity(攻擊 / 交互)或 1.21.2+ 的 attack 數據包;用跳躍輸入下坐騎。
  • Bedrock: inventory_transaction item_use_on_entity(攻擊 / 交互),攜帶確切的手持物品和玩家位置;原版客戶端會先 懸停實體(interact mouse_over_entity);下坐騎是 interact leave_vehicle。
  • bedboo:
    • 與上游一樣不改變機器人的視角(無論玩家朝向哪裡,BDS 都接受攻擊和交互,已實測驗證:攻擊機器人身後的殭屍、騎上身後的船);
    • 目標變化時機器人先懸停目標,然後發送交易(click_pos 相對於目標腳部;手持物品來自 bot._bedrock.heldNetworkItem());attack 先揮手(原版順序);
    • 數據包經由 bot._bedrock.physics.afterControlsSent 發送:立即發送,或者——當潛行 / 疾跑變化尚未包含在已發送的 player_auth_input 中時——緊跟在下一個輸入之後(上游在 setControlState 中同步發送 entity_action;見 點擊前的潛行 / 疾跑);
    • 同步 API 和返回值與上游相同。沒有坐騎時 dismount() 與上游一樣觸發 error。

載具

  • 影響: bot.vehicle、entity.vehicle、entity.passengers、mount、dismount、entityAttach、 entityDetach、bot.moveVehicle。
  • Java: attach_entity / set_passengers。
  • Bedrock: set_entity_link { ridden_entity_id, rider_entity_id (unique ids), type: 0 remove, 1 rider, 2 passenger },对于生成时就在骑乘的实体,也出现在 add_entity.links / add_player.links 中。
  • bedboo: 鏈接更新 vehicle / passengers 並觸發 entityAttach(passenger, vehicle) / entityDetach(passenger, vehicle);對機器人則為 bot.vehicle + mount / dismount(vehicle)。重複的鏈接被忽略。 當機器人所乘的載具被移除時觸發 dismount(vehicle)(上游把該處理器註冊在協議客戶端上,而那裡從不觸發 entityGone—— bedboo 實現了其本意)。moveVehicle 通過每 tick 的輸入(bot._bedrock.input.setVehicle)駕駛載具,屬於物理插件:見 載具和騎乘控制。

下船或下礦車

  • 影響: bot.dismount()、dismount / forcedMove 事件、騎乘結束後的 bot.entity.position。
  • Java: 服務器計算下坐騎位置(DismountHelper:載具周圍的空位,否則在其頂部)並把騎乘者傳送過去。
  • Bedrock: 騎乘者離開船或礦車時 BDS 不發送傳送(馬的騎乘者可能收到一次校正)。騎乘者坐在載具的座位上 (rider_seat_position,在載具協議位置上方 1.02,眼睛高度),這使得在鐵軌上的礦車下方其腳部陷入方塊 0.1,在陸地上的 船下方陷入地面 0.225。BDS 自己會把它那份騎乘者直接向上抬出該方塊(實測:客戶端上報其他位置時,會被校正到座位 x/z、 方塊頂部)。
  • bedboo: 與 BDS 一致:在 dismount 時把騎乘者從座位向上抬,直到其碰撞箱不受阻擋(座位本就空閒時——水上的船——保持 不動);該移動像傳送一樣觸發(forcedMove),並隨下一個輸入發出,因此服務器的位置與機器人一致,機器人可以走開(不會被 埋在下方一格)。

多次騎乘之間的座位

  • 影響: 騎乘時的 bot.entity.position。
  • Java: 客戶端自己不移動乘客(mineflayer 將位置保持在上坐騎的位置)。
  • Bedrock: 騎乘者的位置就是其載具的座位。BDS 只在 rider_seat_position(actor data)變化時發送它:加入時的 actor data 為 (0, 0, 0),第一次乘船或礦車時設為 (0, 1.02, 0),之後的船和礦車不再發送。
  • bedboo: 在多次騎乘之間保留上一次的座位(船 → 礦車 → 船:騎乘者每次都跟隨其載具);仍未知的座位退回到船 / 礦車的 座位或載具頂部。

騎乘者的位置

  • 影響: bot.vehicle 已設置時的 bot.entity.position 和 move,bot.dismount() 之後的位置。
  • Java: 客戶端模擬載具,騎乘者坐在上面。
  • Bedrock: BDS 根據騎乘者的輸入模擬載具,並把騎乘者保持在載具的座位上:載具位置 + rider_seat_position actor data (在 BDS 1.26.51.1 上實測:船的座位 (0, 1.02, 0) 在船的協議位置之上 = 腳部比船的腳部低 0.225;馬 (0, 2.32, −0.2) = 腳部高 0.7、靠後 0.2)。它每 6 tick 發送一次載具校正,下船時並不總是傳送騎乘者(保留其上報的位置)。
  • bedboo: 騎乘時每個 player_auth_input 都上報該座位(載具的最新位置來自 move_entity 或載具校正,座位按載具的偏航 旋轉),bot.entity.position 跟隨它(載具移動時觸發 move);不預測載具物理。沿 x / z 的座位偏移按載具上報的偏航旋轉: 實測的單人座位沒有這種偏移;雙人船的座位未經驗證。騎乘者保持在座位上,並在船 / 馬旁邊下來。

裝備與護甲屬性

  • 影響: entity.equipment、entity.heldItem、entityEquip、bot.getExplosionDamages(entity, …)。
  • Java: entity_equipment 槽位 0 主手、1 副手、2 腳 … 5 頭、6 身體;護甲 / 護甲韌性是同步的屬性。
  • Bedrock: mob_equipment(窗口 inventory = 主手,offhand)和 mob_armor_equipment { helmet, chestplate, leggings, boots, body };不發送護甲屬性。
  • bedboo: 裝備索引與上游相同(0 手、1 副手、2 靴子、3 護腿、4 胸甲、5 頭盔、6 身體)。生物、玩家和機器人會獲得實時的 generic.armor / generic.armorToughness(上游爆炸插件讀取的屬性)以及 minecraft:armor / minecraft:armor_toughness 屬性,由所穿戴的物品計算得出(每件物品的護甲值和韌性取自 minecraft.wiki;與上游一樣不計 附魔)。非生物實體沒有這些屬性(對它們 getExplosionDamages 返回 null,與上游一致)。

掉落物

  • 影響: entity.getDroppedItem()、itemDrop、playerCollect。
  • Java: 物品堆是物品實體的一個元數據條目;itemDrop 在該元數據上觸發;collect 數據包。
  • Bedrock: add_item_entity 攜帶物品(ItemV4);take_item_entity { runtime_entity_id: the item, target: the collector },然后 remove_entity。相邻的物品堆会合并:在保留的物品上发送 entity_event item_entity_merge { data: the new stack size },然后对被吸收的物品发送 remove_entity(沒有元數據更新)。
  • bedboo: 協議中的物品保存為 entity.metadata.item;prismarine-entity 補丁讓 getDroppedItem() 在 Bedrock 上讀取 它(prismarine-item fromNotch);itemDrop 緊隨物品的 entitySpawn 觸發;合併會設置新數量並觸發 entityUpdate + itemDrop,與 Java 的物品堆元數據更新一致;playerCollect(collector, collected) 觸發時物品仍可讀取。

畫

  • 影響: bot.blockAt(pos, true).painting、mineflayer 的 Painting。
  • Java: spawn_entity_painting(≤ 1.18;標題 / 圖案 id、方塊位置、方向)——1.19+ 的畫是普通實體。
  • Bedrock: add_painting { coordinates (the painting's center), direction 0-3, title }(標題 Kebab、 SkullAndRoses 等)。
  • bedboo: 兩者兼有:bot.entities 中的 painting 實體(entitySpawn / entityGone),以及註冊在世界中的 Painting(id, floored center, name, direction vector);name 是新版 Java 的變種名(kebab、skull_and_roses 等), 方向向量使用上游的表。

煙花助推

  • 影響: usedFirework、bot.fireworkRocketDuration。
  • Java: 火箭的 attached_to_target 元數據指出被助推的玩家。
  • Bedrock: 助推中的火箭是 add_entity minecraft:fireworks_rocket,owner_eid 為 -1,並在元數據鍵 18 中給出被助推 玩家的 unique id(bedrock-protocol 命名為 minecart_has_display,對火箭而言是 long);其物品 NBT 是展示物品(元數據 鍵 16,Fireworks.Flight)。
  • bedboo: 機器人滑翔時,附著於機器人(鍵 18)、由機器人擁有或射出的 fireworks_rocket 計為一次助推:每枚火箭觸發一次 usedFirework(rocketId),並按上游公式根據物品的 Flight 計算持續時間。助推在物理方面的處理見鞘翅。