..
2025-08-06 22:13:32 -05:00
2025-08-06 22:13:32 -05:00
2025-08-06 22:13:32 -05:00
2025-08-06 22:13:32 -05:00
2025-08-06 22:13:32 -05:00
2025-08-06 22:13:32 -05:00
2025-08-06 22:13:32 -05:00
2025-08-06 22:13:32 -05:00
2025-08-06 22:13:32 -05:00

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

// 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

// 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

// 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:

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:

# 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:

// 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

const CommandTypeCustom CommandType = 100

func (ct CommandType) String() string {
    switch ct {
    case CommandTypeCustom:
        return "custom"
    default:
        return CommandType(ct).String()
    }
}

Custom Handlers

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:

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.