Add README and agent guidelines documentation

README covers building, running, connecting, world data format,
game mechanics, database schema, mudtool usage, and admin system.
AGENTS.md provides architecture overview, concurrency model, coding
conventions, and step-by-step guides for extending the codebase.

Made-with: Cursor
This commit is contained in:
AI Agent
2026-03-14 15:12:49 -06:00
parent 5fd2c10198
commit 3f164e4697
2 changed files with 396 additions and 0 deletions

276
README.md Normal file
View File

@@ -0,0 +1,276 @@
# 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 entirely in TOML files under a `world/` directory. The server reads this at startup — no recompilation needed to change content.
### Directory Structure
```
world/
├── manifest.toml # world name and spawn room
├── races/ # playable races
│ ├── dwarf.toml
│ ├── elf.toml
│ └── ...
├── classes/ # playable classes
│ ├── warrior.toml
│ ├── mage.toml
│ └── ...
└── <region>/ # one directory per region
├── region.toml # region metadata
├── rooms/
│ ├── town_square.toml
│ └── ...
├── npcs/
│ ├── barkeep.toml
│ └── ...
└── objects/
├── rusty_sword.toml
└── ...
```
### manifest.toml
```toml
name = "The Shattered Realm"
spawn_room = "town:town_square"
```
### Room
```toml
name = "Town Square"
description = "A cobblestone square with a fountain."
[exits]
north = "town:tavern"
south = "town:gate"
east = "town:market"
```
Room IDs are `<region>:<filename_stem>`.
### NPC
```toml
name = "Town Guard"
description = "A bored guard."
room = "town:gate"
base_attitude = "neutral" # friendly, neutral, wary, aggressive, hostile
faction = "guards" # optional — attitude shifts propagate to faction
respawn_secs = 90 # optional — respawn timer after death
[dialogue]
greeting = "Move along."
[combat] # optional — omit for weak default stats (20hp/4atk/2def/5xp)
max_hp = 60
attack = 10
defense = 8
xp_reward = 25
```
### Object
```toml
name = "Rusty Sword"
description = "A battered iron blade."
room = "town:cellar"
kind = "weapon" # weapon, armor, consumable, treasure, or omit
takeable = true
[stats]
damage = 5 # for weapons
# armor = 4 # for armor
# heal_amount = 30 # for consumables
```
### Race
```toml
name = "Dwarf"
description = "Stout and unyielding."
[stats]
strength = 1
dexterity = -1
constitution = 2
```
### Class
```toml
name = "Warrior"
description = "Masters of arms and armor."
[base_stats]
max_hp = 120
attack = 14
defense = 12
[growth]
hp_per_level = 15
attack_per_level = 3
defense_per_level = 2
```
## 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.