Table of Contents

Configuration Guide

This guide reflects the current runtime behavior in Moongate v2.

Configuration Sources

Priority order:

  1. Command-line arguments
  2. Environment variables
  3. moongate.json in root directory
  4. Defaults

Command-Line Arguments

Current Program command signature supports:

  • --show-header (bool, default true)
  • --root-directory (string)
  • --uo-directory (string)
  • --loglevel (LogLevelType, default Debug)

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_DIRECTORY
  • MOONGATE_UO_DIRECTORY
  • MOONGATE_<PROPERTY>
  • MOONGATE_<SECTION>__<PROPERTY>
  • MOONGATE_<SECTION>__<SUBSECTION>__<PROPERTY>

Examples:

  • MOONGATE_HTTP__PORT=8088
  • MOONGATE_HTTP__JWT__SIGNING_KEY=change-me
  • MOONGATE_SPATIAL__SECTOR_ENTER_SYNC_RADIUS=3

Additional runtime env vars (outside MoongateConfig):

  • MOONGATE_ADMIN_USERNAME
  • MOONGATE_ADMIN_PASSWORD
  • MOONGATE_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:

  1. moongate.json
  2. MOONGATE_* 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, default true)
  • Game.PingServerPort (int, default 12000)

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:

  • data
  • templates
  • scripts
  • web
  • save
  • logs
  • cache
  • email/templates
  • plugins

Scripting

Current scripting runtime option:

  • Scripting.EnableFileWatcher (bool, default true)
    • true: enables the centralized runtime watcher for scripts/**/*.lua, templates/**/*.json, and data/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, default 0)
    • <= 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, default false)
    • enables intelligent NPC dialogue
  • Llm.ApiKey (string?, default null)
    • OpenAI API key
    • if omitted, runtime falls back to OPENAI_API_KEY
    • if both are present, Llm.ApiKey wins
  • Llm.Model (string, default gpt-5-mini)
  • Llm.BaseUrl (string?, default null)
    • optional OpenAI-compatible endpoint override
  • Llm.ListenerCooldownMilliseconds (int, default 60000)
    • per-NPC cooldown for player-triggered replies
  • Llm.IdleCooldownMilliseconds (int, default 300000)
    • per-NPC cooldown for autonomous chatter
  • Llm.IdleNearbyPlayerRange (int, default 12)
    • idle chatter only runs when at least one player is nearby
  • Llm.SpeechRange (int, default 12)
    • speech broadcast range when the NPC talks
  • Llm.MaxMemoryCharacters (int, default 4000)
    • trims persisted memory before prompt injection
  • Llm.MaxOutputTokenCount (int, default 1200)
    • output token budget for one structured dialogue completion

Implementation note:

  • ai_dialogue requests 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 text ok
  • /metrics → Prometheus text format (if metrics factory configured)
  • /scalar and /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.AdminLoginLogoPath
  • Http.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:


Previous: Installation Guide | Next: Quick Start