Repository navigation
Callbacks
Callbacks are functions that the library calls automatically when specific events happen, such as receiving a message from the server or disconnecting. You define what should happen by overriding these functions in your client.
The Client class inherits from ClientCallbackInterface, which defines all available callbacks with empty default implementations. You override the ones you care about.
Here is the typical sequence of events when connecting to an Archipelago server:
- You call
client.start()to initiate the WebSocket connection - Once connected,
on_ready()fires — the connection is open but you haven't authenticated yet - The server automatically sends a
RoomInfopacket with server details, triggeringon_room_info() - You send a
Connectpacket with your slot name and game to authenticate - The server responds with
ConnectedorConnectionRefused, triggeringon_connected()oron_connection_refused() - During the session, incoming packets are dispatched in order:
on_received()(raw JSON string) ->on_packet()(parsed packet, all types) -> the specific handler (e.g.on_print_json()) - When the server disconnects,
on_connection_closed()fires
The "Async" column indicates whether the callback must be defined with async def (Yes) or regular def (No). See Sync vs async callbacks below for details.
| Callback | Async | Parameter | Description |
|---|---|---|---|
on_ready() |
Yes | — | WebSocket connection established, ready to send and receive packets |
on_connect_error(error) |
No | Connection error | Connection attempt failed (e.g. refused, timeout, invalid URI) |
on_connection_closed(close_code) |
No | Close code | Server closed the connection |
Each packet callback receives a single argument: the parsed packet object. You can access the packet's fields as attributes (e.g. packet.slot, packet.errors). See the Packets page for the full list of fields on each packet type.
| Callback | Async | Parameter | Description |
|---|---|---|---|
on_received(packet) |
Yes | str |
Raw JSON string received from the server, before parsing |
on_packet(packet) |
Yes | ServerPacket |
Any parsed packet. Fires before any specific handler, useful for logging |
on_connected(packet) |
Yes | Connected |
Authentication successful. Contains your slot number, player list, etc. |
on_connection_refused(packet) |
Yes | ConnectionRefused |
Authentication rejected. Check packet.errors for reasons |
on_room_info(packet) |
Yes | RoomInfo |
Server info, sent automatically when you first connect |
on_room_update(packet) |
Yes | RoomUpdate |
Room state changed (players joining/leaving, etc.) |
on_print_json(packet) |
Yes | PrintJSON |
Formatted message from the server (chat, hints, item sends, etc.) |
on_received_items(packet) |
Yes | ReceivedItems |
Items delivered to the player |
on_location_info(packet) |
Yes | LocationInfo |
Response to a location scout request |
on_data_package(packet) |
Yes | DataPackage |
Game data (item names, location names, etc.) |
on_bounced(packet) |
Yes | Bounced |
Message relayed from another client via the server |
on_retrieved(packet) |
Yes | Retrieved |
Response to a data storage Get request |
on_set_reply(packet) |
Yes | SetReply |
Response to a data storage Set request |
on_invalid_packet(packet) |
Yes | InvalidPacket |
Server reports a malformed packet was sent |
Most callbacks are async — they are defined with async def and can use await inside them (e.g. to send packets back to the server).
Two callbacks are synchronous (regular def): on_connect_error and on_connection_closed. These run during connection management where async execution could interfere with reconnection and shutdown logic.
The library enforces this at assignment time. If you accidentally use the wrong type, you'll get a clear error:
# Wrong - on_ready is an async callback, so it must use "async def":
def bad_handler():
print("ready")
client.on_ready = bad_handler
# TypeError: Cannot monkey patch coroutine function on_ready with non-coroutine function.
# Correct:
async def good_handler():
print("ready")
client.on_ready = good_handler # worksThere are two ways to override callbacks:
You can replace a callback by assigning a new function on the client instance. This is quick and convenient for simple use cases:
from archipelagopy import Client, packets
async def on_print_json(packet: packets.PrintJSON):
for msg in packet.data:
if msg.text is not None:
print(f">> {msg.text}")
client = Client(port=12345)
client.on_print_json = on_print_json # replaces the default (empty) on_print_jsonFor anything beyond a simple script, subclass Client and override the methods you need. This keeps all your callback logic organized in one class:
from archipelagopy import Client, packets
from archipelagopy.callback_interface import OnConnectExceptionUnion
class MyClient(Client):
async def on_ready(self):
print("Connected and ready")
async def on_connected(self, packet: packets.Connected):
print(f"Authenticated as slot {packet.slot}")
async def on_connection_refused(self, packet: packets.ConnectionRefused):
print(f"Refused: {packet.errors}")
await self.stop()
# Note: on_connect_error uses "def", not "async def"
def on_connect_error(self, error: OnConnectExceptionUnion):
print(f"Connection failed: {error}")OnConnectExceptionUnion is a type alias imported from archipelagopy.callback_interface. It represents the possible error types: ConnectionRefusedError, TimeoutError, OSError, and several websocket-specific errors. You don't need to import it — it's only useful for type hints.
on_packet fires for every parsed packet before the specific handler. This is useful for logging or inspecting all traffic:
class DebugClient(Client):
async def on_packet(self, packet: packets.ServerPacket):
print(f"Received: {type(packet).__name__}")