Overview
Moongate is an open-source Ultima Online server emulator written in C# on .NET 10. It combines Lua scripting, PostgreSQL persistence and Redis-backed login-to-game handoff, with reusable libraries for building server tools and services.
World saves never stop the game: the game loop pauses only to copy the world into memory, about a tenth of a second for 173,000 entities, and the save writes to PostgreSQL in the background, only the entities that changed since the last save. See A save does not stop the game.
Moongate is multi-shard: one login server lists any number of game servers (up to
128), each running its own world with its own database, and players pick one from
the client’s server list. standalone mode runs the login and a single shard in
one process. See Docker login and realms.
Status
Section titled “Status”Under active development. The foundations are in place: networking and packet pipeline, login server and game realms, Lua runtime, PostgreSQL persistence, shard data loading, and client-file readers with movement and line-of-sight queries. On top of them, a player today can:
- Create a character and walk a decorated world, with doors and keys, lights, teleporters and public moongates; see the other players and talk to them; days, weather and seasons pass by region, and dungeons are dark.
- Fight with fists, weapons and bows, block with a shield, die and leave a corpse, and come back as a ghost at an ankh or a healer. Towns have guards, criminals, murder counts and a jail.
- Use the skills, which rise with use: every classic trade has its script, from hiding and stealing to the bard skills and tracking; learn them from trainers and join the NPC guilds.
- Cast all 64 Magery spells from a spellbook or a scroll, sixteen of the seventeen of Necromancy and the first four of Chivalry; drink potions. Monsters cast back.
- Gather and craft: fishing, mining, lumberjacking and the nine crafts (blacksmithing, tailoring, carpentry, tinkering, fletching, cooking, cartography, alchemy, inscription), with repair.
- Buy from and sell to the vendors, keep gold and checks in the bank, tame animals, ride mounts and stable pets, found a player guild, read and write books and bulletin boards, dye clothes.
- Meet NPCs run by Lua scripts: monsters that chase, flee and fight, animals, guards, vendors, healers and stable masters, and the six classic champion spawns.
Much of this is recent and has not been tried with a real client yet. Still missing: houses and boats, party, the chat window and the character profile, runebooks, quests, treasure maps, player vendors, and the modern ruleset with item properties, resistances and special moves. NPCs do not block movement yet, and the town guards do not punish players. See Implementation status for supported behavior and remaining work, and the Roadmap for the order in which the missing systems are built.
Getting started
Section titled “Getting started”To run Moongate, you need your own Ultima Online client data files, PostgreSQL, and Redis 7+. Client data is not included. The First start guide walks through preparing the server root, configuring these dependencies, applying database migrations, and starting the server.
Choose an installation method below. The Linux installer and container image include the .NET runtime; building from source requires the .NET 10 SDK.
Install on Linux
Section titled “Install on Linux”curl -fsSL https://moongate.sh/install.sh | shInstalls the latest release into /opt/moongate and makes moongate and mgctl
available on your path. Supports Linux x64 and ARM64 with glibc. Keep your server
root outside the installation directory so upgrades preserve your configuration
and data. See Install on Linux for options, upgrades and removal.
Docker
Section titled “Docker”Every release publishes a linux/amd64 image to
Docker Hub.
See Run with Docker for first-start configuration, persistent
storage, Docker Compose, logs, and upgrades.
To run on Kubernetes, use the Helm chart.
Build from source
Section titled “Build from source”git clone https://codeberg.org/moongate/moongate.gitcd moongategit switch developdotnet build Moongate.slnx -c Releasedevelop contains unreleased work. Use a release tag
to build a published version. Continue with First start
to configure and run it, or Contributing to work on the code.
Scripting
Section titled “Scripting”Scripts run on the game loop thread in a sandboxed Lua 5.2 runtime powered by
LuaCSharp. Put your startup script in
scripts/init.lua under the server root:
-- scripts/init.lualog.info("booted {Engine} {Version}", engine.name, engine.version)
timer.every(30, function() log.info("tick") wait(2) -- suspends this coroutine without blocking the game loop log.info("two seconds later")end)The runtime provides logging, timers, events, NPC and item scripts, instruction budgets, and generated editor definitions. See Writing Lua scripts for available APIs, reload commands and configuration, and the package README for C# bindings and sandbox limits.
Server guides
Section titled “Server guides”| Area | Guides |
|---|---|
| Configuration and operation | Server configuration, commands, diagnostics |
| Clients | Enhanced Client |
| Storage | PostgreSQL persistence and world saves |
| Protocol and execution | Packets and handlers, game loop and timers |
| Client data | Client files, movement and line-of-sight queries |
| Validation | Test coverage, dependency security audits |
Extending Moongate
Section titled “Extending Moongate”| Goal | Guides |
|---|---|
| Add server behavior | Plugins, Lua modules in C# |
| Add diagnostics | Metric providers |
| Define shard content | Shard data files, TOML templates, NPC spawns |
| Script the game | Lua scripts, gumps, bank |
| Customize data formats | TOML value types |
| Translate server messages | Localization |
The compiled sample plugin demonstrates plugin registration, Lua bindings and a metric provider. The test suite loads it through the real plugin loader.
Libraries
Section titled “Libraries”The ten library packages have their own English READMEs and runnable examples. See NuGet libraries and package verification for the package list, dependencies, and the local verification command.
Documentation
Section titled “Documentation”Browse the full guides and library documentation at moongate.sh. See the changelog for release history and Writing documentation for local previews and page contributions.
Contributing
Section titled “Contributing”Read CONTRIBUTING.md for development setup, coding conventions,
validation commands, and the pull request workflow. Contributions target develop.
Moongate is also a personal project built for the enjoyment of programming. How I use AI explains the maintainer’s approach to AI-assisted migration, testing and design, and the code he chooses to write by hand.
License
Section titled “License”Moongate is licensed under AGPL-3.0-or-later. Third-party attribution is listed in THIRD-PARTY-NOTICES.md.
Made with ❤️ by Tom
