Skip to content

nerdrip/nodeuo

Repository files navigation

Ultima Online Node

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.

Public Repository Status

This project is prepared for public source distribution.

  • Project code is licensed as AGPL-3.0-or-later.
  • Modified versions that are distributed or offered as a network service must make the corresponding source code available to the community under the same license terms.
  • The repository must not contain Ultima Online client files, generated assets, world saves, accounts, passwords, shard secrets, or private player data.
  • Contribution rules are documented in CONTRIBUTING.md.
  • The full license text is in LICENSE.

What Is In This Repository

Area Technology Role
Server Node.js, ESM, ws 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 + sharp 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

Current Direction

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:

  • apps/server owns the engine and world indexes.
  • apps/scripts owns gameplay content.
  • Scripts should use high-level api.game, api.lifecycle, api.systems, _inventory, _movement, _spatial, and registry helpers.
  • The client preserves UO behavior, but rendering, cache, UI, and the asset pipeline are built for the web.
  • PNG assets are always the fallback path. .ktx2 is an optional faster path for VRAM/decode if you generate it with toktx.
  • templates/ is reference material for audits and bug fixes, not runtime code.

Repository Layout

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

Requirements

  • Node.js >=20.11
  • pnpm 9.12.0 through Corepack or a global install
  • Windows .bat launchers or Linux/macOS .sh launchers
  • A local Ultima Online Classic installation for asset extraction
  • Optional Khronos KTX-Software (toktx) for .ktx2 generation

Basic check:

node -v
corepack enable
pnpm -v

Quick Start

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:

  • install the dependencies needed to start the Electron launcher;
  • start the server, browser client, bridge, admin panel, and extractor;
  • run project install/update actions;
  • check and install KTX2/toktx tooling;
  • stream service logs in one window.

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

Asset Pipeline

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

pnpm extract generates PNG/JSON/bin fallback assets. pnpm extract:ktx2 converts existing PNG atlases to .ktx2 when toktx 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.

Runtime Modes

Scenario Windows Linux/macOS
GUI launcher tools\run-control-panel.bat tools/run-control-panel.sh
Browser client + project server tools\bats\run-all.bat tools/sh/run-all.sh
WebSocket server only tools\bats\run-server.bat tools/sh/run-server.sh
WebSocket server + raw TCP for ClassicUO tools\bats\run-server-tcp.bat tools/sh/run-server-tcp.sh
WebSocket server + TCP + admin panel tools\bats\run-server-admin.bat tools/sh/run-server-admin.sh
Vite client only tools\bats\run-client.bat tools/sh/run-client.sh
Browser client through bridge to an external shard tools\bats\run-client-bridge.bat host:port tools/sh/run-client-bridge.sh host:port
Bridge only tools\bats\run-bridge.bat host:port tools/sh/run-bridge.sh host:port

Default ports:

Service Port
Browser client Vite 5173
Project WebSocket server 2593
Raw TCP listener 2594
Bridge 2595
Admin panel 2596

Important PNPM Commands

Command Purpose
pnpm install install monorepo dependencies
pnpm server start the server with node --watch
pnpm client start the Vite dev server
pnpm build build workspaces that define a build script
pnpm test run workspace tests
pnpm lint run ESLint for the repository
pnpm extract extract assets from UO MUL/UOP files
pnpm extract:ktx2 generate .ktx2 files next to PNG atlases
pnpm client:perf-smoke run the client performance smoke test
pnpm client:profile capture a client profile
pnpm audit:servuo audit server functionality against ServUO
pnpm audit:servuo:map:check check the ServUO coverage map

Server

apps/server is the runtime engine:

  • accounts, sessions, and login;
  • WebSocket and optional raw TCP listener;
  • UO binary packets and protocol compatibility;
  • world state: mobiles, items, sectors, parent/child indexes, persistence;
  • movement, visibility, update ranges, pathfinding, and standing Z;
  • combat, notoriety, poison, regen, party, guild, chat, corpses;
  • systems dispatch: spells, crafting, housing, pets, PvP, rewards, bosses, quests, economy, events;
  • admin panel and diagnostics.

Architectural rule: the engine should not contain concrete game content when that content can live in apps/scripts. The engine exposes APIs, indexes, and safe operations; scripts register content and behavior.

Server Scripts

apps/scripts/src is the gameplay layer:

  • player and admin commands;
  • item definitions and item lifecycle scripts;
  • NPC/mobile templates, vendors, and AI;
  • skills, spells, crafting, loot tables;
  • quests, regions, spawns, and events;
  • JSON data in apps/scripts/src/data.

The canonical guide for the current API is:

docs/server-scripting.md

The old pattern of scanning world.items or world.mobiles directly is an exception. New code should use:

  • api.game for gameplay operations and indexed reads;
  • api.lifecycle for hot-reload-safe commands, events, and timers;
  • api.systems for engine domains;
  • _inventory.js, _movement.js, _spatial.js, and _entities.js;
  • declarative defineScript() for simple modules.

Client

apps/client is a web implementation of the UO client:

  • Vite + PixiJS v8;
  • isometric WebGL renderer;
  • map streaming and chunk cache;
  • PNG atlases with optional KTX2/Basis;
  • mobile/static animations, gumps, paperdoll, journal, macro/hotkey flow;
  • dynamic lights from world and equipment;
  • roof/ceiling autohide for buildings;
  • UI that follows ClassicUO behavior while using DOM/WebGL-friendly patterns;
  • smoke tests for protocol, UI, rendering, pathfinder, asset cache, lights, 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

Bridge And Compatibility

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.

Data And Saves

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.

Documentation

Document Role
QUICKSTART.md short setup and launch guide
CONTRIBUTING.md contribution, testing, and licensing rules
LICENSE full AGPL license text
CODE_OF_CONDUCT.md behavior rules for the public project
docs/README.md repository documentation index
docs/server-scripting.md current server scripting rules
tools/README.md launchers, Control Panel, bridge, and environment variables
apps/server/src/content/ARCHITECTURE.md engine vs scripts split
apps/server/src/systems/README.md systems layer overview

Development Workflow

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

Contributions

Before opening a pull request:

  • read CONTRIBUTING.md;
  • explain what changed and why;
  • include tests or manual verification;
  • keep refactors, features, and data changes separate where practical;
  • do not add generated assets, world saves, or private data;
  • make sure the contribution can be licensed as AGPL-3.0-or-later.

Coding Rules

  • Do not migrate scripts back to the old raw runtime API.
  • Do not scan world.items or world.mobiles in hot paths when an indexed facade exists.
  • Do not assign item.parent or mob.x/y/z/map directly from gameplay code; use api.game.item.move, api.game.mobile.move, or api.game.mobile.teleport.
  • Script registrations should be hot-reload-safe through api.lifecycle.
  • The client should preserve UO behavior, but implementation can be web-native: batching, caches, atlases, lazy loading, dirty regions, and fixed-row virtual lists are preferred.
  • templates/ is for audits, comparisons, and bug fixing; it is not runtime code.

License And Legal Notes

Project code is licensed as AGPL-3.0-or-later. 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.

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages