Skip to main content

UOPython - Extract information and images from the UO client files. New Fork from jackuolls ultima-py

Project description

PyPI version

uopython

uopython is a python library for rendering images from the Ultima Online client files. The SDK part of the project is almost a direct 1:1 code translation of the C# Ultima SDK (used by UOFiddler, among other things).

It does not support saving back to client files, only reading.

Why?

The C# SDK does not run with mono due to implementations being missing from the underlying libraries. Attempts to get this to run in dotnet core or using mono have never been successful. Rewriting this code in Python allows the code to be used in a linux environment, for the most part out of the box. Since Python has many available popular open source web frameworks, this library allows you to serve up images directly in code used by your web framework of choice.

It also includes some features not seen anywhere else, such as the rendering of player avatars. Items & paperdolls have been done before in PHP, but that code is difficult to read and edit, whereas this library takes a much more flexible and simple approach (the same as which is used in the C# SDK). This lib even fixes a few rendering bugs which are present in the C# SDK.

Features

uopython can currently do the following:

  • Render land, statics. This includes rendering of in game items.
  • Render "animations" or single frames of animations. This includes monsters and players, though player construction is done by rendering the mount, body, hair and clothing layers in order.
  • Draw text from the client (eg, ASCIIFont).
  • Extract information about skills - naming, groups, indexes.
  • Rendering paperdolls / individual gumps
  • Load and display Ultima Online map files

Installation

Install uopython to your project with:

pip install uopython

You must specify your Ultima Online client directory by any of the following methods:

  • environment.ini - add the line ULTIMA_FILES_DIR=/path/to/ultima
  • Django - add into settings.py: ULTIMA_FILES_DIR=/path/to/ultima
  • Specify an environment variable ULTIMA_FILES_DIR with the value /path/to/ultima

Settings

As above, settings can be set through any of the methods that the ULTIMA_FILES_DIR can be set by (environment.ini, Django settings, environment variable).

Currently there are only 2 settings:

  • ULTIMA_FILES_DIR, this is the path to your Ultima Online directory. This has no default and will not read from registry.
  • ULTIMA_MOUNT_IDS, if loaded via environment, should be a valid json list of all possible mount IDs. If set in Django, can simply be set up as a list. This has a default of mounts that are found in the 5.0.8.3 client.

How to use uopython

Here are detailed examples for using each major component of the library:

Working with Art (Items and Land Tiles)

from uopython.sdk.art import Art

# Render a static item (like a moongate)
moongate_item_id = 0x0F6C
art = Art.get_static(moongate_item_id, check_max_id=False)
art.save("moongate.png")

# Render a land tile
land_id = 0x3
land_tile = Art.get_land(land_id)
land_tile.save("land_tile.png")

# Get dimensions of an item
width, height = art.width, art.height
print(f"Moongate dimensions: {width}x{height}")

Working with Hues (Colors)

from uopython.sdk.art import Art
from uopython.sdk.hues import Hues

# Load an item
item_id = 0x0F6C
art = Art.get_static(item_id, check_max_id=False)

# Apply different hues
red_hue = Hues.HUES[32]  # Red
blue_hue = Hues.HUES[100]  # Blue
gold_hue = Hues.HUES[53]  # Gold

# Apply hues to the item
red_item = red_hue.apply_to(art, only_grey_pixels=False)
blue_item = blue_hue.apply_to(art, only_grey_pixels=True)  # Only applies to greyscale pixels
gold_item = gold_hue.apply_to(art)

# Save the results
red_item.save("red_item.png")
blue_item.save("blue_item.png")
gold_item.save("gold_item.png")

Working with Animations

from uopython.sdk.animations import Animations

# Get a specific animation
body_id = 400  # Example: human male
action = 0  # Standing
direction = 0  # Facing north
animation = Animations.get_animation(body_id, action, direction)

# Save the first frame
if animation and animation.frames:
    frame = animation.frames[0]
    frame.save("human_standing.png")
    
# Get information about the animation
if animation:
    print(f"Animation frames: {len(animation.frames)}")
    print(f"Frame dimensions: {animation.frames[0].width}x{animation.frames[0].height}")

Creating Character Avatars

from uopython.sdk.animation_assembler import AnimationAssembler

# Create a mounted character
body_id = 400  # Human male
action = 0  # Standing
direction = 0  # North
mount_id = 16000  # Horse

# Define equipment
equipment = [
    (0x1411, 0),      # (Item ID for chainmail tunic, hue 0)
    (0x1413, 0),      # (Item ID for chainmail leggings, hue 0)
    (0x1414, 0),      # (Item ID for chainmail coif, hue 0)
]

# Set hair and beard styles
hair_style = 0x203C
hair_hue = 1001
beard_style = 0x203E
beard_hue = 1001

# Create the avatar
avatar = AnimationAssembler.assemble_animation(
    body_id, action, direction, mount_id=mount_id,
    equipment=equipment, hair_style=hair_style, hair_hue=hair_hue,
    beard_style=beard_style, beard_hue=beard_hue
)

# Save the avatar
if avatar:
    avatar.save("mounted_knight.png")

Working with Fonts and Text

from uopython.sdk.asciifont import ASCIIFont

# Load a font
font = ASCIIFont(3)  # Font style 3

# Render text
text_image = font.get_text("Hello Ultima Online!")
text_image.save("hello_uo.png")

# Get text with a specific color (hue)
colored_text = font.get_text("Colored Text", hue=32)  # Red text
colored_text.save("colored_text.png")

Working with Skills Information

from uopython.sdk.skills import Skills

# Get all skills
all_skills = Skills.SKILLS

# Print information about each skill
for skill_id, skill in enumerate(all_skills):
    if skill:
        print(f"Skill #{skill_id}: {skill.name}, Group: {skill.group}")
        
# Look up a specific skill
fishing_skill = next((s for s in all_skills if s and s.name == "Fishing"), None)
if fishing_skill:
    print(f"Fishing skill ID: {all_skills.index(fishing_skill)}")
    print(f"Fishing skill group: {fishing_skill.group}")

Working with Gumps (UI Elements)

from uopython.sdk.gumps import Gumps

# Load a gump
gump_id = 0x09A8  # Example gump ID
gump = Gumps.get_gump(gump_id)

# Save the gump image
if gump:
    gump.save("gump.png")
    print(f"Gump dimensions: {gump.width}x{gump.height}")

Rendering Paperdolls

from uopython.sdk.paperdoll import Paperdoll

# Get a paperdoll for a specific body type
body_type = 400  # Human male
paperdoll = Paperdoll.get(body_type)

# Save the paperdoll
if paperdoll:
    paperdoll.save("paperdoll.png")
    
# Add equipment to a paperdoll
from uopython.sdk.gumps import Gumps

body_type = 400  # Human male
paperdoll = Paperdoll.get(body_type)

# Add armor pieces (these are gump IDs)
chest_piece = Gumps.get_gump(0x1411)  # Chainmail tunic
legs_piece = Gumps.get_gump(0x1413)   # Chainmail leggings

# Composite the equipment onto the paperdoll
# (This is a simplified example - actual implementation would depend on the library internals)
# final_paperdoll = paperdoll.composite([chest_piece, legs_piece])
# final_paperdoll.save("equipped_paperdoll.png")

Using the map_loader module

The map_loader module allows you to load and interact with Ultima Online map files:

from uopython.map_loader import MapLoader

# Initialize the map loader for a specific map
# Maps are numbered 0-5:
# 0: Felucca, 1: Trammel, 2: Ilshenar, 3: Malas, 4: Tokuno, 5: TerMur
map_loader = MapLoader(0)  # Loads map 0 (Felucca)

# Get an image of a specific region
# Parameters: start_x, start_y, width, height
map_image = map_loader.get_image(1400, 1450, 200, 200)
map_image.save("felucca_region.png")

# Get information about a specific map cell
cell = map_loader.get_cell(1400, 1450)
print(f"Terrain ID: {cell.id}")
print(f"Altitude: {cell.altitude}")

# Get multiple cells as a 2D array
# Parameters: start_x, start_y, width, height
cells = map_loader.get_cells(1400, 1450, 10, 10)
for y in range(10):
    for x in range(10):
        print(f"Cell at ({x+1400}, {y+1450}): Terrain ID {cells[y][x].id}")

# Get static items at a specific location
statics = map_loader.get_statics(1400, 1450)
for static in statics:
    print(f"Static item: ID {static.item_id}, Z {static.z}")

# Render a map with statics included
# Parameters: start_x, start_y, width, height, include_statics (boolean)
full_map_image = map_loader.get_image(1400, 1450, 200, 200, include_statics=True)
full_map_image.save("felucca_with_statics.png")

# Render a map centered on specific coordinates
# Parameters: center_x, center_y, radius (in cells)
centered_map = map_loader.get_centered_image(1400, 1450, 100)
centered_map.save("centered_map.png")

The map_loader provides comprehensive access to the Ultima Online map data, allowing you to:

  • Render map regions with or without static items
  • Get terrain and altitude information for specific locations
  • Analyze static items at any location
  • Create custom map visualizations for different purposes

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

uopython-0.2.0.tar.gz (22.9 kB view details)

Uploaded Source

Built Distribution

uopython-0.2.0-py3-none-any.whl (28.3 kB view details)

Uploaded Python 3

File details

Details for the file uopython-0.2.0.tar.gz.

File metadata

  • Download URL: uopython-0.2.0.tar.gz
  • Upload date:
  • Size: 22.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.2

File hashes

Hashes for uopython-0.2.0.tar.gz
Algorithm Hash digest
SHA256 eea6e12e4f6100f74346c3fa67cd17613ef1a0e463b0ee23d77cdd00a52e5f92
MD5 8a52ece721c911848e1221e1b0b96ed7
BLAKE2b-256 5c36a634ad324c49f290e3cacf0713142f7f588b04c632eaa32954c9903f829e

See more details on using hashes here.

File details

Details for the file uopython-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: uopython-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 28.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.2

File hashes

Hashes for uopython-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 346133dba5a235029b8557d1607ee9b1c395044aeb107b2cc2f2b62e0b368588
MD5 b134372739486f0f0af7ca6499bc788f
BLAKE2b-256 3b9cc07cde362adeb1e3c9d234f9a5ee03e95e38ca7ab4fd57d8ac93ff4bb767

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page