eq2go/internal/commands/README.md

327 lines
9.4 KiB
Markdown

# EQ2Go Command System
The EQ2Go command system provides a comprehensive framework for handling player commands, admin commands, and console commands in the EverQuest II server emulator. This system is converted from the original C++ EQ2EMu codebase while leveraging modern Go patterns and practices.
## Architecture Overview
The command system consists of several key components:
- **CommandManager**: Central registry for all commands with thread-safe operations
- **CommandContext**: Execution context providing access to players, zones, arguments, and messaging
- **Command Types**: Different command categories (Player, Admin, Console, etc.)
- **Subcommand Support**: Hierarchical command structure for complex operations
## Core Components
### CommandManager
The `CommandManager` is the central hub that:
- Registers commands by name with case-insensitive lookup
- Manages subcommands under parent commands
- Executes commands with proper admin level checking
- Parses raw command strings into structured contexts
### CommandContext
The `CommandContext` provides:
- Type-safe argument parsing (string, int, float, bool)
- Message queuing with channel and color support
- Validation helpers for argument counts and requirements
- Access to game objects (player, zone, target)
- Result storage for complex operations
### Command Types
Commands are categorized by type:
- **Player Commands** (`CommandTypePlayer`): Basic player actions like `/say`, `/tell`, `/who`
- **Admin Commands** (`CommandTypeAdmin`): GM/Admin tools like `/kick`, `/ban`, `/summon`
- **Console Commands** (`CommandTypeConsole`): Server management from console
- **Specialized Types**: Spawn, Zone, Guild, Item, and Quest commands
## Admin Levels
The system supports four admin levels:
- **Player** (0): Basic player commands
- **Guide** (100): Helper/guide commands
- **GM** (200): Game master commands
- **Admin** (300): Full administrative access
## Usage Examples
### Basic Command Registration
```go
// Initialize the command system
cm, err := InitializeCommands()
if err != nil {
log.Fatalf("Failed to initialize commands: %v", err)
}
// Register a custom command
customCmd := &Command{
Name: "custom",
Type: CommandTypePlayer,
Description: "A custom command",
Usage: "/custom <arg>",
RequiredLevel: AdminLevelPlayer,
Handler: func(ctx *CommandContext) error {
if err := ctx.ValidateArgumentCount(1, 1); err != nil {
ctx.AddErrorMessage("Usage: /custom <arg>")
return nil
}
arg := ctx.Arguments[0]
ctx.AddStatusMessage(fmt.Sprintf("You used custom command with: %s", arg))
return nil
},
}
err = cm.Register(customCmd)
if err != nil {
log.Printf("Failed to register custom command: %v", err)
}
```
### Executing Commands
```go
// Parse and execute a command from a client
err := ExecuteCommand(cm, "/say Hello everyone!", client)
if err != nil {
log.Printf("Command execution failed: %v", err)
}
```
### Subcommand Registration
```go
// Register a parent command
parentCmd := &Command{
Name: "manage",
Type: CommandTypeAdmin,
RequiredLevel: AdminLevelGM,
Handler: func(ctx *CommandContext) error {
ctx.AddErrorMessage("Usage: /manage <player|item|zone> [options]")
return nil
},
}
cm.Register(parentCmd)
// Register subcommands
playerSubCmd := &Command{
Name: "player",
Type: CommandTypeAdmin,
RequiredLevel: AdminLevelGM,
Handler: func(ctx *CommandContext) error {
// Handle player management
return nil
},
}
cm.RegisterSubCommand("manage", playerSubCmd)
```
## Command Implementation
### Player Commands
Located in `player.go`, these include:
- **Communication**: `/say`, `/tell`, `/yell`, `/shout`, `/ooc`, `/emote`
- **Group Management**: `/group`, `/groupsay`, `/gsay`
- **Guild Management**: `/guild`, `/guildsay`, `/officersay`
- **Information**: `/who`, `/time`, `/location`, `/consider`
- **Character**: `/afk`, `/anon`, `/lfg`, `/inventory`
- **Utilities**: `/help`, `/quit`, `/trade`, `/quest`
### Admin Commands
Located in `admin.go`, these include:
- **Player Management**: `/kick`, `/ban`, `/unban`, `/summon`, `/goto`
- **Communication**: `/broadcast`, `/announce`
- **Spawn Management**: `/spawn`, `/npc`
- **Item Management**: `/item`, `/giveitem`
- **Character Modification**: `/modify`, `/setlevel`, `/setclass`
- **Server Management**: `/reload`, `/shutdown`, `/cancelshutdown`
- **GM Utilities**: `/invisible`, `/invulnerable`, `/speed`, `/flymode`
- **Information**: `/info`, `/version`
### Console Commands
Located in `console.go`, these include prefixed versions of admin commands for console use:
- **Player Management**: `console_ban`, `console_kick`, `console_unban`
- **Communication**: `console_broadcast`, `console_announce`, `console_tell`
- **Information**: `console_guild`, `player`, `console_zone`, `console_who`
- **Server Management**: `console_reload`, `console_shutdown`, `exit`
- **MOTD Management**: `getmotd`, `setmotd`
- **Rules Management**: `rules`
## Message Channels and Colors
Commands can send messages through various channels:
### Channels
- `ChannelSay` (8): Local say messages
- `ChannelTell` (28): Private messages
- `ChannelBroadcast` (92): Server-wide broadcasts
- `ChannelError` (3): Error messages
- `ChannelStatus` (4): Status updates
### Colors
- `ColorWhite` (254): Standard text
- `ColorRed` (3): Errors and warnings
- `ColorYellow` (5): Status messages
- `ColorChatRelation` (4): Relationship text
## Error Handling
The command system provides comprehensive error handling:
```go
func HandleExampleCommand(ctx *CommandContext) error {
// Validate player is present
if err := ctx.RequirePlayer(); err != nil {
return err
}
// Validate argument count
if err := ctx.ValidateArgumentCount(1, 3); err != nil {
ctx.AddErrorMessage("Usage: /example <required> [optional1] [optional2]")
return nil
}
// Validate admin level
if err := ctx.RequireAdminLevel(AdminLevelGM); err != nil {
return err
}
// Command logic here...
return nil
}
```
## Testing
The command system includes comprehensive tests in `commands_test.go`:
```bash
# Run all command tests
go test ./internal/commands -v
# Run specific test
go test ./internal/commands -run TestCommandManager_Execute
```
Tests cover:
- Command registration and retrieval
- Argument parsing and validation
- Message handling
- Admin level checking
- Subcommand functionality
- Error conditions
## Integration with Server
To integrate the command system with the server:
```go
// Initialize commands during server startup
commandManager, err := commands.InitializeCommands()
if err != nil {
log.Fatalf("Failed to initialize commands: %v", err)
}
// Handle incoming command from client
func handleClientCommand(client ClientInterface, rawCommand string) {
err := commands.ExecuteCommand(commandManager, rawCommand, client)
if err != nil {
log.Printf("Command execution error: %v", err)
}
}
```
## Thread Safety
The command system is designed to be thread-safe:
- CommandManager uses read/write mutexes for concurrent access
- CommandContext uses mutexes for message and result storage
- All operations are safe for concurrent use
## Extension Points
The system is designed for easy extension:
### Custom Command Types
```go
const CommandTypeCustom CommandType = 100
func (ct CommandType) String() string {
switch ct {
case CommandTypeCustom:
return "custom"
default:
return CommandType(ct).String()
}
}
```
### Custom Handlers
```go
func MyCustomHandler(ctx *CommandContext) error {
// Custom command logic
ctx.AddStatusMessage("Custom command executed!")
return nil
}
```
## Performance Considerations
- Commands are indexed by name in a hash map for O(1) lookup
- Case-insensitive matching uses normalized lowercase keys
- Message batching reduces client communication overhead
- Argument parsing is lazy and type-safe
## Migration from C++
Key differences from the original C++ implementation:
1. **Type Safety**: Go's type system prevents many runtime errors
2. **Memory Management**: Automatic garbage collection eliminates memory leaks
3. **Concurrency**: Native goroutine support for concurrent operations
4. **Error Handling**: Explicit error returns instead of exceptions
5. **Testing**: Built-in testing framework with comprehensive coverage
## Future Enhancements
Planned improvements:
- Lua script integration for dynamic commands
- Command aliasing system
- Advanced permission system
- Command cooldowns and rate limiting
- Audit logging for admin commands
- Dynamic command loading/unloading
## Troubleshooting
### Common Issues
**Command Not Found**: Ensure command is registered and name matches exactly
**Insufficient Privileges**: Check admin level requirements
**Argument Validation**: Use proper argument count validation
**Interface Errors**: Ensure client implements ClientInterface correctly
### Debug Output
Enable debug output for command execution:
```go
ctx.AddDefaultMessage(fmt.Sprintf("Debug: Command %s executed with %d args",
ctx.CommandName, ctx.ArgumentCount()))
```
## Conclusion
The EQ2Go command system provides a robust, extensible framework for handling all types of game commands while maintaining compatibility with the original EverQuest II protocol. The system's modular design and comprehensive testing ensure reliability and ease of maintenance.