Available Events
Events that can be handled with the @on decorator.
Usage
@on("event_name")
def handler(param1, param2):
# Handle event
pass
Event List
chat_message
Fired when a chat message is received.
Parameters:
chat_data(dict) - Dictionary containing chat message details with the following keys:sender(str) - Player who sent the message or "SYSTEM" for system messagescontent(str) - Message contenttype(str) - Message type:"PLAYER_CHAT"or"SYSTEM_MESSAGE"timestamp(int) - Unix timestamp in millisecondsis_signed(bool) - Whether the message was signedbot_name(str) - Which bot received the messagesender_uuid(str, optional) - Player UUID (present for PLAYER_CHAT, absent for SYSTEM_MESSAGE)minecraft_chat_type(str, optional) - Minecraft chat type (only for PLAYER_CHAT), one of:"CHAT"- Normal player chat"MSG_COMMAND_INCOMING"- Received whisper"MSG_COMMAND_OUTGOING"- Sent whisper"EMOTE_COMMAND"- /me command"SAY_COMMAND"- /say command"TEAM_MSG_COMMAND_INCOMING"- Received team message"TEAM_MSG_COMMAND_OUTGOING"- Sent team message"UNKNOWN"- Unknown chat type
This event is also delivered to global scripts, which coordinate multiple
bots; use bot_name to tell which bot received the message.
@on("chat_message")
def handle_chat(chat_data):
sender = chat_data["sender"]
message = chat_data["content"]
msg_type = chat_data["type"]
if message == "!help":
bot.chat("Available commands: !help, !goto")
# Check if it's a whisper
if chat_data.get("minecraft_chat_type") == "MSG_COMMAND_INCOMING":
utils.log(f"Received whisper from {sender}: {message}")
health_change
Fired when bot health changes.
Parameters:
old_health(float) - Previous healthnew_health(float) - New health
@on("health_change")
def health_monitor(old_health, new_health):
if new_health < 10:
utils.log("Low health warning!")
plugin_message
Fired when a client plugin sends a message (PluginContext.sendMessage), and when a plugin fails (channel mcbot:failed). Global scripts get it too.
Parameters:
message(dict) -bot_name,plugin,channel,data(the payload decoded from JSON) andpayload(the raw JSON)
@on("plugin_message")
def on_plugin(message):
if message["channel"] == "mcbot:failed":
utils.log("%s's plugin %s failed: %s" % (message["bot_name"], message["plugin"], message["data"]["error"]))
hunger_change
Fired when bot hunger changes.
Parameters:
old_hunger(float) - Previous hungernew_hunger(float) - New hunger
@on("hunger_change")
def hunger_monitor(old_hunger, new_hunger):
if new_hunger < 6:
utils.log("Low hunger!")
player_state
Fired when player state updates.
Parameters:
state(dict) - Player state information
@on("player_state")
def state_update(state):
utils.log(f"State: {state}")
inventory_update
Fired when inventory is updated.
Parameters:
selected_slot(int) - Currently selected hotbar slot (0-8)inventory(list) - List of inventory items, each item is a dict with keys:slot,item_id,count,display_name,enchantments. Empty slots are omitted. The full inventory is always passed, even though the client sends updates as deltas.
@on("inventory_update")
def inv_update(selected_slot, inventory):
utils.log(f"Inventory: {len(inventory)} items, slot {selected_slot}")
for item in inventory:
utils.log(f" {item['display_name']} x{item['count']} in slot {item['slot']}")
screen_updated
Fired when the current GUI screen changes or its state is refreshed (e.g. after a button click or key press).
Parameters:
screen(ScreenStateorNone) - Full current screen state, orNoneif no screen is open (back in-game)
@on("screen_updated")
def on_screen_update(screen):
if screen is None:
utils.log("Back in-game")
elif "DeathScreen" in screen.screen_class:
bot.chat("I died!")
else:
utils.log(f"Screen: {screen.title or screen.screen_class}, {len(screen.widgets)} widgets")
container_update
Fired when an open container's contents are synced (chest, furnace, crafting table, etc.). Not fired when the container closes.
Parameters:
container(dict) - Container state with keys:id(int) - Container/window IDtype(int) - Menu type IDitems(list) - Items in the container, each a dict with keysslot,item_id,count,damage,max_damage,display_name,enchantmentsx,y,z(int, optional) - Block position, present only for containers with a world positionproperties(dict, optional) - Menu properties (e.g. furnace burn/cook progress), present only when non-empty
Slot numbering covers the whole open menu: container slots first, then the player's main inventory and hotbar (for a single chest: 0-26 chest, 27-53 player main, 54-62 hotbar).
@on("container_update")
def on_container(container):
utils.log(f"Container {container['id']} has {len(container['items'])} slots")
for item in container['items']:
if item['item_id'] != "minecraft:air":
utils.log(f" slot {item['slot']}: {item['item_id']} x{item['count']}")
block_update
Fired when a single block changes.
Parameters:
x(int) - Block X coordinatey(int) - Block Y coordinatez(int) - Block Z coordinateblock_id(str) - New block state string (e.g."minecraft:oak_log[axis=y]")
@on("block_update")
def on_block(x, y, z, block_id):
if "chest" in block_id:
utils.log(f"Chest placed at ({x}, {y}, {z})")
multi_block_update
Fired when several blocks in one chunk section change at once. Only the number of changed blocks is passed; the world data is already
updated, so query positions with world.get_block.
Parameters:
count(int) - Number of blocks that changed
@on("multi_block_update")
def on_multi_block(count):
utils.log(f"{count} blocks changed at once")
chunk_loaded
Fired when a chunk is received from the server and added to the world data.
Parameters:
chunk_x(int) - Chunk X coordinate (block X >> 4)chunk_z(int) - Chunk Z coordinate (block Z >> 4)dimension(str) - Dimension the chunk belongs to (e.g."minecraft:overworld")
@on("chunk_loaded")
def on_chunk(chunk_x, chunk_z, dimension):
utils.log(f"Loaded chunk ({chunk_x}, {chunk_z}) in {dimension}")
chunk_unloaded
Fired when a chunk leaves render distance and is dropped from the world data. Blocks
in that chunk are no longer readable from memory (world.get_block(..., use_disk=True)
can still read them if world saving is on).
Parameters:
chunk_x(int) - Chunk X coordinatechunk_z(int) - Chunk Z coordinate
@on("chunk_unloaded")
def on_chunk_unload(chunk_x, chunk_z):
utils.log(f"Unloaded chunk ({chunk_x}, {chunk_z})")
baritone_status_update
Fired when baritone pathfinding status changes.
Parameters:
status(dict) - Baritone status information with keys:is_pathing(bool) - Whether currently pathfindingis_calculating(bool) - Whether a path calculation is runningevent_type(PathEventType) - Path event type (seebaritone.PathEventTypeenum)goal_description(str, optional) - Description of current goalactive_process(dict, optional) - Active process infoestimated_ticks_to_goal(float, optional) - ETA in ticksticks_remaining_in_segment(float, optional) - Ticks remaining in segment
is_pathing false does not mean stopped
is_pathing is false for the whole of a path calculation - Baritone drops its current path the instant a segment ends - so a bot waiting on the next segment of a long path reads exactly like a bot whose path failed. Check is_calculating before treating is_pathing false as a stop.
from baritone import PathEventType
@on("baritone_status_update")
def on_baritone_update(status):
if status['is_pathing']:
if 'estimated_ticks_to_goal' in status:
seconds = status['estimated_ticks_to_goal'] / 20.0
utils.log(f"Pathfinding - ETA: {seconds:.1f}s")
# Check if reached goal
if status['event_type'] == PathEventType.AT_GOAL:
utils.log("Reached destination!")
elif status['event_type'] == PathEventType.CALC_FAILED:
utils.log("Pathfinding failed!")
baritone_log
Fired when Baritone logs a message on the client (chat log lines, toasts, desktop
notifications). Baritone writes this output directly to the local chat HUD without any
network packet, so it does not appear in chat_message events.
Parameters:
log(dict) - Log message details with keys:content(str) - Plain message text, with the[Baritone]prefix strippedkind(str) - Where Baritone sent the message:"chat","toast"or"notification"is_error(bool) - Whether Baritone flagged the message as an error ("notification"kind only)title(str, optional) - Toast title ("toast"kind, only when Baritone used a custom title)bot_name(str) - Which bot's Baritone emitted the message
This event is also delivered to global scripts, which coordinate multiple
bots; use bot_name to tell whose Baritone spoke.
- timestamp (int) - Unix timestamp in milliseconds
@on("baritone_log")
def on_baritone_log(log):
utils.log(f"Baritone: {log['content']}")
# React to output that has no structured event
if log['content'].startswith("Unable to find a path"):
utils.log("Pathfinding gave up, trying a different goal")
hotkey_pressed
Fired when a key the bot was told to watch goes down in game. The keys are chosen from a
script with bot.set_hotkeys.
Only the focused game reports a press, so the same key can be watched on every bot and still
act on the one being played. By default a press while a screen is open (chat, inventory, the
pause menu) is not reported; in_screens=True lifts that.
This event is also delivered to global scripts.
Parameters:
key(dict) - Press details with keys:id(str) - The watch's id, as given tobot.set_hotkeyskey(int) - Theworld.Keycode that matchedmodifiers(int) - Theworld.KeyModbitmask the watch asked forbot_name(str) - Which bot's game the key was pressed in
Presses are reported on the edge, once per press, never repeated while the key is held. A press shorter than one game tick (50 ms) can be missed.
bot.set_hotkeys({"pull": world.Key.G,
"stash": (world.Key.K, world.KeyMod.CONTROL)}, bot_name="MyAccount")
@on("hotkey_pressed")
def on_hotkey(key):
if key["id"] == "pull":
world.interact_block(100, 64, 200, bot_name="StasisBot")
script_message
Fired when another script sends this script a message via
comms.emit or
comms.send. This event is also
delivered to global scripts. Registering the handler makes the script
reachable by comms.send; broadcasts additionally require a
comms.subscribe(topic) call. While this handler is registered,
comms.receive() gets nothing - messages go to the handler.
Parameters:
msg(dict) - The message, with keys:topic(str) - Topic passed toemit/send(""for a plainsend)data- The payload (plain data, deep-copied)sender_scope(str) - Sender's bot name, or"_global"sender_script(str) - Sender's script filenametimestamp(float) - Send time, epoch seconds
comms.subscribe("tasks")
@on("script_message")
def on_message(msg):
utils.log(f"{msg['sender_scope']}/{msg['sender_script']}: {msg['data']}")
if msg["topic"] == "tasks":
comms.send(msg["sender_scope"], {"status": "accepted"})
bot_connected
Fired when a bot finishes connecting to the manager (status becomes Online). Delivered to the bot's own scripts and to global scripts.
Parameters:
bot_name(str) - Name of the bot that connected
@on("bot_connected")
def on_connect(bot_name):
utils.log(f"{bot_name} is online")
comms.send(bot_name, {"cmd": "resume"})
bot_disconnected
Fired when a bot disconnects from the manager (status becomes Offline). Delivered to the bot's own scripts and to global scripts. The bot's scripts keep running in the manager after a disconnect.
Parameters:
bot_name(str) - Name of the bot that disconnecteduptime_seconds(float) - How long the bot was connected (0.0 if unknown)
@on("bot_disconnected")
def on_disconnect(bot_name, uptime_seconds):
utils.log(f"{bot_name} went offline after {uptime_seconds:.0f}s")