Documentation + tools
List generated from folders in /docs.
README preview from GitHub (main / configured branch).
Node/Web implementation of an Ultima Online shard and browser client. The project started as a functional migration from ServUO and ClassicUO patterns, but the goal is an independent codebase: compatible with the UO protocol where that is useful, and designed for Node.js, WebSocket, PixiJS, and modern browser rendering.
This repository does not include game files. You generate runtime assets locally from your own legal Ultima Online Classic installation.
This project is prepared for public source distribution.
make the corresponding source code available to the community under the same license terms.
world saves, accounts, passwords, shard secrets, or private player data.
| Area | Technology | Role |
|---|---|---|
| Server | Node.js, ESM, CODE_0 | Shard runtime, world state, accounts, persistence, scripts, gameplay systems |
| Client | Vite, PixiJS v8, WebGL | Browser UO client for the project WebSocket flow and bridge flow |
| Scripts | JavaScript ESM + Script API | Commands, items, mobiles, NPCs, AI, skills, spells, quests, spawns |
| Extractor | Node.js + CODE_0 | MUL/UOP to PNG/JSON/bin assets, optional KTX2/Basis output |
| Control Panel | Electron | Start/stop server, client, bridge, extractor, tools, and logs |
| Bridge | Node.js TCP/WebSocket | Browser client to raw TCP ServUO/RunUO/OSI-style shard |
The priority is functional coverage against ServUO and ClassicUO behavior without copying their architecture one-to-one. Reference projects are used for parity, protocol behavior, and bug fixing; the runtime design should stay native to this repository.
Main rules:
CODE0, CODE1, CODE_2, and registry helpers.
pipeline are built for the web.
for VRAM/decode if you generate it with CODE_0.
code.
apps/
client/ Vite + PixiJS browser client
server/ shard, world engine, net handlers, persistence, systems
scripts/ gameplay content and server scripting API consumers
bridge/ WebSocket <-> raw TCP bridge for external shards
control-panel/ Electron launcher with logs and tool buttons
packages/
protocol/ UO binary protocol, packets, Huffman/shared helpers
extractor/ asset pipeline: MUL/UOP -> client assets
tools/
run-control-panel.bat main Windows GUI launcher
run-control-panel.sh main Linux/macOS GUI launcher
bats/ Windows command launchers
sh/ Linux/macOS command launchers
audit/ ServUO/ClassicUO audits and coverage maps
docs/
README.md documentation index
server-scripting.md guide for the current server Script API
templates/
ClassicUO/ServUO reference code, for comparison only
saves/
local world/account saves
Basic check:
node -v
corepack enable
pnpm -v
Recommended Windows path:
tools\run-control-panel.bat
Recommended Linux/macOS path:
chmod +x tools/run-control-panel.sh tools/sh/*.sh
tools/run-control-panel.sh
The Control Panel can:
Terminal path for Linux/macOS:
pnpm install
UO_SRC="/path/to/Ultima Online Classic" tools/sh/extract-assets.sh
tools/sh/run-server.sh
tools/sh/run-client.sh
Terminal path for Windows:
pnpm install
$env:UO_SRC="C:\Program Files (x86)\Electronic Arts\Ultima Online Classic"
tools\bats\extract-assets.bat
tools\bats\run-server.bat
tools\bats\run-client.bat
The development client normally runs at:
http://localhost:5173
The project WebSocket server normally runs at:
ws://127.0.0.1:2593/game
A full extraction creates:
apps/client/public/assets/
That directory contains art/gump/anim/static atlases, map chunks, statics, tiledata, hues, multi data, lights, fonts, cliloc, and manifests.
Common commands:
pnpm extract
pnpm extract:ktx2:tool:check
pnpm extract:ktx2:tool:install
pnpm extract:ktx2
CODE0 generates PNG/JSON/bin fallback assets. CODE1 converts existing PNG atlases to CODE2 when CODE3 is available. The client tries KTX2 where present and falls back to PNG when the parser or file is not available.
KTX2 is mainly useful for large texture atlases: smaller transfer, lower VRAM use, and faster GPU upload after transcoding. PNG remains the required fallback and the easiest format for debugging.
| Scenario | Windows | Linux/macOS |
|---|---|---|
| GUI launcher | CODE_0 | CODE_0 |
| Browser client + project server | CODE_0 | CODE_0 |
| WebSocket server only | CODE_0 | CODE_0 |
| WebSocket server + raw TCP for ClassicUO | CODE_0 | CODE_0 |
| WebSocket server + TCP + admin panel | CODE_0 | CODE_0 |
| Vite client only | CODE_0 | CODE_0 |
| Browser client through bridge to an external shard | CODE_0 | CODE_0 |
| Bridge only | CODE_0 | CODE_0 |
Default ports:
| Service | Port |
|---|---|
| Browser client Vite | CODE_0 |
| Project WebSocket server | CODE_0 |
| Raw TCP listener | CODE_0 |
| Bridge | CODE_0 |
| Admin panel | CODE_0 |
| Command | Purpose |
|---|---|
| CODE_0 | install monorepo dependencies |
| CODE_0 | start the server with CODE_0 |
| CODE_0 | start the Vite dev server |
| CODE_0 | build workspaces that define a build script |
| CODE_0 | run workspace tests |
| CODE_0 | run ESLint for the repository |
| CODE_0 | extract assets from UO MUL/UOP files |
| CODE_0 | generate CODE_0 files next to PNG atlases |
| CODE_0 | run the client performance smoke test |
| CODE_0 | capture a client profile |
| CODE_0 | audit server functionality against ServUO |
| CODE_0 | check the ServUO coverage map |
CODE_0 is the runtime engine:
quests, economy, events;
Architectural rule: the engine should not contain concrete game content when that content can live in CODE_0. The engine exposes APIs, indexes, and safe operations; scripts register content and behavior.
CODE_0 is the gameplay layer:
The canonical guide for the current API is:
docs/server-scripting.md
The old pattern of scanning CODE0 or CODE1 directly is an exception. New code should use:
CODE_0 is a web implementation of the UO client:
gumps, animation, and performance budgets.
Useful checks after renderer changes:
pnpm --filter @uo/client run smoke:roof
pnpm --filter @uo/client run smoke:light
pnpm --filter @uo/client build
Full client smoke:
pnpm --filter @uo/client run smoke
The project supports three practical configurations:
browser client -> project WebSocket server
ClassicUO/Razor -> project raw TCP server
browser client -> WebSocket bridge -> external ServUO/RunUO raw TCP shard
This lets the browser client evolve without abandoning protocol compatibility, and it lets the server be tested with native clients.
Local saves live in:
saves/world.json
saves/accounts.json
Locally generated assets live in:
apps/client/public/assets/
These paths are environment data. Do not treat them as source-of-truth review material unless you are intentionally testing persistence migration or the asset pipeline.
| Document | Role |
|---|---|
| CODE_0 | short setup and launch guide |
| CODE_0 | contribution, testing, and licensing rules |
| CODE_0 | full AGPL license text |
| CODE_0 | behavior rules for the public project |
| CODE_0 | repository documentation index |
| CODE_0 | current server scripting rules |
| CODE_0 | launchers, Control Panel, bridge, and environment variables |
| CODE_0 | engine vs scripts split |
| CODE_0 | systems layer overview |
Before a larger change:
git status --short
pnpm test
After server changes:
pnpm --filter @uo/server test
After client changes:
pnpm --filter @uo/client build
pnpm --filter @uo/client run smoke:client-perf
After script changes:
pnpm --filter @uo/server test
pnpm audit:servuo:map:check
After asset pipeline changes:
pnpm extract:ktx2:tool:check
pnpm --filter @uo/extractor run ktx2:dry-run
Before opening a pull request:
facade exists.
use CODE0, CODE1, or CODE_2.
batching, caches, atlases, lazy loading, dirty regions, and fixed-row virtual lists are preferred.
code.
Project code is licensed as CODE_0. The intent is simple: you may use, copy, host, and modify the project, but project changes should return to the community under the same terms when distributed or offered over a network.
This repository does not distribute Ultima Online files. Asset extraction requires your own legal copy of the UO client. Original code in this repository is a separate implementation; for any files ported from or based on external projects, respect the licenses noted in headers, history, and documentation.