Skip to content

Overview

Moongate logo

CI on develop Dependency security audit on main Latest release License: AGPL-3.0-or-later

Documentation at moongate.sh Container image .NET 10 Lua 5.2 scripting Buy me a coffee

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.

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.

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.

Terminal window
curl -fsSL https://moongate.sh/install.sh | sh

Installs 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.

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.

Terminal window
git clone https://codeberg.org/moongate/moongate.git
cd moongate
git switch develop
dotnet build Moongate.slnx -c Release

develop 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.

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.lua
log.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.

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
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.

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.

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.

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.

Moongate is licensed under AGPL-3.0-or-later. Third-party attribution is listed in THIRD-PARTY-NOTICES.md.

Made with ❤️ by Tom

Buy me a coffee