Configuration Guide
This guide reflects the current runtime behavior in Moongate v2.
Configuration Sources
Priority order:
- Command-line arguments
- Environment variables
moongate.jsonin root directory- Defaults
Command-Line Arguments
Current Program command signature supports:
--show-header(bool, defaulttrue)--root-directory(string)--uo-directory(string)--loglevel(LogLevelType, defaultDebug)
Example:
dotnet run --project src/Moongate.Server -- \
--root-directory /opt/moongate \
--uo-directory /opt/uo \
--loglevel Information
Environment Variables
Configuration env support is generic and maps to the full MoongateConfig model:
MOONGATE_ROOT_DIRECTORYMOONGATE_UO_DIRECTORYMOONGATE_<PROPERTY>MOONGATE_<SECTION>__<PROPERTY>MOONGATE_<SECTION>__<SUBSECTION>__<PROPERTY>
Examples:
MOONGATE_HTTP__PORT=8088MOONGATE_HTTP__JWT__SIGNING_KEY=change-meMOONGATE_SPATIAL__SECTOR_ENTER_SYNC_RADIUS=3
Additional runtime env vars (outside MoongateConfig):
MOONGATE_ADMIN_USERNAMEMOONGATE_ADMIN_PASSWORDMOONGATE_UI_DIST
moongate.json
Location:
<RootDirectory>/moongate.json
If missing, bootstrap creates one with default values.
Current Merge Behavior
At startup, bootstrap loads configuration with standard provider precedence:
moongate.jsonMOONGATE_*environment variables (override file values)
Config Model
Top-level shape:
{
"rootDirectory": "/opt/moongate",
"uoDirectory": "/opt/uo",
"logLevel": "Information",
"logPacketData": true,
"isDeveloperMode": false,
"http": {
"isEnabled": true,
"port": 8088,
"websiteUrl": "http://localhost",
"isOpenApiEnabled": true
},
"game": {
"shardName": "Moongate Shard",
"timerTickMilliseconds": 250,
"timerWheelSize": 512,
"idleCpuEnabled": true,
"idleSleepMilliseconds": 1,
"pingServerEnabled": true,
"pingServerPort": 12000
},
"metrics": {
"enabled": true,
"intervalMilliseconds": 1000,
"logEnabled": true,
"logToConsole": false,
"logLevel": "Trace"
},
"scripting": {
"enableFileWatcher": true
},
"llm": {
"isEnabled": false,
"apiKey": null,
"model": "gpt-5-mini",
"baseUrl": null,
"listenerCooldownMilliseconds": 60000,
"idleCooldownMilliseconds": 300000,
"idleNearbyPlayerRange": 12,
"speechRange": 12,
"maxMemoryCharacters": 4000
},
"email": {
"isEnabled": false,
"fromAddress": "noreply@localhost",
"fallbackLocale": "en",
"smtp": {
"host": "localhost",
"port": 25,
"useSsl": false,
"username": null,
"password": null
}
},
"persistence": {
"saveIntervalSeconds": 30
}
}
Game Networking
Relevant game keys for shard reachability checks:
Game.PingServerEnabled(bool, defaulttrue)Game.PingServerPort(int, default12000)
This UDP listener echoes datagrams unchanged and is intended for lightweight monitoring or edge reachability checks. For operational behavior and probe examples, see UDP Ping Server.
Directories
DirectoriesConfig auto-creates directory tree under root using DirectoryType values:
datatemplatesscriptswebsavelogscacheemail/templatesplugins
Scripting
Current scripting runtime option:
Scripting.EnableFileWatcher(bool, defaulttrue)true: enables the centralized runtime watcher forscripts/**/*.lua,templates/**/*.json, anddata/spawns/**/*.json- Lua files are invalidated by path and recompiled on next execution
- reloadable JSON files are reloaded one file at a time on the game loop thread
- manual single-file reload is also available with
reload_template <filePath> false: disables watcher creation entirely
Scripting.LuaBrainMaxBrainsPerTick(int, default0)<= 0: no explicit per-tick cap> 0: limits how many due NPC brains are processed per tick (helps smooth spikes under heavy load)
LLM
Moongate can optionally use OpenAI-backed dialogue for selected NPC brains through the ai_dialogue Lua module.
Relevant keys:
Llm.IsEnabled(bool, defaultfalse)- enables intelligent NPC dialogue
Llm.ApiKey(string?, defaultnull)- OpenAI API key
- if omitted, runtime falls back to
OPENAI_API_KEY - if both are present,
Llm.ApiKeywins
Llm.Model(string, defaultgpt-5-mini)Llm.BaseUrl(string?, defaultnull)- optional OpenAI-compatible endpoint override
Llm.ListenerCooldownMilliseconds(int, default60000)- per-NPC cooldown for player-triggered replies
Llm.IdleCooldownMilliseconds(int, default300000)- per-NPC cooldown for autonomous chatter
Llm.IdleNearbyPlayerRange(int, default12)- idle chatter only runs when at least one player is nearby
Llm.SpeechRange(int, default12)- speech broadcast range when the NPC talks
Llm.MaxMemoryCharacters(int, default4000)- trims persisted memory before prompt injection
Llm.MaxOutputTokenCount(int, default1200)- output token budget for one structured dialogue completion
Implementation note:
ai_dialoguerequests are scheduled through the async work scheduler and run off the game loop- the NPC reply can therefore arrive slightly after the player speech
- this is intentional and prevents slow OpenAI calls from stalling the shard
Recommended production setup:
export OPENAI_API_KEY="sk-..."
Local/dev alternative in moongate.json:
{
"Llm": {
"IsEnabled": true,
"ApiKey": "sk-...",
"Model": "gpt-5-mini"
}
}
For prompt files, memory files, and Lua usage, see Intelligent NPC Dialogue.
Email Templates
Email templates are resolved from:
DirectoriesConfig[DirectoryType.EmailTemplates]
Default bundled templates:
registration_ok(en.subject.sbn,en.text.sbn,en.html.sbn)recover_password(en.subject.sbn,en.text.sbn,en.html.sbn)
Scriban templates receive a global websiteUrl value from Http.WebsiteUrl.
When Email.IsEnabled = false, the runtime uses a no-op sender and does not perform SMTP delivery.
HTTP Endpoints
When HTTP is enabled:
/→ UI frontend when UI hosting is enabled (default)/health→ plain textok/metrics→ Prometheus text format (if metrics factory configured)/scalarand/openapi/*(if OpenAPI enabled)
Branding assets are served from:
DirectoriesConfig[DirectoryType.WebRoot]
Login pages consume public branding metadata from:
/api/branding
Relevant config keys:
Http.AdminLoginLogoPathHttp.PlayerLoginLogoPath
Persistence Setting
Only persistence knob currently exposed:
Persistence.SaveIntervalSeconds(autosave interval)
Docker Notes
For container runs, typical environment:
MOONGATE_ROOT_DIRECTORY=/app
MOONGATE_UO_DIRECTORY=/uo
Mount /app for runtime data and /uo for UO client files.
The most complete runnable examples currently live in:
- Quick Start for local and Docker launch commands
- README.md for top-level onboarding
Previous: Installation Guide | Next: Quick Start