aboutsummaryrefslogtreecommitdiff
path: root/AGENTS.md
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-11 04:46:27 -0400
committerhistoria <[not public]>2026-06-11 08:58:37 +0000
commit1b9e2da3b3c438d8dc53d3489725dd5ba0022777 (patch)
tree62264f24420bf4cfaa734942c65cc8dd45ba3d3b /AGENTS.md
parent06c02a697e5daf8832a462de5970dd4c0e13a02c (diff)
downloadthehouseoficarus-1b9e2da3b3c438d8dc53d3489725dd5ba0022777.tar.gz
feat: web client, get/drop updates and fixes
Diffstat (limited to 'AGENTS.md')
-rw-r--r--AGENTS.md79
1 files changed, 45 insertions, 34 deletions
diff --git a/AGENTS.md b/AGENTS.md
index 6834676..5de818b 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -2,6 +2,8 @@
Third Collapse — a Runescape-like sci-fi MUD written in Go. Data-driven via YAML files. No database, no ORM.
+See `TODO.md` for the full project overview, implemented features, and roadmap.
+
## Build & Run
```bash
@@ -11,23 +13,26 @@ make test # go test ./...
make vet # go vet ./...
```
-Single dependency: `gopkg.in/yaml.v3`.
+Binary accepts `--config <path>` (defaults to `config.yaml`). If no config found, starts telnet on :4000.
+
+Dependencies: `gopkg.in/yaml.v3`, `github.com/gorilla/websocket`.
## Package Map
```
-cmd/mud/main.go Entry point — wires server, game, tick engine
-internal/net/ Telnet server, TCP session state machine, room hub
-internal/game/ Session handler, login, command dispatch, all game logic
+cmd/mud/main.go Entry point — config loading, multi-listener, tick engine
+internal/config/ YAML config (telnet, http, https listeners)
+internal/net/ Conn interface (tcp + websocket), session state, hub, IAC echo
+internal/game/ Login flow, command dispatch, input sanitization, all game logic
internal/action/ Behavior structs (GatherConfig, TalkConfig, etc.), Action, drop tables
-internal/player/ Player struct, skills, inventory, XP, Account YAML persistence
+internal/player/ Player struct, skills, inventory, XP, name/password validation
internal/world/ Room, MobDef, MobInstance, ObjState, ground items, wandering
internal/combat/ Combat state tracking, OSRS-style combat formulas
internal/object/ ItemDef, ObjectDef, item/object YAML loaders
internal/engine/ Tick scheduler — 600ms interval, subscriber pattern
```
-`internal/game/` is the largest package and contains most command implementations as `cmd_*.go` files.
+`internal/game/` is the largest package and contains most command implementations as `cmd_*.go` and `action_*.go` files.
## Key Conventions
@@ -37,7 +42,11 @@ internal/engine/ Tick scheduler — 600ms interval, subscriber pattern
**No database.** Everything is flat YAML files. Account passwords use sha256 + 16-byte random salt.
-**Tick-driven.** The world runs on a 600ms tick. Combat, gathering, regen, wandering, respawns all advance per tick. See `cmd/mud/main.go` for the subscription loop.
+**Transport-agnostic.** The `Conn` interface (`internal/net/conn.go`) abstracts the transport layer. `tcpConn` wraps a raw `net.Conn` for telnet. `wsConn` wraps `gorilla/websocket.Conn` for the web client. Game code works with `*Session` regardless of transport.
+
+**Input sanitization.** `HandleSession` strips Unicode control characters (ANSI escapes, nulls, etc.) from every input line before dispatch. Account/character names validated to `[A-Za-z0-9 ]{1,30}`. Input truncated to 1024 bytes. Password echo suppressed via IAC ECHO (telnet) and OSC sequences (web). WebSocket origin checked against host header.
+
+**Tick-driven.** The world runs on a 600ms tick. Combat, gathering, regen, wandering, respawns, shared depletion, woodcutting timers all advance per tick. See `cmd/mud/main.go` for the subscription loop.
## Two State Systems
@@ -52,12 +61,13 @@ internal/engine/ Tick scheduler — 600ms interval, subscriber pattern
3. Switch on command word
4. Most commands call into `cmd_*.go` files
-Commands that need an object/mob interaction route through `StartAction()` in `action.go`, which:
-1. Normalizes verb (mine/chop/fish → gather, talk/speak/ask → talk, pull/push → toggle)
-2. Searches object instances in room
-3. Falls back to mob instances if no object matches
-4. Loads the behavior from YAML
-5. Routes to type-specific handler (startGather, startTalk, startUse, startToggle)
+Actions that interact with objects/mobs route through `StartAction()` in `action.go`, which:
+1. Normalizes verb (mine/chop/fish/cut → gather, talk/speak/ask → talk, pull/push → toggle)
+2. Checks for ambiguous matches (multiple object types)
+3. Searches object instances in room
+4. Falls back to mob instances if no object matches
+5. Loads the behavior from YAML
+6. Routes to type-specific handler (startGather, startTalk, startUse, startToggle)
## Adding a New Skill
@@ -68,7 +78,7 @@ Commands that need an object/mob interaction route through `StartAction()` in `a
5. Place the object in a room YAML in `data/rooms/`
6. Create any resource items in `data/items/`
-Woodcutting is the next planned gathering skill — same pattern as mining (see `data/behaviors/mine_copper.yaml`).
+Set `xp` on the behavior to award XP on successful gathers. Set `shared_deplete` for tree-style depletion, or use per-drop `depletes: true` for rock-style depletion.
## Adding a New Production Skill
@@ -80,37 +90,38 @@ Same as gathering but use `type: use` behavior (see `UseConfig` in `internal/act
2. Add a case in `handleGameCommand()` in `internal/game/game.go`
3. Update `data/help/` YAML files
+## Two Depletion Mechanics
+
+**Per-drop depletion** (mining, regular trees): Set `depletes: true` on a drop entry. The resource depletes on first successful gather of that drop. Rocks don't show despawn timers when not depleted.
+
+**Shared depletion** (higher-tier trees): Set `shared_deplete: <ticks>` on the behavior. A shared timer counts down while anyone is chopping; when it hits 0, the next successful gather depletes the tree for all players. The timer regenerates back to max when no one is chopping. `WoodcuttingTick` manages this in `internal/game/tick.go`.
+
## Data Files
```
data/rooms/<id>.yaml Room definitions (exits, objects, mobs, spawns, on_enter)
data/items/<id>.yaml Item definitions (stats, equip slot, tool type, speed)
-data/mobs/<id>.yaml Mob definitions (combat stats, drops, behavior, wandering)
-data/objects/<id>.yaml Object definitions (name, behavior, hidden)
-data/behaviors/<id>.yaml Behaviors (gather, talk, use, toggle configs)
-data/drops/<id>.yaml Shared drop tables (weighted item lists)
-data/help/<id>.yaml Help topics
-data/players/accounts/ Account YAML (gitignored)
-data/players/characters/ Character YAML (gitignored)
+data/mobs/<id>.yaml Mob definitions (combat stats, drops, behavior — NO wander config)
+data/objects/<id>.yaml Object definitions (name, behavior, hidden)
+data/behaviors/<id>.yaml Behaviors (gather, talk, use, toggle configs)
+data/drops/<id>.yaml Shared drop tables (weighted item lists)
+data/help/<id>.yaml Help topics
+data/players/accounts/ Account YAML (gitignored)
+data/players/characters/ Character YAML (gitignored)
```
-See `WORLDBUILDING.md` for full YAML format reference with examples.
+Wander config (`wander_rooms`, `wander_interval`) is set per-instance in room YAML — mob defs are generic. Mobs wander via legal (unconditioned) room exits; objects teleport between rooms in their list.
-## Current State
-
-- 21 skills defined, 2 implemented (Mining, Fishing)
-- 4 behavior types: gather, use, talk, toggle
-- Combat system complete (melee only — Ranged not implemented yet)
-- 11 rooms with conditional exits and on-enter scripts
-- Talk system: dialog trees with conditions, item give/take, flag setting, teleport, heal
-- Account-wide alias system
-- No shops, banks, or quest system yet (though talk + flags already supports quest logic)
+See `WORLDBUILDING.md` for full YAML format reference with examples.
## Places to Be Careful
- `StartAction` searches objects first, then mobs. A mob must have `behavior:` set on its YAML def to be interactable.
-- Exits changed from `map[ExitDir]int` to `map[ExitDir]ExitDef` — old `north: 2` still works via custom `UnmarshalYAML`.
-- `CheckExitCondition` was unified into `checkCondition` — there's only one condition evaluator now.
+- Exits changed from `map[ExitDir]int` to `map[ExitDir]ExitDef` — old `north: 2` still works via custom `UnmarshalYAML`. Same pattern used for `RoomMob` (supports both `"man"` and `{id: man, ...}`).
+- `checkCondition` is the single condition evaluator — used by exits, talk options, on-enter scripts, and toggle checks.
- Object `Hidden: true` means the object doesn't appear in room listings but is still interactable.
- Alias expansion happens before command dispatch. An alias can shadow a built-in command.
-- `say` preserves case in the message (alias expansion preserves case, and the dispatch extracts the original input text for say).
+- `say` preserves case (alias expansion preserves case, and the dispatch extracts the original input text for say).
+- `get`, `drop`, and `quit` cancel the player's active action (gathering, use, etc.).
+- `findGroundMatches` and `findInventoryMatches` support bidirectional prefix matching — `"iron ax"` matches `"iron axe"`.
+- Mob wander config is per-instance in room YAML via `RoomMob`, not on `MobDef`. Mobs without `wander_interval` in the room stay still.