跳到正文
本頁目錄

玩家狀態與生存

死亡與重生、維度切換、經驗、能力、出生點,以及床、釣魚和書這幾項生存交互。觀察環境為 BDS 1.26.51.1(protocol 2193)與 bedrock-protocol 3.60.1。

重生握手

  • 影響: bot.respawn()、respawn 選項、isAlive、death / respawn / spawn 事件。
  • Java: 死亡 = update_health ≤ 0;client_command(執行重生)→ 服務器 respawn 包 → update_health → spawn。
  • Bedrock: 死亡 = 玩家自己的 entity_event death_animation + minecraft:health 屬性為 0(沒有 set_health 0),隨後在 死亡位置收到 respawn state 0(搜索中)。重生是一個三步握手:客戶端 respawn state 2(client_ready;若在服務器的 state 0 之前發送,BDS 會忽略)→ 服務器 respawn state 0 + state 1(就緒,眼睛高度的出生位置)→ 客戶端 player_action respawn → 服務器 entity_event respawn + set_health 20。重生到另一維度時(在下界死亡、在主世界出生),客戶端 state 2 與服務器 state 1 之間會插入一個不帶 loading_screen_id 的 change_dimension;若用 serverbound_loading_screen 回應它,客戶端會被 斷開(unexpected_packet)。
  • bedboo: API 和事件順序與上游相同(health → death;respawn 在服務器的 state 1 時觸發,對應 Java 的 respawn 包; 服務器的生命值更新表明玩家存活後,由生命週期模塊觸發 spawn)。bot.respawn() 每次死亡只發送一次 state 2(必要時等待服務器的 state 0);respawn: false 選項讓機器人停留在死亡界面。對於不帶 loading_screen_id 的 change_dimension,生命週期模塊不發送 加載界面確認,並且在重生過程中完成維度切換而不觸發額外的 spawn:每次死亡只有一次 respawn 和一次 spawn,跨維度也是如此。 加入時和末地出口的 respawn 包不算死亡。重生到另一維度後 spawn 時的位置見出生搜索高度。

創造模式玩家不會死亡

  • 影響: 對創造模式的機器人使用 /kill(或任何傷害);為已死亡的機器人設置遊戲模式。
  • Java: /kill 能殺死創造模式玩家。
  • Bedrock: "Players cannot be killed while they are in Creative mode"(/damage 和虛空也不行),並且不能對已死亡的玩家 設置遊戲模式("No targets matched selector")。
  • bedboo: 庫中無需修改。殺死機器人之前先把它切換到生存或冒險模式;非默認的遊戲模式(例如冒險)在重生後會保留。

維度切換、末地製作人員名單

  • 影響: bot.game.dimension、維度切換時的 respawn / game / spawn 事件、末地出口傳送門。
  • Java: 一個帶有另一維度的 respawn 包(製作人員名單另有 game_state_change win_game,用 client_command 跳過)。
  • Bedrock: change_dimension(/execute in … tp 時為腳部位置;經傳送門時是一個無效位置,隨後由 move_player 重置)→ 客戶端 player_action dimension_change_ack → 服務器 dimension_change_ack → 客戶端帶 loading_screen_id 的 serverbound_loading_screen 1 / 2。經出口傳送門離開末地:BDS 先發送 show_credits {status: 0}(僅在玩家第一次離開末地時), 並一直等待客戶端的 show_credits {status: 1}(不等到就永遠不繼續),然後才發送前往主世界的 change_dimension(respawn: true)。
  • bedboo: 與上游一致:切換時先 game 再 respawn(isAlive 為 false),新維度加載完成後 spawn(isAlive 為 true); 製作人員名單立即跳過(show_credits status 1),與上游的 client_command 一致。站在 portal(下界傳送門,Bedrock 的名字; 生存模式玩家約需 4 s,創造模式約 1.5 s)和 end_portal 方塊中即可通過傳送門旅行。世界如何重置、適用哪些高度: 見維度。

跨維度切換等待 tick

  • 影響: 在循環中用 await bot.waitForTicks(1) 走進傳送門的代碼。
  • Java: 重生到另一維度期間,物理 tick 仍在繼續。
  • Bedrock: 玩家切換維度期間(change_dimension → 維度切換確認 → player_spawn;末地出口還會顯示製作人員名單),bedboo 會暫停物理。
  • bedboo: bot.waitForTicks(1) 會一直等到切換結束,並在 5 s 後以 "Timeout waiting for 1 ticks" 拒絕,即使機器人已經到達。 走進傳送門時,應等待下一個 tick,或 game(維度已切換)、spawn、respawn、death 事件中最先發生的一個,並在新維度中通過 spawn 等待到達(bedboo agent 的 util.tick(bot) 就是這樣做的,且從不拒絕)。

經驗值

  • 影響: bot.experience.points。
  • Java: 服務器發送總經驗值。
  • Bedrock: 只有 update_attributes 中的 minecraft:player.level 和 minecraft:player.experience(經驗條進度)。
  • bedboo: points = 達到當前等級所需的經驗 + 進度 × 下一級所需經驗(Bedrock 與 Java 共用同一條曲線;/xp 10 → 1 級 + 3/9 → 10 點)。無法區分附魔花掉的經驗。

能力

  • 影響: bot.abilities、abilities 事件。
  • Java: 加入時以及每次遊戲模式變化時發送帶標誌位的 abilities 包。
  • Bedrock: 加入時以及權限變化時發送帶能力層的 update_abilities(base、spectator、commands、editor、loading screen: allowed / enabled 集合、飛行 / 行走速度)。執行 /gamemode 時,客戶端自行推導該遊戲模式的能力;BDS 只在飛行狀態變化時發送 update_abilities。BDS 在回應 request_ability 時,以及在改變飛行狀態的遊戲模式變化之後(飛行中 → 生存,進入 / 離開旁觀), 會發送兩次 update_abilities,重複機器人已有的值(在 BDS 1.26.51.1 上測得)。在旁觀模式下,BDS 的能力層會清除 mayFly, 而 flying 仍保持開啟。
  • bedboo: 合併各能力層(每層決定它所允許的標誌;後面的層覆蓋前面的層)。遊戲模式變化時,能力按 Java 服務器的 GameType.updatePlayerAbilities 設置(創造:mayFly、instantBuild、invulnerable;旁觀:再加 flying,沒有 instantBuild; 生存 / 冒險:無),並像 Java 一樣只觸發一次 abilities。沒有任何變化的 update_abilities 不觸發 abilities,並保持 bot.abilities 對象不變(加入時的第一次總會上報)。bot.abilities 是唯一的飛行狀態來源:物理引擎跟隨它,不會回發 request_ability(飛行)。

出生點

  • 影響: bot.spawnPoint。
  • Java: spawn_position = 世界出生點(指南針目標),帶真實高度。
  • Bedrock: start_game.spawn_position(世界出生點;高度未確定時 y = 32767:有人在那裡出生時服務器會搜索最高的安全方塊), 以及 spawn_type 為 world(/setworldspawn)或 player(床、重生錨、/spawnpoint;Java 從不發送)的 set_spawn_position。
  • bedboo: bot.spawnPoint = 世界出生點(來自 start_game,之後是 world 更新 + game);玩家自己的重生點不會改變它。 32767 的高度會在出生點區塊列加載後解析:見出生搜索高度。

床、睡覺與 spawnReset

  • 影響: bot.sleep、bot.wake、sleep / wake 事件、bot.isABed、bot.parseBedMetadata、spawnReset。
  • Java: 16 種顏色的床方塊,帶朝向 / 部位 / 佔用狀態;睡覺 = 使用床;entity_action leave_bed 起床;睡眠狀態是玩家的姿態 元數據;game_state_change no_respawn_block_available。
  • Bedrock:
    • 只有一個 bed 方塊(顏色在方塊實體中;另有 straw_bed),帶 direction(0 南、1 西、2 北、3 東)、head_piece_bit、 occupied_bit。名字以 "bed" 結尾的第一個物品是 straw_bed,而不是床。
    • 睡覺 = 對床進行物品使用 click_block。服務器回應 set_entity_data 的 player_flags 第 1 位 + player_bed_position (床頭),用一次 correct_player_move_prediction 把玩家移到床上(腳在床頂面下方約 0.7,位於床頭方塊中心),並標記床頭的 occupied_bit;創造模式玩家也能睡覺。player_action stop_sleeping 讓玩家起床(animate wake_up + player_flags 0, 並修正到床旁邊)。若沒有人叫醒玩家,BDS 會在 100 tick 後自行結束睡眠(doDaylightCycle 開啟時跳過夜晚;時鐘跳到早晨)。
    • 用 /setblock 放床總是放置整張床:給定位置成為床頭,床尾在其後方(head_piece_bit 被忽略;例如 /setblock <head> bed ["direction"=0]);移除一半會破壞另一半。
    • 當重生用的床 / 重生錨已不存在時,會以 tile.bed.notValid / tile.respawn_anchor.notValid 消息通知;若回退位置就是床出生點 本身的位置,則不會有任何通知。
  • bedboo: isABed 匹配 bed 和 *_bed;parseBedMetadata 根據 Bedrock 狀態返回與上游相同結構的結果;收到上述消息時觸發 spawnReset。sleep() 按上游的順序、使用上游的消息執行上游的檢查(時間 / 雷暴、已在睡覺、不是床、已被佔用、半張床、 canDigBlock 觸及範圍、點擊距離、敵對生物);會等待 activateBlock 完成(Bedrock 上它是異步的);3 s 後報 'bot is not sleeping'。wake() 發送 player_action stop_sleeping 並立即返回,與上游一致。

剛放下的床是"半張床"

  • 影響: 在 bot.placeBlock 放下床之後立即調用 bot.sleep(bed)。
  • Java: 服務器為兩半各發送一次方塊變化;客戶端在能點擊之前就能看到兩半。
  • Bedrock: 床尾和床頭作為兩個獨立的 update_block 到達(在 BDS 1.26.51.1 上觀察到)。
  • bedboo: 在被點擊的格子剛出現床時就調用 bot.sleep(),會以上游的 "there's only half bed" 被拒絕(另一半的 bot.isABed 仍為 false),一個 tick 之後就可以成功。應等待(≤ 20 tick)兩個格子都是床,並在這種拒絕後再試一次 sleep。之後的睡眠行為見 床。

釣魚

  • 影響: bot.fish()。
  • Java: 用 use_item 拋竿 / 收竿;浮漂是一個 fishing_bobber spawn_entity;咬鉤表現為浮漂旁邊的 6 個 fishing / bubble 粒子(world_particles),上游據此檢測。
  • Bedrock: 拋竿 / 收竿 = 手持釣竿進行物品使用 click_air。浮漂是 add_entity minecraft:fishing_hook,其 owner_eid 元數據是拋竿者的 unique id。等待期間,魚鉤先發送 entity_event fish_hook_tease(附近有魚),然後是帶 fish_x / fish_z 元數據的 fish_hook_position(一條魚游過來,約 1–3 s);咬鉤是魚鉤上的 entity_event fish_hook_hook。隨後收竿時,漁獲作為一個 飛向玩家的 add_item_entity 掉落(通過 take_item_entity 拾取),外加經驗球,並移除魚鉤(remove_entity)。
    • 實測等待時間(拋竿 → fish_hook_hook,開闊水域,用 /enchant 設置等級):Lure 0 晴天 6.3–32.3 s(均值 20.7,n=10); Lure 0 雨天 6.0–20.9 s(12.1,n=8);Lure III 晴天 2.5–12.7 s(5.9,n=8);Lure III 雨天 1.9–12.2 s(5.7,n=14)。 基礎窗口與 Java 的 100–600 tick(+ 魚游過來的時間)相符,因此 fishingBiteDelayMaxTicks: 600 (特性表)成立;與 Java 一樣,每級 Lure 縮短約 5 s。
    • Bedrock 的 /give 不能攜帶附魔,/enchant 的 Lure 上限為 III(/give @s fishing_rod + /enchant @s lure 3);BDS 不會把 /enchant 的結果告訴創造模式玩家。
  • bedboo: 上游的任務邏輯和消息不變;浮漂是 fish() 之後機器人擁有的第一個 fishing_hook(忽略其他玩家的浮漂;上游會接受任何 浮漂),咬鉤是它上面的 fish_hook_hook。與上游一樣,fish() 本身沒有時間限制。

書

  • 影響: bot.writeBook、bot.signBook。
  • Java: edit_book { slot, pages[], title? } 攜帶整本書,最多 100 頁;頁面是 NBT 字符串(nbt.value.pages.value.value = 頁面文本);服務器回顯被編輯的槽位。
  • Bedrock:
    • 必須先打開書:對手持的 writable_book 進行一次物品使用(click_air)(新書隨後會帶著空的 pages 列表返回);與該使用在 同一 tick 到達服務器的編輯會被丟棄。
    • 編輯逐頁進行:book_edit { inventory_slot: hotbar slot, type: replace_page | add_page | delete_page | swap_pages, page_number, text, photo_name },署名是 book_edit { type: sign, title, author, xuid }。BDS 對編輯不作任何回應;關閉書 (item_release)會讓它重新發送這本書(新的 stack id)。
    • 物品 NBT:pages: [{ text, photoname }](文本要用 pages.value.value.map(p => p.text.value) 讀取,而不是當作字符串列表); 成書另外帶 author、title、xuid(離線時為 '')和 generation 0。18 個字符的標題會被接受。
    • BDS 最多保留 50 頁,其餘的被丟棄。
  • bedboo: 上游的檢查、消息和槽位處理(書被移到快捷欄槽位 0 並手持,之後恢復手持槽位 / 書所在槽位)。一次編輯是一個會話: 打開 → 若干 book_edit(只發送有變化的頁面,多餘的頁面從末尾刪除)→(sign)→ 釋放,以重新發送的書包含所請求的頁面(或成書) 作為確認;未得到確認的會話會以更長的打開延遲重試一次(總計 20 s,與上游的確認超時相同)。用書本身已有的頁面調用 writeBook 不會發送任何內容。超過 50 頁會被立即拒絕(too many pages: a Bedrock book holds at most 50 pages),此時尚未移動任何物品; 編輯失敗時仍會恢復手持槽位並把書放回原處。