Skip to content

Build from source

EasyUO Reforged is four Windows programs, built with Lazarus / Free Pascal from one repository. You need to build it to try a change of your own, for example a new client entry. To just use it, take the zip from the releases page instead.

Project Builds What it is
EasyUOReforged.lpi EasyUOReforged.exe The script editor and runner.
uo.lpi uo.dll The client engine as a DLL, for other programs (uo.dll API). EasyUOReforged.exe does not use it.
EUOUpdtr.lpi EUOUpdtr.exe EUOUpdater, the scan tool for new client builds (Deriving values by hand).
EUOMenuDesigner.lpi EUOMenuDesigner.exe The MENU Designer, which lays out menu windows and writes their script.
  • Windows, 64-bit. Everything builds for x86_64-win64 only.
  • Lazarus 3.6 or newer, from the 64-bit Windows installer on lazarus-ide.org. It includes Free Pascal 3.2.2 and the two editor packages the GUI uses (SynEdit and the SynUni highlighter), so there is nothing else to install. The project was developed on Lazarus 3.6; CI builds every push with the current stable release.
  • Git, to clone the repository. The build also uses it to put the commit into the version string.
  • PowerShell 7 (pwsh), for the test script.

For this site you also need Node.js, and for EUOMigrate, Python (see Using EUOMigrate).

Terminal window
git clone https://github.com/ilpersi/EasyUOReforged.git
cd EasyUOReforged

lazbuild.exe builds a Lazarus project from the command line. The installer does not put it on PATH: it is in the Lazarus folder, C:\lazarus unless you chose another one. For the current PowerShell window:

Terminal window
$env:Path += ';C:\lazarus'
lazbuild --version

To keep it, add the folder to your PATH in Windows (Edit environment variables for your account).

The programs share their code through three Lazarus packages. Tell Lazarus where they are, once per machine:

Terminal window
lazbuild --add-package-link common/uocommon.lpk uo/uoengine.lpk parser/euoparser.lpk
Package Folder Contents Uses
uocommon common/ Reading and writing the client’s memory, shared types.
uoengine uo/ The client engine: version detection, offset tables, variables, commands, events. uocommon
euoparser parser/ The script language: interpreter, expressions, script execution. uoengine, uocommon

The links are saved in your Lazarus configuration, so the IDE finds the packages too. They point at one folder: if you keep a second clone or a git worktree, its builds still compile the packages of the clone you registered last. Run the command again in the clone you are working in.

Terminal window
lazbuild --build-mode=Release uo.lpi
lazbuild --build-mode=Release EasyUOReforged.lpi
lazbuild --build-mode=Release EUOUpdtr.lpi
lazbuild --build-mode=Release EUOMenuDesigner.lpi

Build any of them, in any order. The programs land in the repository folder, next to the .lpi files. From a fresh clone, all four together take about a minute.

Each project has two build modes. Both write the same file name, so the last build wins.

Mode For
Default (leave out --build-mode) Debugging: debug information, light optimization.
Release What a release ships: optimized (-O3), no debug information, symbols stripped.

The modes keep their compiled units in separate folders (lib\x86_64-win64\ and lib\x86_64-win64-release\). EUOUpdater has folders of its own, because its main unit has the same name as the GUI’s, and so does the MENU Designer.

Before every build, tools/gen-version.ps1 writes common/ReforgedVersion.pas with a version such as 26.10.24.70afbc8: today’s date and the current commit. The title bar, Help → About and #ReforgedVer show it. The file is git-ignored and only rewritten when the value changes. A fresh clone does not have it until the first build: if your editor complains before then, run pwsh tools/gen-version.ps1. Without Git, the commit part reads nogit.

Terminal window
pwsh ./tests/run_tests.ps1

The script:

  1. finds lazbuild: on PATH, in a usual Lazarus folder, or in $env:LAZARUS_DIR;
  2. refreshes the version file and registers the packages;
  3. builds tests/RunTests.lpi and runs the FPCUnit suite;
  4. checks that every command and variable has a self-test case and a page on this site, so a new command fails the suite until both exist.

Most tests need no game client. tests/LiveClientTests.pas runs against a client if one is running and logged in, and reports its tests as ignored otherwise. Anything else that needs a live client is checked by hand, with the self-test.

To run part of the suite, call the runner the script built:

Terminal window
tests/RunTests.exe --list
tests/RunTests.exe --format=plain --suite=TEuoInterpreterTests
tests/RunTests.exe --format=plain --suite=TEuoInterpreterTests.TestVersionVarsAreDistinct

Without --format=plain the runner prints XML.

  1. Register the packages first (step 3).
  2. Project → Open Project, and pick EasyUOReforged.lpi (or uo.lpi, EUOUpdtr.lpi, EUOMenuDesigner.lpi).
  3. Pick the build mode: Project → Project Options → Compiler Options, the Build modes list at the top.
  4. Run → Build (Shift+F9) builds it. Run → Run (F9) starts it under the debugger; use the Default mode for that.

The GUI has no form files (.lfm): easyuo/main.pas creates every control in code, so the form designer has nothing to show. The same goes for the MENU Designer (tools/EUOMenuDesigner/mdmain.pas).

The programs need no other files next to them. The sql command uses Windows’ own SQLite, or a 64-bit sqlite3.dll placed next to EasyUOReforged.exe (see the SQL guide).

A build of your own is not code-signed either, so SmartScreen or an antivirus can warn about it for the same reason it warns about a release: it reads and writes another program’s memory. See SmartScreen and antivirus.

This site lives in website/ (Astro Starlight). You only need it to change these pages:

Terminal window
cd website
npm ci
npm run dev

npm run dev serves the site at http://localhost:4321/EasyUOReforged/ and reloads a page when you save it. npm run build builds it into website/dist/ and fails on a broken internal link, as the Docs build check workflow does for every pull request and every push to main. The pages are the Markdown files in website/src/content/docs/.

  • .github/workflows/ci.yml runs the steps above on a clean windows-latest machine for every push and pull request: the version file, the package links, the four Release builds, run_tests.ps1, and the EUOMigrate tests. It keeps the programs as a build artifact.
  • .github/workflows/release.yml does the same for a v* tag, then publishes a GitHub release: a zip with the four programs, LICENSE, NOTICE, README.md and CHANGELOG.md, and SHA-256 checksums. The release page shows the tag’s section of CHANGELOG.md, or the commits since the previous tag if it has none (see Cutting a release).
  • .github/workflows/docs-check.yml (Docs build check) builds this site for pull requests and pushes to main, without publishing it.
  • .github/workflows/docs.yml (Publish docs site) publishes this site from the latest release, after release.yml succeeds. To publish it at another time, run it by hand from main (Actions → Publish docs site → Run workflow); its ref field takes a tag, branch or commit to publish instead of the latest release.

If a build works in CI but not on your machine, compare your steps with ci.yml.

Each change that script users would notice adds a line under ## Unreleased in CHANGELOG.md, in ### Added, ### Changed or ### Fixed. When it is time to release, from a clean main:

Terminal window
pwsh tools/release.ps1 v26.11.05

The script renames ## Unreleased to ## v26.11.05 - <date>, starts a new empty ## Unreleased above it, commits that as Release v26.11.05 and tags the commit. It prints the release notes as GitHub will show them, and pushes nothing. If they read right, push the branch and the tag:

Terminal window
git push origin main v26.11.05

The tag starts release.yml. To see the notes for any tag without releasing, run pwsh tools/release-notes.ps1 -Tag v26.11.05.

Message Cause Fix
'lazbuild' is not recognized ... The Lazarus folder is not on PATH. Step 2.
Could not find lazbuild. Set $env:LAZARUS_DIR ..., from run_tests.ps1 Lazarus is neither on PATH nor in a usual folder. Set $env:LAZARUS_DIR to your Lazarus folder and run it again.
Error: (lazbuild) Broken dependency: uoengine The packages are not registered. Step 3.
Can't find unit ... after switching between Default and Release with -B Compiled units (.ppu) left over from the other mode. Delete the compiled units (below) and build again.
Can't create object file: ...EasyUOReforged.exe (error code: 5) The program is running, so Windows does not let the linker replace it. Close it and build again.
A test crashes with an access violation right after a class gained fields A test unit that reaches the class only through another unit was not recompiled. Delete tests\lib and run the tests again.
The version ends in nogit Git is not on PATH. Install Git, or add it to PATH.

To delete every compiled unit (all git-ignored), from the repository folder:

Terminal window
Remove-Item -Recurse -Force lib, common\lib, uo\lib, parser\lib, tests\lib -ErrorAction SilentlyContinue