Practical recipes for common bot tasks. Each example shows the Python
reference version and the minecraft_bot_accel equivalent where
they differ.
import asyncio
from minecraft_bot.bot import Bot
async def main():
async with Bot.offline("172.26.160.1", 25565, "ExampleBot") as bot:
print(f"connected as entity {bot.entity_id}")
print(f"spawn position: ({bot.x:.1f}, {bot.y:.1f}, {bot.z:.1f})")
asyncio.run(main())Accel equivalent:
import asyncio
import minecraft_bot_accel as mb
async def main():
bot = mb.Bot.offline("172.26.160.1", 25565, "ExampleBot")
await bot.connect()
try:
eid = await bot.entity_id()
pos = await bot.position()
print(f"connected as entity {eid}")
print(f"spawn position: {pos[:3]}")
finally:
await bot.disconnect()
asyncio.run(main())async with Bot.offline("172.26.160.1", 25565, "Miner") as bot:
await asyncio.sleep(2) # let chunks stream in
blocks = bot.world.find_blocks_nearby(
"minecraft:diamond_ore",
origin=(bot.x, bot.y, bot.z),
radius=32,
limit=8,
)
for x, y, z in blocks:
print(f"diamond at ({x}, {y}, {z})")Accel: identical API.
bot = mb.Bot.offline("172.26.160.1", 25565, "Miner")
await bot.connect()
try:
for _ in range(40):
if bot.loaded_chunk_count() > 20:
break
await asyncio.sleep(0.25)
pos = await bot.position()
blocks = bot.world.find_blocks_nearby(
"minecraft:diamond_ore",
origin=pos[:3],
radius=32,
limit=8,
)
for x, y, z in blocks:
print(f"diamond at ({x}, {y}, {z})")
finally:
await bot.disconnect()Python reference walks via 20 Hz physics tick with auto-jump and auto-step for half-blocks and slabs:
async with Bot.offline("172.26.160.1", 25565, "Walker") as bot:
await bot.walk_to(bot.x + 10, bot.y, bot.z, timeout=30.0)Accel drives motion through the same 20 Hz physics tick the Python reference uses: A* plans the path, the tick applies walk speed, gravity, auto-jump, and per-axis collision against the World cache. The function signature, motion profile, and per-tick Player Position packets match across backends.
bot = mb.Bot.offline("172.26.160.1", 25565, "Walker")
await bot.connect()
try:
pos = await bot.position()
ok = await bot.walk_to(pos[0] + 10, pos[1], pos[2], timeout=30.0)
print(f"arrived: {ok}")
finally:
await bot.disconnect()# Python ref
await bot.drop_held_item() # drop one
await bot.drop_held_item(full_stack=True) # drop the whole stack# Accel
await bot.drop_held_item()
await bot.drop_held_item(full_stack=True)import asyncio
import minecraft_bot
import minecraft_bot_accel as mb
async def main():
bot_py = minecraft_bot.bot.Bot.offline("172.26.160.1", 25565, "PyBot")
bot_ac = mb.Bot.offline("172.26.160.1", 25565, "AcBot")
# Connect in sequence (Paper rate-limits same-IP reconnects).
async with bot_py:
eid_py = bot_py.entity_id
await asyncio.sleep(5) # respect server-side connection throttle
await bot_ac.connect()
try:
eid_ac = await bot_ac.entity_id()
print(f"py-bot eid={eid_py}, accel-bot eid={eid_ac}")
finally:
await bot_ac.disconnect()
asyncio.run(main())The accel Bot does not duplicate the Python reference's 176 typed packet dataclasses. To send a custom serverbound packet, encode it with the Python encoder and forward the bytes:
import minecraft_bot_accel as mb
from minecraft_bot.codec import Writer, varint
from minecraft_bot.protocol.v763.packets.play.serverbound import (
chat_command,
)
bot = mb.Bot.offline("172.26.160.1", 25565, "RawBot")
await bot.connect()
try:
cmd = chat_command.ChatCommand(
command="say hello",
timestamp=int(time.time() * 1000),
salt=0,
argument_signatures=(),
message_count=0,
acknowledged=b"\x00" * 3,
)
w = Writer()
varint.write(cmd.packet_id(), w)
chat_command.encode(cmd, w)
await bot.send_raw(w.bytes())
finally:
await bot.disconnect()import minecraft_bot_accel as mb
bot = mb.Bot.offline("172.26.160.1", 25565, "Inspector")
await bot.connect()
try:
await asyncio.sleep(2)
w = bot.world
print(f"loaded chunks: {w.loaded_chunk_count()}")
pos = await bot.position()
x, y, z = int(pos[0]), int(pos[1]), int(pos[2])
for dy in [-1, 0, 1, 2]:
name = w.get_block_name(x, y + dy, z)
solid = w.is_solid(x, y + dy, z)
print(f" ({x},{y+dy},{z}): {name} solid={solid}")
finally:
await bot.disconnect()Both backends expose a pure-function physics.tick(state, intent, world, *, in_water=False, in_lava=False). Use it to simulate
movement without a connection.
from minecraft_bot.physics import PhysicsState, PhysicsIntent, tick
class FloorWorld:
def is_solid(self, x, y, z):
return y == 0
state = PhysicsState(x=0.5, y=5.0, z=0.5)
intent = PhysicsIntent(dx=1.0, sprint=True)
for _ in range(20):
state = tick(state, intent, FloorWorld())
print(state)Accel batched tick:
from minecraft_bot_accel.physics import PhysicsState, PhysicsIntent, tick_n
from minecraft_bot_accel.world import World
state = PhysicsState(x=0.5, y=5.0, z=0.5)
intent = PhysicsIntent(dx=1.0, sprint=True)
world = World()
# (load chunks into `world` so the tick has a floor to land on)
state = tick_n(state, intent, world, 20)
print(state)from minecraft_bot.pathfinding import find_path
# Synthesise a flat-floor World, find a path from (0, 1, 0) to (10, 1, 0).
path = find_path(world, (0, 1, 0), (10, 1, 0), max_fall=3)
print(f"path of {len(path.nodes)} nodes, cost {path.cost:.2f}")Accel takes the same World object and signature:
from minecraft_bot_accel.pathfinding import find_path
path_nodes = find_path(bot.world, (0, 1, 0), (10, 1, 0), max_fall=3)
# Note: accel returns a list[tuple[int, int, int]] (no Path wrapper)
print(f"path of {len(path_nodes)} nodes")async with Bot.offline("172.26.160.1", 25565, "Listener") as bot:
@bot.on_packet("chat_message")
async def on_chat(pkt):
print(f"saw chat: {pkt}")
await asyncio.sleep(60)Bot.on_packet(packet_id, callback) subscribes to any clientbound
packet by numeric id. The callback receives (packet_id, body)
where body is the raw payload bytes after the id varint. Decode
the body through the Python reference's typed decoders when you
need a structured view.
import asyncio
import minecraft_bot_accel as mb
from minecraft_bot.codec import Reader
from minecraft_bot.protocol.v763.packets.play.clientbound.system_chat import (
decode as decode_system_chat,
)
ID_SYSTEM_CHAT = 0x67 # play / clientbound
async def main():
bot = mb.Bot.offline("172.26.160.1", 25565, "ChatListener")
def on_chat(packet_id, body):
pkt = decode_system_chat(Reader(body))
print(f"chat: {pkt}")
await bot.on_packet(ID_SYSTEM_CHAT, on_chat)
await bot.connect()
try:
await asyncio.sleep(60)
finally:
await bot.disconnect()
asyncio.run(main())Multiple callbacks per id are allowed and fire in registration order.
Callbacks run on the dispatcher task, so launch any long-running
work on a separate asyncio task (asyncio.create_task(...)) to
avoid blocking the loop. Bot.clear_hooks() drops every
registration.