BDS notes
Behaviour of Bedrock Dedicated Server 1.26.51.1 worth knowing when you run bots against it: what the server prints, what it sends, and when. bedboo handles all of this; the notes help when you read packet logs or script the server console.
Startup and ports
- Readiness line:
[… INFO] Server started., followed by a multi-lineTRANSPORT TYPE ERRORblock whentransport=raknet("Your current connection type is not set to NetherNet … Players will not be able to connect"). It is harmless: RakNet clients connect fine. BDS also logsSigned in to signaling service successfully. A fresh flat world is ready about 1 s after the process starts. - A busy port prints
ERROR] Port [<port>] may be in use by another process. Free up port and re-run program …, thenExiting programand a crash dump; the server exits within a second. - NetherNet: BDS opens its signalling listener on TCP
server-portand logsAccepting clients on [::]:<port>. When that TCP port is still held (for exampleTIME_WAITconnections of a previous server, about a minute) it runs without the listener and logs nothing; clients then getECONNREFUSED. - Pings: with
enable-lan-visibility=falseBDS does not answer the unconnected ping, so bedboo defaults toskipPing: true.
Transports and backends
- RakNet through raknet-native works (join ≈0.3 s,
start_game≈0.5 s,spawn≈1.0 s). raknet-native 1.2.3 bundles x64 prebuilds only (linux-5-x64,darwin-21-x64,win32-10-x64) and its source build is disabled, so arm64 hosts (Apple Silicon, linux-arm64) have no RakNet backend. The workspace patch makes the binding find the bundled prebuild on newer kernels (linux-6); the prebuild needs glibc ≥ 2.34. raknetBackend: 'jsp-raknet'fails: BDS answers the open-connection request withID_INCOMPATIBLE_PROTOCOL_VERSION(server RakNet protocol 11; jsp-raknet speaks 10).- NetherNet with HTTP signalling on the server port works (join ≈1.7 s, spawn ≈2.6 s). The HTTP signalling of bedrock-protocol and node-nethernet is backported in the workspace patches.
Join sequence
start_game.player_positionis(0.5, 32769.62, 0.5)(the spawn search height), then threerespawnpackets: state 0 at 32769.62, state 0 at 32768, state 1 at the real eye-level spawn ((0.5, -58.38, 0.5)on a flat world, feet y = -60). The client answers state 1 withrespawn { state: 2, runtime_entity_id }. Then chunks andplay_status player_spawn.- Loading screen gate: after spawning, BDS does not simulate the player (
player_auth_inputpositions and move vectors are ignored, nocorrect_player_move_prediction) until the client sendsserverbound_loading_screen { type: 1 }and{ type: 2 }. After that, walking inputs move the player and impossible moves are corrected. start_game:rewind_history_size = 40,server_authoritative_block_breaking = true,server_authoritative_inventory = true,block_network_ids_are_hashes = true;player_gamemodeisfallback, soworld_gamemodeholds the game mode. Defaultserver.properties:server-authoritative-movement-strict=false,player-position-acceptance-threshold=0.5.player_listarrives asrecords: [{ type: 'add', username, … }], before the player is spawned or targetable.
Chunks and saving
level_chunkalways arrives in sub-chunk request mode (sub_chunk_count: 0withhighest_subchunk_countpresent), never with inline sub-chunks.subchunk_request { dimension, origin, requests: [{ x: 0, y: -4..19, z: 0 }] }returns onesubchunkwith an entry per request (successwith payload, orsuccess_all_air).network_chunk_publisher_updateradius 64 → 160 blocks afterrequest_chunk_radius 10.- With no player nearby, chunks are not loaded:
setblock/testforblockanswerCannot place block outside of the world. - Modified chunks reach LevelDB only every 5–10 s, and
save holddoes not flush them, so an online backup can miss recent changes. A graceful stop saves everything.
Console commands
say/tellrawprint nothing on the console; command errors areERRORlines (Unknown command: <cmd>. Please check that the command exists …,No targets matched selector,Syntax error: …).listprintsThere are n/max players online:plus a line of names;querytargetprints a JSON block (eye-levely);gamerule(no arguments) prints all rules on one line;testforblockprintsSuccessfully found the block at x,y,z./The block at x,y,z is Air (expected: …).gamemode <m> <player>sendsupdate_player_game_type { gamemode, player_unique_id }(notset_player_game_type); nothing is sent when the player already has that mode. Game mode commands do not reach dead players (No targets matched selector).tp <p> 10 -60 10centres integer x/z (Teleported p to 10.50, -60.00, 10.50) and sendsmove_player { mode: 'teleport', teleport: { cause: 'command' } }at eye level.setblockprintsBlock placedand sendsupdate_block; the same block again printsThe block couldn't be placedand sends nothing.summonprintsObject successfully summonedand sendsadd_entity(feet position, centred);kill @e[type=pig]printsKilled Pigand sendsentity_event death_animation, the drops (add_item_entity), thenremove_entity.- Creative players cannot be killed (
Players cannot be killed while they are in Creative mode.), not even by/damage … voidor the void.
Packets worth knowing
- Commands from the client:
command_request { command, origin: { type: 'player', uuid, request_id: '' }, … }is answered bycommand_outputwhose origin echoes the uuid (notrequest_id), plus anevent { event_type: 'command_executed' }. - Chat: a client
textchat (type: 'chat',category: 'authored') is echoed to everyone withsource_name: '<name>§r'. - Inventory:
/give,/replaceitem(hotbar / inventory) and/clear(even when nothing is cleared) sendinventory_contentof every window (inventory 36, armor 5, ui 54, off-hand 1); an armorreplaceitemsendsinventory_slot;/givealso sends aninventory_transaction. Player items carrystack_ids. - Inventory resend: an
inventory_transaction { transaction_type: 'inventory_mismatch' }makes BDS resend the player's inventory (inventory_content× 4 +player_hotbar); a rejected item stack request or reopening the inventory screen resends nothing. - Death: own
entity_event death_animation,death_info,text(death.attack.generic),respawnstate 0 at the death position. Respawn: clientrespawnstate 2 → serverrespawnstate 0 (y 32767) + state 1 (eye-level spawn) → clientplayer_action respawn→entity_event respawn+set_health 20. - Time: there is no
set_timepacket, not even for/time set; time travels insync_world_clocks. - Falling blocks: a block starting to fall and a falling block landing come as
update_block_syncedonly, never asupdate_block(falling blocks). - Mobs: a flat world spawns passive mobs continuously: hundreds of
move_entity_deltaper minute.