實體與玩家
本頁說明實體、玩家、玩家列表、戰鬥事件、騎乘以及與實體相關的事件在 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_x21,rot_y64);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。
- name / displayName / type / kind / entityType / width / height 來自
機器人自身的元數據、屬性與效果
- 影響:
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_status6/7/8/10 以及animation0/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_positionactor 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-itemfromNotch);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計算持續時間。助推在物理方面的處理見鞘翅。