Repository navigation
Example: Advanced Client
This example shows the recommended way to build a client: subclass Client, override callbacks as methods, use a context manager for clean resource handling, and run your own work alongside the client.
- Creates a custom client class (
AdvancedClient) that handles connection, authentication, and errors - Logs in automatically when the server sends its initial
RoomInfopacket - Runs a placeholder task concurrently with the client
- Uses
async withto ensure the client is always properly shut down
import asyncio
from asyncio import Server
from archipelagopy import packets
from archipelagopy.callback_interface import OnConnectExceptionUnion
from archipelagopy.client import Client
from archipelagopy.enums.item_handling_flag import ItemHandlingFlag
from archipelagopy.packets import Connect
class AdvancedClient(Client):
async def on_ready(self):
print("Client is connected and ready")
async def on_room_info(self, packet: packets.RoomInfo):
packet = Connect(
version=packet.version,
tags=["Tracker"],
name="Mario", # Slot name
items_handling=ItemHandlingFlag.OWN_WORLD | ItemHandlingFlag.OTHER_WORLDS,
slot_data=True
)
await self.send(packet)
def on_connect_error(self, error: OnConnectExceptionUnion):
print("Failed to connect:", error)
async def on_connection_refused(self, packet: packets.ConnectionRefused):
print("Connection refused:", packet.errors)
await self.stop()
async def on_connected(self, packet: packets.Connected):
print(f"Logged in as: {packet.slot_info[packet.slot].name}")
async def on_packet(self, packet: Server):
print(f">> ({packet})\n")
async def my_work_task():
"""
Example task, replace with your own asynchronous work.
"""
while True:
await asyncio.sleep(1)
async def runner():
"""
Test function to run the client.
"""
# Uncomment enable debug logging
# import logging
# logging.basicConfig(level=logging.DEBUG)
async with AdvancedClient(port=12345) as client:
my_task = asyncio.create_task(my_work_task())
await client.wait_closed(my_task) # wait for the client to close or the task to finish
def main():
try:
asyncio.run(runner())
except KeyboardInterrupt:
pass
if __name__ == "__main__":
main()-
class AdvancedClient(Client)creates a subclass ofClient. Instead of assigning callback functions one by one (like the Simple Client), we override them as class methods. This is cleaner when you have multiple callbacks and keeps everything organized. -
async with AdvancedClient(port=12345) as client:is a context manager. It callsclient.start()when entering the block andclient.stop()when leaving — even if an error occurs. This prevents resource leaks. -
on_room_infois called automatically when the server sends its initialRoomInfopacket. This is a good place to authenticate because the packet contains the server's version, which you can pass directly to theConnectpacket. -
ItemHandlingFlag.OWN_WORLD | ItemHandlingFlag.OTHER_WORLDScombines two flags using the|(bitwise OR) operator. This tells the server to send you items from both your own game and other players' games. -
on_connect_errorhandles network-level failures (server unreachable, timeout, etc.). Note it usesdef, notasync def— this is one of the two synchronous callbacks. See Callbacks for why. -
on_connection_refusedhandles authentication failures (wrong password, invalid slot name). It callsawait self.stop()to shut down the client. -
asyncio.create_task(my_work_task())startsmy_work_taskrunning concurrently in the background. This is where you'd put your own game logic. -
await client.wait_closed(my_task)blocks until either the client disconnects ormy_taskfinishes, whichever happens first. Without the task argument, it would only wait for the client to disconnect.