Code Structure
Code Structure
Section titled “Code Structure”Package Organization
Section titled “Package Organization”TalesMUD follows a layered architecture. The dependency direction flows inward:
mudserver → service → repository, never the reverse.
pkg/├── entities/ — Data models (no business logic, no DB access)├── repository/ — SQLite data access (depends on entities)├── service/ — Business logic (depends on repository, entities)├── server/ — HTTP API (depends on service)├── mudserver/ — WebSocket game server (depends on service)│ └── game/ — Game engine, commands, combat└── scripts/ — Lua scripting engine (depends on service)Key Patterns
Section titled “Key Patterns”Facade Pattern
Section titled “Facade Pattern”The service/facade.go provides a single access point to all services:
type Facade interface { Users() UserService Characters() CharacterService Rooms() RoomService Items() ItemService NPCs() NPCService Dialogs() DialogService Quests() QuestService Skills() SkillService Scripts() ScriptService Loot() LootService Parties() PartyService Runner() RunnerService}The game engine holds a Facade reference. This decouples the game logic from specific service implementations.
Generic Repository
Section titled “Generic Repository”pkg/repository/sqlite_generic.go provides a generic CRUD repository:
type GenericRepository[T any] struct { db *sql.DB tableName string}
func (r *GenericRepository[T]) FindByID(id string) (*T, error) { row := r.db.QueryRow("SELECT data FROM "+r.tableName+" WHERE id = ?", id) var jsonData string if err := row.Scan(&jsonData); err != nil { return nil, err } var entity T json.Unmarshal([]byte(jsonData), &entity) return &entity, nil}Command Interface
Section titled “Command Interface”Commands implement a simple interface:
type Command interface { Keys() []string // Command aliases Execute(ctx *GameContext, args string)}The CommandProcessor tries each registered command’s Keys() against the player input.
Commands also have a RoomProcessor variant for room-specific commands.
Trait Composition
Section titled “Trait Composition”Entities use Go struct embedding for trait composition:
type Character struct { *entities.Entity // ID, Created, Updated traits.BelongsUser // UserID traits.CurrentRoom // RoomID // ... character-specific fields}Adding a New Entity Type
Section titled “Adding a New Entity Type”- Define the struct in
pkg/entities/yourtype/ - Create a repository interface and SQLite implementation in
pkg/repository/ - Add a service interface and implementation in
pkg/service/ - Add the service to the Facade interface and implementation
- Add REST API handlers in
pkg/server/handler/ - Register routes in
pkg/server/server.go
Lua Modules
Section titled “Lua Modules”Each tales.* module is implemented as a Go file in:
pkg/scripts/runner/lua/modules/├── items_module.go├── rooms_module.go├── characters_module.go├── npcs_module.go├── dialogs_module.go├── quests_module.go├── game_module.go└── utils_module.goEach module registers functions into the Lua VM state.
Next Steps
Section titled “Next Steps”- Development Setup — Environment setup
- Build from Source — Build process