Skip to content

Latest commit

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Hytale Python Client

Unofficial Python QUIC client library for Hytale game servers. Supports full OAuth2 authentication, player movement, inventory management, block operations, and more.

Installation

pip install -e .

Or with venv:

python -m venv venv
source venv/bin/activate
pip install -e .

Quick Start

Simple Connection (Insecure Server)

importasynciofromhytaleimportHytaleClientasyncdefmain():
client=HytaleClient(
host="127.0.0.1",
port=5520,
username="Player",
)
awaitclient.connect()
awaitclient.wait_for_position()
print(f"Position: {client.position}")
awaitclient.disconnect()
asyncio.run(main())

Authenticated Connection

importasynciofromhytaleimportHytaleClientasyncdefmain():
client=HytaleClient(host="127.0.0.1", port=5520)
# OAuth flow - opens browser for loginawaitclient.connect(auth=True)
awaitclient.wait_for_position()
print(f"Logged in as: {client.username}")
print(f"Position: {client.position}")
awaitclient.disconnect()
asyncio.run(main())

With Auth Caching (Remembers Login)

# First run: opens browser for OAuth# Subsequent runs: uses cached tokensclient=HytaleClient(host="127.0.0.1", port=5520, cache_auth=True)
awaitclient.connect(auth=True)
# Clear cache when neededHytaleClient.clear_auth_cache()

Player Movement

# Wait for spawn positionawaitclient.wait_for_position()
# Get current positionx, y, z=client.positionyaw, pitch=client.yaw, client.pitch# Move to absolute coordinatesclient.move(x=100, y=65, z=200)
# Move relative to current positionclient.move_relative(dx=5, dy=0, dz=-3)
# Fly forward (in look direction)client.fly_forward(distance=10.0)
# Look at directionclient.look(yaw=90.0, pitch=0.0)
# Walk to target (sends movement packets)awaitclient.walk_to(x=100, y=65, z=200, speed=4.3)

Inventory Management

# Wait for inventory to loadawaitasyncio.sleep(2)
# Print inventory summaryclient.print_inventory()
# Get itemsitem=client.get_item_in_hand()
hotbar_item=client.get_hotbar_item(slot=0)
storage_item=client.get_storage_item(slot=5)
# Select hotbar slot (0-8)client.select_hotbar_slot(3)
# Move items between slotsclient.move_item(
from_section=InventorySectionId.HOTBAR, from_slot=0,
to_section=InventorySectionId.STORAGE, to_slot=10,
quantity=5# or omit for all
)
# Convenient methodsclient.move_to_storage(hotbar_slot=2, storage_slot=0)
client.move_from_storage(storage_slot=0, hotbar_slot=2)
client.swap_hotbar_slots(slot1=0, slot2=1)
# Sort inventoryclient.sort_inventory(InventorySectionId.STORAGE)

Block Operations

Place Blocks

# Place block at coordinates (uses item in hand)client.place_block(x=100, y=65, z=200)
# Place specific block by IDclient.place_block(x=100, y=65, z=200, block_id=42)
# Place relative to player's look directionclient.place_block_relative(forward=2, right=0, up=0)

Break Blocks (Under constraction)

# Break block at coordinatesclient.break_block(x=100, y=65, z=200)
# Break with multiple hits (for harder blocks)client.break_block_hold(x=100, y=65, z=200, hits=10)

Chunk Data

# Wait for chunks to loadawaitasyncio.sleep(5)
# Get chunk count and rangeprint(f"Loaded chunks: {client.chunk_count}")
print(f"Range: {client.get_loaded_chunk_range()}")
# Get current chunkchunk=client.get_current_chunk()
ifchunk:
print(f"Chunk at ({chunk.x}, {chunk.y}, {chunk.z})")
# Get block at world coordinatesblock_id=client.get_block(x=100, y=65, z=200)
# Check if position is loadedifclient.is_block_loaded(100, 65, 200):
print("Block is in a loaded chunk")

Events

Subscribe to events for real-time updates:

fromhytaleimportConnectedEvent, WorldSettingsEvent, JoinWorldEvent@client.on(ConnectedEvent)defon_connected(event):
print("Connected to server!")
@client.on(WorldSettingsEvent)defon_world_settings(event):
print(f"World height: {event.world_height}")
print(f"Spawn: {event.spawn_point}")
@client.on(JoinWorldEvent)defon_join(event):
print(f"Joined world: {event.world_name}")

Available Events

EventDescription
ConnectedEventQUIC connection established
DisconnectedEventDisconnected from server
WorldSettingsEventWorld configuration received
JoinWorldEventJoined a world instance
ClientIdEventClient entity ID assigned
TeleportEventPlayer teleported
EntityUpdatesEventEntity state updates
ChunkEventChunk data received
ChunkUnloadEventChunk unloaded
InventoryUpdateEventInventory changed
ActiveSlotEventActive slot changed
PingEventServer ping
PacketEventRaw packet (all packets)

CLI Usage

# Insecure server
hytale-client --host 127.0.0.1 --port 5520 --username Player
# Authenticated server
hytale-client --host 127.0.0.1 --port 5520 --auth
# With debug logging
hytale-client --host 127.0.0.1 --port 5520 --debug

Advanced: Manual Authentication

For full control over authentication:

fromhytaleimportHytaleClientfromhytale.authimport (
authorize, fetch_game_profile, SessionServiceClient
)
asyncdefmain():
# Step 1: OAuthtokens=awaitauthorize()
# Step 2: Get profileprofile=awaitfetch_game_profile()
# Step 3: Create sessionsession_client=SessionServiceClient()
session=awaitsession_client.create_game_session(
tokens.access_token, profile.uuid
)
# Step 4: Connectclient=HytaleClient(
host="server.example.com",
port=5520,
username=profile.username,
identity_token=session.identity_token,
session_token=session.session_token,
uuid=profile.uuid,
)
awaitclient.connect()
awaitclient.wait()
asyncio.run(main())

Protocol Details

  • Transport: QUIC over UDP
  • TLS: 1.3 with mTLS (self-signed client certificates)
  • ALPN: hytale/1
  • Compression: Zstandard for large packets
  • Frame format: [4B length LE][4B packet ID LE][payload]
  • Authentication: OAuth2 + JWT identity tokens

About

Unofficial Python QUIC client for Hytale. Supports OAuth2 authentication, player movement, inventory management, and block operations.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages