198 lines
6.4 KiB
Markdown
198 lines
6.4 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
cargo build # builds both mudserver and mudtool
|
|
cargo build --release # optimized build
|
|
```
|
|
|
|
This produces two binaries:
|
|
- `mudserver` — the game server
|
|
- `mudtool` — database management CLI/TUI
|
|
|
|
## Running the Server
|
|
|
|
```bash
|
|
./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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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/MANIFEST.md) — world name, spawn room, layout |
|
|
| `world/races/` | [RACES.md](world/races/RACES.md) — stats, body, natural attacks, resistances, etc. |
|
|
| `world/classes/` | [CLASSES.md](world/classes/CLASSES.md) — base stats, growth, hidden, guild |
|
|
| `world/guilds/` | [GUILDS.md](world/guilds/GUILDS.md) — spells, growth, race restrictions |
|
|
| `world/spells/` | [SPELLS.md](world/spells/SPELLS.md) — damage, cost, cooldown, effects |
|
|
| `world/<region>/` | [REGION.md](world/town/REGION.md) — region metadata |
|
|
| `world/<region>/rooms/` | [ROOMS.md](world/town/rooms/ROOMS.md) — name, description, exits |
|
|
| `world/<region>/npcs/` | [NPCS.md](world/town/npcs/NPCS.md) — attitude, race/class, combat, dialogue |
|
|
| `world/<region>/objects/` | [OBJECTS.md](world/town/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 values
|
|
- `server_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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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.
|