Classic Ultima Online on Godot 4 .NET
Two layers. Launchers are .bat files under launchers\, grouped by
job; every one of them calls launchers\_shared\common.bat first and then
runs an engine command or a Python tool. Tools are one folder per job
under tools\, each with a run.py entry point, all importing the shared
tools\guo package for paths and configuration. Third-party programs the
project depends on get a folder of their own with a README (tools\godot,
tools\modernuo).
Every launcher is a pair: <name>.bat and <name>.sh, same name,
same behaviour. The .sh sources launchers/_shared/common.sh; one that
cannot work off Windows says why and exits 2. See Linux.
Each launcher says what it does in its first line: a rem line straight
after @echo off in the .bat, the same sentence as the # line after the
shebang in the .sh, and an optional args: line after it listing the flags
it takes. DirectorDeck’s Run panel shows that sentence as the button’s hint.
A launcher stays in the foreground for long-running work (a shard, a
server) so its output can be watched and stopped, unless its line says it
detaches (an editor or a browser); it exits non-zero on failure and never
asks a question on stdin. launchers\dev\launcher_lint.bat checks all of
it, and so do the smoke, the pre-push hook and CI;
launchers\dev\launcher_lint.bat --list prints every pair with its line.
_shared\Not launchers. config.bat (defaults, committed), config.local.bat
(yours, gitignored, from config.local.bat.example) and common.bat (the
shared logic), and their Linux twins config.sh, config.local.sh and
common.sh. See Configuration.
game\| Launcher | Does |
|---|---|
play.bat |
The launcher. Runs the client against the configured shard. --offline loads data without a shard; --frames N quits after N frames; anything else goes to the client. |
pipeline\ (data steps, in order)| Launcher | Does |
|---|---|
00_bootstrap.bat |
Fetches the pinned engine into tools\godot and the upstream reference into sources\ClassicUO. |
01_verify_client_data.bat |
tools\uodata verify: is the UO install complete, and which version is it. |
02_warm_cache.bat |
Optional: pre-build the decode cache. |
03_port_audit.bat |
tools\port_audit: re-measures the port and writes docs\port_status.md. |
04_world_export.bat |
tools\world export then verify: turns the editor’s world project into patched map files. |
editor\| Launcher | Does |
|---|---|
open_project.bat |
Opens the Godot project in the editor. |
open_solution.bat |
Opens the generated GUO.sln. |
open_reference.bat |
Opens the upstream ClassicUO reference. |
shard\ (the local ModernUO server, see Dev Shard)| Launcher | Does |
|---|---|
fetch.bat |
Clones ModernUO at the pin and applies the patches. Once. |
build.bat |
Publishes it. Once, about two minutes. |
run.bat |
Runs it; Ctrl-C stops it. |
populate.bat |
Logs the owner account in and types the world generation commands. Once per new world. |
dev\| Launcher | Does |
|---|---|
build.bat |
dotnet build of the client; stops after UO_BUILD_TIMEOUT seconds (180) and cleans up only what it started. |
smoke.bat |
The seven-step health check: engine, imports, C# build, client data, offline load, the editor add-on, the launchers. Run before every commit. |
screenshot.bat |
Boots the client with --screenshot into build\screenshots; extra flags pass through (--play --shot-after N). |
playtest.bat |
A scripted session against the shard: log in, walk, gumps, drag, speak; exit 0 only if every check passed. |
perf_lab.bat |
Your frame rate at 1920x1080 and at 2560x1440 zoom 2.5, as a table and a report to share. Needs the dev shard running. See Performance. |
perf_lab_doctor.bat |
Checks what the perf lab needs and says how to fix what is missing; measures nothing. |
perf_probe.bat |
The developer’s frame-time probe under the perf lab: one window size, every column. |
endurance.bat [seconds] |
The playtest, then keeps walking (five minutes by default) and compares the last stretch with the first in frame time, object count and memory. |
multi_client.bat |
Four scripted clients at once, tiled 2x2, one lane each: session, effects, highlight, sweep. --only, --list, --sound. |
plugin_probe.bat |
Builds a native and a managed test plugin, plays a session with both, reads their logs back. Needs MSVC. |
sweep.bat |
Photographs the same five places every run, for comparing renderer changes by eye. |
ab_compare.bat |
ClassicUO and GUO in the same places, stacked in one image. See Parity and Drift. |
side_by_side.bat |
Both clients live on one monitor, in one place. |
render_diff.bat |
Compares a ClassicUO render dump with a GUO one. |
render_probe.bat, batcher_probe.bat, blend_probe.bat, mesh_probe.bat, atlas_probe.bat, audio_probe.bat |
The renderer and audio self-checks the ADRs cite in their Validation sections. |
touch_probe.bat |
Synthetic fingers through the touch layer on the desktop; 18 checks against the shard. |
editor_smoke.bat |
Opens the real editor headless and checks the add-on. |
brand_icons.bat |
Rebuilds every icon from design\brand\guo-sigil.png. |
port_errors.bat |
Clusters the C# build’s errors by cause. |
rebuild_class_cache.bat |
Regenerates the engine’s class cache when a new C# node type will not appear. |
clean_cache.bat |
Deletes the decode cache. |
sync_upstream.bat |
Reports upstream ClassicUO commits since the pin; --pin records the current head as reviewed. |
worktree_setup.bat |
Readies a fresh git worktree: copies your config.local.bat, deny.local.txt and .claude/settings.local.json from the main checkout, checks the engine and upstream resolve (no directory links), runs one headless import. |
fetch_godot.bat |
Re-fetches the pinned engine on its own. |
build_guoasset.bat |
Builds the guoasset MCP server. |
launcher_lint.bat |
Checks every launcher pair (description line, line endings, executable bit, no stdin); --list prints them all. |
docs_lint.bat, privacy_scan.bat |
The pre-push checks on their own: Markdown links and anchors; LAN addresses, emails and machine paths. |
selftest.bat |
Every Python tool self-test CI runs, read from the CI workflow; --list, --only <text>. |
scenario_run.bat |
Runs a scripted scenario and records it (tools\scenario_run); lists the scenarios when given nothing. |
gump_studio_smoke.bat, profile_migrations.bat, guo_mcp_probe.bat, editor_live.bat, world_parity.bat |
Smokes and probes for Gump Studio, the profile migration ladder, the automation MCP, the editor’s live tier and the World view. |
server_manager.bat |
The editor’s named servers and clients: init, clients, doctor (the default). |
world\The world authoring tools, each printing its usage when run with nothing:
multi.bat (new multis), decorate.bat (furnishing them), mapgen.bat
(procedural maps), mapgen_districts.bat (towns on them) and uopack.bat
(art, gumps and animations out to PNG and back).
windows\, android\, web\, steamdeck\The export pipelines: doctor.bat (what the export needs and what this
machine has), export.bat, and for Android install.bat, run.bat,
smoke.bat (--avd guo_phone for GUO’s own emulator), dual_probe.bat,
portrait_probe.bat, device_manager.bat; for web serve.bat,
smoke.bat and ws_bridge.bat; for the Steam Deck push.bat, run.bat,
screenshot.bat and smoke.bat. See Windows Build,
Android Build, Web Client and
Steam Deck.
store\The local Asset Store: serve.bat, publish.bat, open.bat and
keygen.bat. See Asset Store.
This page lists the main launchers. launchers\dev\launcher_lint.bat --list
prints every launcher pair with its one-line description, including
art\, servuo\ and the rest of dev\ (perf_probe, scenario_run,
server_lab, port_drift, pytest_all, mcp and more).
| Folder | Entry point | Does |
|---|---|---|
guo |
(package) | Shared configuration, paths, the map reader uomap.py. Every tool imports it. |
uodata |
run.py verify\|list\|where |
Checks the UO install, prints the file registry and the resolved paths. |
port_audit |
run.py [--out] [--json] |
Scores the port per file and tier; writes docs\port_status.md. CI fails if the committed report is stale. |
port_bulk |
run.py --area X |
Ports a mechanical-tier area (verbatim/shim) by renamespacing. |
port_errors |
run.py [--top N] [--raw] |
Clusters build errors. |
port_triage |
run.py |
Sorts what remains of the port by tier and cause. |
sync_upstream |
run.py [--pin] [--no-fetch] [--limit] [--at-pin] |
Upstream drift report; --at-pin checks the reference out at the reviewed commit. |
worktree_setup |
run.py [--no-import] |
Readies a fresh git worktree without directory links; see UO_GODOT_HOME / UO_UPSTREAM_DIR in Configuration. |
ab_compare, side_by_side, render_diff, render_dump |
see Parity and Drift | The parity tooling. |
multi_client |
run.py [--only] [--list] |
The four-lane run. |
plugin_probe |
run.py [--no-run] |
The plugin host check. |
plugin_host |
(C# project) | The bootstrap that loads managed assistants (Razor and the like) inside the client; shipped with the exported build. |
guoasset |
(C# MCP server) | Renders UO art from the client data as a parity reference for agents. tools\guoasset\README.md. |
brand |
run.py [--sheet] |
Every app icon and the splash from the sigil. |
windows |
run.py doctor\|preset\|export\|icon |
The Windows export and its icon check. |
android |
run.py doctor\|templates\|keystore\|settings\|preset\|export\|install\|run\|logcat\|push\|smoke\|dual_probe\|displays |
The Android pipeline. |
web |
run.py doctor\|preset\|export\|serve\|smoke |
The web pipeline, on the community engine build in tools\godot_web. |
bg_videos |
run.py [--only] [--size] [--out] |
Renders the ten built-in background loops. |
editor_smoke, editor_live, editor_shard, world, world_parity |
see Editor | The editor add-on’s checks, the private shard instance, the world export and its parity check. |
modernuo |
configure.py, patches\, config\ |
The dev shard’s patches and configuration templates; the checkout itself is gitignored. |
godot |
(README) | The pinned engine, gitignored. |
Every run.py answers --help with the same text as its README’s header.