Reviewed-on: #6
MUD Server
A text-based multiplayer RPG (MUD) that accepts connections over SSH. Written in Rust with a data-driven world definition system — rooms, NPCs, objects, races, and classes are all defined in TOML files and can be changed without recompiling.
Requirements
- Rust toolchain (edition 2021+)
- SQLite is bundled via
rusqlite— no system SQLite needed
Building
cargo build # builds both mudserver and mudtool
cargo build --release # optimized build
This produces two binaries:
mudserver— the game servermudtool— database management CLI/TUI
Running the Server
./target/debug/mudserver
Options
| Flag | Default | Description |
|---|---|---|
--port, -p |
2222 |
SSH listen port |
--world, -w |
./world |
Path to world data directory |
--db, -d |
./mudserver.db |
Path to SQLite database file |
The server generates a random SSH host key on each startup. The database is created automatically if it doesn't exist.
Connecting
Any SSH client works. The username becomes the player's character name:
ssh mycharacter@localhost -p 2222
Password and key auth are both accepted (no real authentication — this is a game server, not a secure shell).
Environment
Set RUST_LOG to control log verbosity:
RUST_LOG=info ./target/release/mudserver # default
RUST_LOG=debug ./target/release/mudserver # verbose
World Data
The world is defined in TOML files under world/. The server loads them at startup — no recompilation needed to change content.
Directory structure
world/
├── manifest.toml
├── races/
├── classes/
├── guilds/
├── spells/
└── <region>/
├── region.toml
├── rooms/
├── npcs/
└── objects/
Schema reference
Each folder contains a reference doc listing every TOML option:
| Location | Reference |
|---|---|
world/ |
MANIFEST.md — world name, spawn room, layout |
world/races/ |
RACES.md — stats, body, natural attacks, resistances, etc. |
world/classes/ |
CLASSES.md — base stats, growth, hidden, guild |
world/guilds/ |
GUILDS.md — spells, growth, race restrictions |
world/spells/ |
SPELLS.md — damage, cost, cooldown, effects |
world/<region>/ |
REGION.md — region metadata |
world/<region>/rooms/ |
ROOMS.md — name, description, exits |
world/<region>/npcs/ |
NPCS.md — attitude, race/class, combat, dialogue |
world/<region>/objects/ |
OBJECTS.md — slot, stats, takeable |
Game Mechanics
Tick System
The game runs on a 3-second tick cycle. Combat actions, status effects, NPC AI, and passive regeneration all resolve on ticks rather than immediately.
Combat
Combat is tick-based. When a player enters combat (via attack or NPC aggro), they choose actions each tick:
| Command | Effect |
|---|---|
attack / a |
Strike the enemy (default if no action queued) |
defend / def |
Brace — doubles effective defense for the tick |
flee |
Attempt to escape (success chance based on DEF stat) |
use <item> |
Use a consumable during combat |
Any NPC can be attacked. Attacking non-hostile NPCs carries attitude penalties (-30 individual, -15 faction) and a warning message but is not blocked.
Attitude System
Every NPC tracks a per-player attitude value from -100 to +100:
| Range | Label | Behavior |
|---|---|---|
| 50 to 100 | Friendly | Will talk |
| 10 to 49 | Neutral | Will talk |
| -24 to 9 | Wary | Will talk |
| -25 to -74 | Aggressive | Won't talk, attackable |
| -75 to -100 | Hostile | Attacks on sight |
Attitudes shift from combat interactions and propagate through NPC factions.
Status Effects
Effects like poison and regeneration are stored in the database and tick down every cycle — including while the player is offline. Effects are cleared on death.
Passive Regeneration
Players out of combat regenerate 5% of max HP every 5 ticks (~15 seconds).
Database
SQLite with WAL mode. Tables:
players— character data (stats, inventory, equipment, room, admin flag)npc_attitudes— per-player, per-NPC attitude valuesserver_settings— key-value config (e.g.registration_open)status_effects— active effects with remaining tick counters
The database is accessed through a GameDb trait, making backend swaps possible.
mudtool
Database management tool with both CLI and TUI modes.
CLI
mudtool --db ./mudserver.db players list
mudtool --db ./mudserver.db players show hero
mudtool --db ./mudserver.db players set-admin hero true
mudtool --db ./mudserver.db players delete hero
mudtool --db ./mudserver.db settings list
mudtool --db ./mudserver.db settings set registration_open false
mudtool --db ./mudserver.db attitudes list hero
mudtool --db ./mudserver.db attitudes set hero town:guard 50
TUI
mudtool --db ./mudserver.db tui
Interactive interface with tabs for Players, Settings, and Attitudes. Navigate with arrow keys, Tab/1/2/3 to switch tabs, a to toggle admin, d to delete, Enter to edit values, q to quit.
Admin System
Players with the is_admin flag can use in-game admin commands:
admin promote <player> Grant admin
admin demote <player> Revoke admin
admin kick <player> Disconnect player
admin teleport <room_id> Warp to room
admin registration on|off Toggle new player creation
admin announce <message> Broadcast to all
admin heal [player] Full heal (self or target)
admin info <player> Detailed player info
admin setattitude <player> <npc> <value> Set attitude
admin list All players (online + saved)
The first admin must be set via mudtool players set-admin <name> true.
Registration Gate
New player creation can be toggled:
mudtool settings set registration_open false # block new players
mudtool settings set registration_open true # allow new players (default)
Or in-game: admin registration off / admin registration on. Existing players can always log in regardless of this setting.