728 lines
18 KiB
Go

package commands
import (
"fmt"
"strings"
)
// RegisterPlayerCommands registers all player-level commands
func RegisterPlayerCommands(cm *CommandManager) error {
commands := []*Command{
// Communication commands
{
Name: "say",
Type: CommandTypePlayer,
Description: "Says something to nearby players",
Usage: "/say <message>",
RequiredLevel: AdminLevelPlayer,
Handler: HandleSay,
},
{
Name: "tell",
Type: CommandTypePlayer,
Description: "Sends a private message to a player",
Usage: "/tell <player> <message>",
RequiredLevel: AdminLevelPlayer,
Handler: HandleTell,
},
{
Name: "yell",
Type: CommandTypePlayer,
Description: "Yells something to a wider area",
Usage: "/yell <message>",
RequiredLevel: AdminLevelPlayer,
Handler: HandleYell,
},
{
Name: "shout",
Type: CommandTypePlayer,
Description: "Shouts something zone-wide",
Usage: "/shout <message>",
RequiredLevel: AdminLevelPlayer,
Handler: HandleShout,
},
{
Name: "ooc",
Type: CommandTypePlayer,
Description: "Sends an out-of-character message",
Usage: "/ooc <message>",
RequiredLevel: AdminLevelPlayer,
Handler: HandleOOC,
},
{
Name: "emote",
Type: CommandTypePlayer,
Description: "Performs an emote",
Usage: "/emote <action>",
RequiredLevel: AdminLevelPlayer,
Handler: HandleEmote,
},
// Group commands
{
Name: "group",
Type: CommandTypePlayer,
Description: "Group management commands",
Usage: "/group <invite|leave|kick|disband> [player]",
RequiredLevel: AdminLevelPlayer,
Handler: HandleGroup,
},
{
Name: "groupsay",
Type: CommandTypePlayer,
Description: "Says something to your group",
Usage: "/groupsay <message>",
RequiredLevel: AdminLevelPlayer,
Handler: HandleGroupSay,
},
{
Name: "gsay",
Type: CommandTypePlayer,
Description: "Says something to your group (short form)",
Usage: "/gsay <message>",
RequiredLevel: AdminLevelPlayer,
Handler: HandleGroupSay,
},
// Guild commands
{
Name: "guild",
Type: CommandTypePlayer,
Description: "Guild management commands",
Usage: "/guild <invite|leave|promote|demote|kick> [player]",
RequiredLevel: AdminLevelPlayer,
Handler: HandleGuild,
},
{
Name: "guildsay",
Type: CommandTypePlayer,
Description: "Says something to your guild",
Usage: "/guildsay <message>",
RequiredLevel: AdminLevelPlayer,
Handler: HandleGuildSay,
},
{
Name: "officersay",
Type: CommandTypePlayer,
Description: "Says something to guild officers",
Usage: "/officersay <message>",
RequiredLevel: AdminLevelPlayer,
Handler: HandleOfficerSay,
},
// Character commands
{
Name: "who",
Type: CommandTypePlayer,
Description: "Lists players online",
Usage: "/who [name pattern]",
RequiredLevel: AdminLevelPlayer,
Handler: HandleWho,
},
{
Name: "time",
Type: CommandTypePlayer,
Description: "Shows current game time",
Usage: "/time",
RequiredLevel: AdminLevelPlayer,
Handler: HandleTime,
},
{
Name: "afk",
Type: CommandTypePlayer,
Description: "Toggles AFK status",
Usage: "/afk [message]",
RequiredLevel: AdminLevelPlayer,
Handler: HandleAFK,
},
{
Name: "anon",
Type: CommandTypePlayer,
Description: "Toggles anonymous status",
Usage: "/anon",
RequiredLevel: AdminLevelPlayer,
Handler: HandleAnonymous,
},
{
Name: "lfg",
Type: CommandTypePlayer,
Description: "Toggles looking for group status",
Usage: "/lfg",
RequiredLevel: AdminLevelPlayer,
Handler: HandleLFG,
},
{
Name: "location",
Type: CommandTypePlayer,
Description: "Shows current location",
Usage: "/location",
RequiredLevel: AdminLevelPlayer,
Handler: HandleLocation,
},
// Item commands
{
Name: "inventory",
Type: CommandTypePlayer,
Description: "Shows inventory information",
Usage: "/inventory",
RequiredLevel: AdminLevelPlayer,
Handler: HandleInventory,
},
{
Name: "consider",
Type: CommandTypePlayer,
Description: "Considers a target",
Usage: "/consider [target]",
RequiredLevel: AdminLevelPlayer,
Handler: HandleConsider,
},
// Trade commands
{
Name: "trade",
Type: CommandTypePlayer,
Description: "Trade management",
Usage: "/trade <start|accept|reject|cancel> [player]",
RequiredLevel: AdminLevelPlayer,
Handler: HandleTrade,
},
// Quest commands
{
Name: "quest",
Type: CommandTypePlayer,
Description: "Quest management",
Usage: "/quest <list|abandon|share> [quest_id]",
RequiredLevel: AdminLevelPlayer,
Handler: HandleQuest,
},
// Misc commands
{
Name: "help",
Type: CommandTypePlayer,
Description: "Shows available commands",
Usage: "/help [command]",
RequiredLevel: AdminLevelPlayer,
Handler: HandleHelp,
},
{
Name: "quit",
Type: CommandTypePlayer,
Description: "Safely logs out of the game",
Usage: "/quit",
RequiredLevel: AdminLevelPlayer,
Handler: HandleQuit,
},
}
for _, cmd := range commands {
if err := cm.Register(cmd); err != nil {
return fmt.Errorf("failed to register command %s: %w", cmd.Name, err)
}
}
return nil
}
// HandleSay handles the /say command
func HandleSay(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
if err := ctx.ValidateArgumentCount(1, -1); err != nil {
ctx.AddErrorMessage("Usage: /say <message>")
return nil
}
message := ctx.RawArguments
// TODO: Implement actual zone-wide say broadcast
// For now, just confirm to the player
ctx.AddMessage(ChannelSay, ColorWhite, fmt.Sprintf("You say, \"%s\"", message))
// TODO: Send to nearby players in zone
// zone.SendNearbyMessage(ctx.Player.GetPosition(), ChannelSay,
// fmt.Sprintf("%s says, \"%s\"", playerName, message))
return nil
}
// HandleTell handles the /tell command
func HandleTell(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
if err := ctx.ValidateArgumentCount(2, -1); err != nil {
ctx.AddErrorMessage("Usage: /tell <player> <message>")
return nil
}
targetName := ctx.Arguments[0]
message := ctx.GetRemainingArguments(1)
// TODO: Implement actual tell system
// For now, just show what would be sent
ctx.AddMessage(ChannelPrivateTell, ColorWhite,
fmt.Sprintf("You tell %s, \"%s\"", targetName, message))
// TODO: Find target player and send message
// if targetPlayer := world.FindPlayerByName(targetName); targetPlayer != nil {
// targetPlayer.SendMessage(ChannelPrivateTell,
// fmt.Sprintf("%s tells you, \"%s\"", playerName, message))
// } else {
// ctx.AddErrorMessage(fmt.Sprintf("Player '%s' not found", targetName))
// }
return nil
}
// HandleYell handles the /yell command
func HandleYell(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
if err := ctx.ValidateArgumentCount(1, -1); err != nil {
ctx.AddErrorMessage("Usage: /yell <message>")
return nil
}
message := ctx.RawArguments
ctx.AddMessage(ChannelYell, ColorWhite, fmt.Sprintf("You yell, \"%s\"", message))
// TODO: Send to wider area in zone
return nil
}
// HandleShout handles the /shout command
func HandleShout(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
if err := ctx.ValidateArgumentCount(1, -1); err != nil {
ctx.AddErrorMessage("Usage: /shout <message>")
return nil
}
message := ctx.RawArguments
ctx.AddMessage(ChannelShout, ColorWhite, fmt.Sprintf("You shout, \"%s\"", message))
// TODO: Send zone-wide
return nil
}
// HandleOOC handles the /ooc command
func HandleOOC(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
if err := ctx.ValidateArgumentCount(1, -1); err != nil {
ctx.AddErrorMessage("Usage: /ooc <message>")
return nil
}
message := ctx.RawArguments
playerName := ctx.GetPlayerName()
ctx.AddMessage(ChannelOutOfCharacter, ColorWhite,
fmt.Sprintf("[OOC] %s: %s", playerName, message))
// TODO: Send to zone OOC channel
return nil
}
// HandleEmote handles the /emote command
func HandleEmote(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
if err := ctx.ValidateArgumentCount(1, -1); err != nil {
ctx.AddErrorMessage("Usage: /emote <action>")
return nil
}
action := ctx.RawArguments
playerName := ctx.GetPlayerName()
ctx.AddMessage(ChannelEmote, ColorWhite, fmt.Sprintf("%s %s", playerName, action))
// TODO: Send emote to nearby players
return nil
}
// HandleGroup handles the /group command
func HandleGroup(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
if ctx.ArgumentCount() == 0 {
ctx.AddErrorMessage("Usage: /group <invite|leave|kick|disband> [player]")
return nil
}
subCommand := strings.ToLower(ctx.Arguments[0])
switch subCommand {
case "invite":
if ctx.ArgumentCount() < 2 {
ctx.AddErrorMessage("Usage: /group invite <player>")
return nil
}
targetName := ctx.Arguments[1]
// TODO: Implement group invite
ctx.AddStatusMessage(fmt.Sprintf("Invited %s to group", targetName))
case "leave":
// TODO: Implement group leave
ctx.AddStatusMessage("Left group")
case "kick":
if ctx.ArgumentCount() < 2 {
ctx.AddErrorMessage("Usage: /group kick <player>")
return nil
}
targetName := ctx.Arguments[1]
// TODO: Implement group kick
ctx.AddStatusMessage(fmt.Sprintf("Kicked %s from group", targetName))
case "disband":
// TODO: Implement group disband
ctx.AddStatusMessage("Disbanded group")
default:
ctx.AddErrorMessage("Usage: /group <invite|leave|kick|disband> [player]")
}
return nil
}
// HandleGroupSay handles the /groupsay and /gsay commands
func HandleGroupSay(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
if err := ctx.ValidateArgumentCount(1, -1); err != nil {
ctx.AddErrorMessage("Usage: /groupsay <message>")
return nil
}
message := ctx.RawArguments
playerName := ctx.GetPlayerName()
// TODO: Check if player is in a group
ctx.AddMessage(ChannelGroupSay, ColorWhite,
fmt.Sprintf("[Group] %s: %s", playerName, message))
// TODO: Send to group members
return nil
}
// HandleGuild handles the /guild command
func HandleGuild(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
if ctx.ArgumentCount() == 0 {
// TODO: Show guild information
ctx.AddStatusMessage("Guild information (not yet implemented)")
return nil
}
subCommand := strings.ToLower(ctx.Arguments[0])
switch subCommand {
case "invite":
if ctx.ArgumentCount() < 2 {
ctx.AddErrorMessage("Usage: /guild invite <player>")
return nil
}
targetName := ctx.Arguments[1]
// TODO: Implement guild invite
ctx.AddStatusMessage(fmt.Sprintf("Invited %s to guild", targetName))
case "leave":
// TODO: Implement guild leave
ctx.AddStatusMessage("Left guild")
default:
ctx.AddErrorMessage("Usage: /guild <invite|leave|promote|demote|kick> [player]")
}
return nil
}
// HandleGuildSay handles the /guildsay command
func HandleGuildSay(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
if err := ctx.ValidateArgumentCount(1, -1); err != nil {
ctx.AddErrorMessage("Usage: /guildsay <message>")
return nil
}
message := ctx.RawArguments
playerName := ctx.GetPlayerName()
// TODO: Check if player is in a guild
ctx.AddMessage(ChannelGuildSay, ColorWhite,
fmt.Sprintf("[Guild] %s: %s", playerName, message))
return nil
}
// HandleOfficerSay handles the /officersay command
func HandleOfficerSay(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
if err := ctx.ValidateArgumentCount(1, -1); err != nil {
ctx.AddErrorMessage("Usage: /officersay <message>")
return nil
}
message := ctx.RawArguments
playerName := ctx.GetPlayerName()
// TODO: Check if player is guild officer
ctx.AddMessage(ChannelOfficerSay, ColorWhite,
fmt.Sprintf("[Officer] %s: %s", playerName, message))
return nil
}
// HandleWho handles the /who command
func HandleWho(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
// TODO: Implement player listing
ctx.AddMessage(ChannelWho, ColorWhite, "Players online:")
ctx.AddMessage(ChannelWho, ColorWhite, fmt.Sprintf(" %s (You)", ctx.GetPlayerName()))
ctx.AddMessage(ChannelWho, ColorWhite, "Total: 1 player online")
return nil
}
// HandleTime handles the /time command
func HandleTime(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
// TODO: Implement game time system
ctx.AddStatusMessage("Game time: 12:00 PM (not yet implemented)")
return nil
}
// HandleAFK handles the /afk command
func HandleAFK(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
afkMessage := ""
if ctx.ArgumentCount() > 0 {
afkMessage = ctx.RawArguments
}
// TODO: Toggle AFK status
if afkMessage != "" {
ctx.AddStatusMessage(fmt.Sprintf("AFK status set with message: %s", afkMessage))
} else {
ctx.AddStatusMessage("AFK status toggled")
}
return nil
}
// HandleAnonymous handles the /anon command
func HandleAnonymous(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
// TODO: Toggle anonymous status
ctx.AddStatusMessage("Anonymous status toggled")
return nil
}
// HandleLFG handles the /lfg command
func HandleLFG(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
// TODO: Toggle LFG status
ctx.AddStatusMessage("Looking for group status toggled")
return nil
}
// HandleLocation handles the /location command
func HandleLocation(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
// TODO: Get actual player position
zoneName := ctx.GetZoneName()
ctx.AddStatusMessage(fmt.Sprintf("Location: %s (coordinates not yet implemented)", zoneName))
return nil
}
// HandleInventory handles the /inventory command
func HandleInventory(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
// TODO: Show inventory information
ctx.AddStatusMessage("Inventory information (not yet implemented)")
return nil
}
// HandleConsider handles the /consider command
func HandleConsider(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
targetName := ctx.GetTargetName()
if targetName == "No Target" && ctx.ArgumentCount() > 0 {
targetName = ctx.Arguments[0]
}
if targetName == "No Target" {
ctx.AddErrorMessage("You must target something or specify a target name")
return nil
}
// TODO: Implement consider system
ctx.AddStatusMessage(fmt.Sprintf("You consider %s... (not yet implemented)", targetName))
return nil
}
// HandleTrade handles the /trade command
func HandleTrade(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
if ctx.ArgumentCount() == 0 {
ctx.AddErrorMessage("Usage: /trade <start|accept|reject|cancel> [player]")
return nil
}
subCommand := strings.ToLower(ctx.Arguments[0])
switch subCommand {
case "start":
if ctx.ArgumentCount() < 2 {
ctx.AddErrorMessage("Usage: /trade start <player>")
return nil
}
targetName := ctx.Arguments[1]
ctx.AddStatusMessage(fmt.Sprintf("Trade initiated with %s", targetName))
case "accept":
ctx.AddStatusMessage("Trade accepted")
case "reject":
ctx.AddStatusMessage("Trade rejected")
case "cancel":
ctx.AddStatusMessage("Trade cancelled")
default:
ctx.AddErrorMessage("Usage: /trade <start|accept|reject|cancel> [player]")
}
return nil
}
// HandleQuest handles the /quest command
func HandleQuest(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
if ctx.ArgumentCount() == 0 {
ctx.AddErrorMessage("Usage: /quest <list|abandon|share> [quest_id]")
return nil
}
subCommand := strings.ToLower(ctx.Arguments[0])
switch subCommand {
case "list":
// TODO: List active quests
ctx.AddStatusMessage("Active quests (not yet implemented)")
case "abandon":
if ctx.ArgumentCount() < 2 {
ctx.AddErrorMessage("Usage: /quest abandon <quest_id>")
return nil
}
questID := ctx.Arguments[1]
ctx.AddStatusMessage(fmt.Sprintf("Abandoned quest %s", questID))
case "share":
if ctx.ArgumentCount() < 2 {
ctx.AddErrorMessage("Usage: /quest share <quest_id>")
return nil
}
questID := ctx.Arguments[1]
ctx.AddStatusMessage(fmt.Sprintf("Shared quest %s", questID))
default:
ctx.AddErrorMessage("Usage: /quest <list|abandon|share> [quest_id]")
}
return nil
}
// HandleHelp handles the /help command
func HandleHelp(ctx *CommandContext) error {
// TODO: Show available commands based on admin level
ctx.AddMessage(ChannelCommands, ColorWhite, "Available commands:")
ctx.AddMessage(ChannelCommands, ColorWhite, "/say <message> - Say something to nearby players")
ctx.AddMessage(ChannelCommands, ColorWhite, "/tell <player> <message> - Send private message")
ctx.AddMessage(ChannelCommands, ColorWhite, "/who - List online players")
ctx.AddMessage(ChannelCommands, ColorWhite, "/time - Show game time")
ctx.AddMessage(ChannelCommands, ColorWhite, "/location - Show current location")
ctx.AddMessage(ChannelCommands, ColorWhite, "/help - Show this help")
return nil
}
// HandleQuit handles the /quit command
func HandleQuit(ctx *CommandContext) error {
if err := ctx.RequirePlayer(); err != nil {
return err
}
ctx.AddStatusMessage("Logging out safely...")
// TODO: Implement safe logout
// if ctx.Client != nil {
// ctx.Client.Disconnect()
// }
return nil
}