Skip to content

Developer guide

This section is for people who work on EasyUO Reforged itself. Its main subject is the job that comes back with every client patch: teaching EasyUO Reforged a new client build, by hand or with the EUOMigrate tool.

If you only want to write scripts, you don’t need any of this: start with Get started. To build the programs yourself, see Build from source. For the ground rules and pull requests, see CONTRIBUTING.md on GitHub.

EasyUO Reforged keeps the memory addresses and object layouts of every client build it supports. A build it does not know usually still attaches, but some things go wrong:

  • variables read 0, N/A or nonsense, for example #CharPosX never changes;
  • events do nothing, for example event Macro or event SysMessage;
  • the client is not offered at all (“No supported UO client found!”), when it is older than every known build.

How client support works explains why; Add a new client fixes it.

  • A clone of the repository, and Lazarus 3.6 or newer to build it (see Build from source).
  • The client executable you want to support.
  • Python 3.10 or newer with Capstone, for EUOMigrate.
  • A character logged in on that client, for the live checks. They only read the client’s memory.
Terminal window
# 1. Derive the values (the client does not need to run)
pip install -r tools/EUOMigrate/requirements.txt
python tools/EUOMigrate/euomigrate.py migrate "C:\Games\Ultima Online\client.exe"
# 2. Start the client, log in, and check them in the running client
python tools/EUOMigrate/euomigrate.py verify tools/EUOMigrate/out/<id>/candidates.json
python tools/EUOMigrate/euomigrate.py probe tools/EUOMigrate/out/<id>/candidates.json
# 3. Paste out/<id>/uoclidata-snippet.pas into uo/uoclidata.pas, rebuild, test
pwsh ./tests/run_tests.ps1
# 4. Add the build to the knowledge base for next time
python tools/EUOMigrate/euomigrate.py fingerprint "C:\Games\Ultima Online\client.exe"

Every step is explained, with examples, in Add a new client.

The architecture of the code as a whole is described in docs/architecture.md.