938 lines
24 KiB
Go
938 lines
24 KiB
Go
package commands
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// RegisterAdminCommands registers all admin-level commands
|
|
func RegisterAdminCommands(cm *CommandManager) error {
|
|
commands := []*Command{
|
|
// Player management commands
|
|
{
|
|
Name: "kick",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Kicks a player from the server",
|
|
Usage: "/kick <player> [reason]",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleKick,
|
|
},
|
|
{
|
|
Name: "ban",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Bans a player from the server",
|
|
Usage: "/ban <player> [duration] [reason]",
|
|
RequiredLevel: AdminLevelAdmin,
|
|
Handler: HandleBan,
|
|
},
|
|
{
|
|
Name: "unban",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Unbans a player",
|
|
Usage: "/unban <player>",
|
|
RequiredLevel: AdminLevelAdmin,
|
|
Handler: HandleUnban,
|
|
},
|
|
{
|
|
Name: "summon",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Summons a player to your location",
|
|
Usage: "/summon <player>",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleSummon,
|
|
},
|
|
{
|
|
Name: "goto",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Teleports you to a player or location",
|
|
Usage: "/goto <player|x y z>",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleGoto,
|
|
},
|
|
{
|
|
Name: "zone",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Zone management commands",
|
|
Usage: "/zone <player> <zone_name>",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleZonePlayer,
|
|
},
|
|
|
|
// Communication commands
|
|
{
|
|
Name: "broadcast",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Broadcasts a message to all players",
|
|
Usage: "/broadcast <message>",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleBroadcast,
|
|
},
|
|
{
|
|
Name: "announce",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Announces a message to all players",
|
|
Usage: "/announce <message>",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleAnnounce,
|
|
},
|
|
|
|
// Spawn management commands
|
|
{
|
|
Name: "spawn",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Spawn management commands",
|
|
Usage: "/spawn <create|remove|list|set> [options]",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleSpawn,
|
|
},
|
|
{
|
|
Name: "npc",
|
|
Type: CommandTypeAdmin,
|
|
Description: "NPC management commands",
|
|
Usage: "/npc <create|remove|edit> [options]",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleNPC,
|
|
},
|
|
|
|
// Item commands
|
|
{
|
|
Name: "item",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Item management commands",
|
|
Usage: "/item <give|remove|create> [options]",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleItem,
|
|
},
|
|
{
|
|
Name: "giveitem",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Gives an item to a player",
|
|
Usage: "/giveitem <player> <item_id> [quantity]",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleGiveItem,
|
|
},
|
|
|
|
// Character modification commands
|
|
{
|
|
Name: "modify",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Modification commands",
|
|
Usage: "/modify <character|spawn|zone|quest|item> [options]",
|
|
RequiredLevel: AdminLevelAdmin,
|
|
Handler: HandleModify,
|
|
},
|
|
{
|
|
Name: "setlevel",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Sets a player's level",
|
|
Usage: "/setlevel <player> <level>",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleSetLevel,
|
|
},
|
|
{
|
|
Name: "setclass",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Sets a player's class",
|
|
Usage: "/setclass <player> <class_id>",
|
|
RequiredLevel: AdminLevelAdmin,
|
|
Handler: HandleSetClass,
|
|
},
|
|
|
|
// Server management commands
|
|
{
|
|
Name: "reload",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Reloads server data",
|
|
Usage: "/reload <spells|quests|zones|items|all>",
|
|
RequiredLevel: AdminLevelAdmin,
|
|
Handler: HandleReload,
|
|
},
|
|
{
|
|
Name: "shutdown",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Shuts down the server",
|
|
Usage: "/shutdown [time_minutes] [reason]",
|
|
RequiredLevel: AdminLevelAdmin,
|
|
Handler: HandleShutdown,
|
|
},
|
|
{
|
|
Name: "cancelshutdown",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Cancels a scheduled shutdown",
|
|
Usage: "/cancelshutdown",
|
|
RequiredLevel: AdminLevelAdmin,
|
|
Handler: HandleCancelShutdown,
|
|
},
|
|
|
|
// GM utility commands
|
|
{
|
|
Name: "invisible",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Toggles GM invisibility",
|
|
Usage: "/invisible",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleInvisible,
|
|
},
|
|
{
|
|
Name: "invulnerable",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Toggles invulnerability",
|
|
Usage: "/invulnerable",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleInvulnerable,
|
|
},
|
|
{
|
|
Name: "speed",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Sets movement speed",
|
|
Usage: "/speed <multiplier>",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleSpeed,
|
|
},
|
|
{
|
|
Name: "flymode",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Toggles fly mode",
|
|
Usage: "/flymode",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleFlyMode,
|
|
},
|
|
|
|
// Information commands
|
|
{
|
|
Name: "info",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Shows detailed information about target",
|
|
Usage: "/info [target]",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleInfo,
|
|
},
|
|
{
|
|
Name: "version",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Shows server version information",
|
|
Usage: "/version",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleVersion,
|
|
},
|
|
|
|
// Testing commands
|
|
{
|
|
Name: "test",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Testing command for development",
|
|
Usage: "/test [parameters]",
|
|
RequiredLevel: AdminLevelAdmin,
|
|
Handler: HandleTest,
|
|
},
|
|
}
|
|
|
|
for _, cmd := range commands {
|
|
if err := cm.Register(cmd); err != nil {
|
|
return fmt.Errorf("failed to register admin command %s: %w", cmd.Name, err)
|
|
}
|
|
}
|
|
|
|
// Register subcommands
|
|
if err := registerModifySubcommands(cm); err != nil {
|
|
return fmt.Errorf("failed to register modify subcommands: %w", err)
|
|
}
|
|
|
|
if err := registerSpawnSubcommands(cm); err != nil {
|
|
return fmt.Errorf("failed to register spawn subcommands: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// registerModifySubcommands registers subcommands for the /modify command
|
|
func registerModifySubcommands(cm *CommandManager) error {
|
|
subcommands := []*Command{
|
|
{
|
|
Name: "character",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Modifies character attributes",
|
|
Usage: "/modify character <player> <attribute> <value>",
|
|
RequiredLevel: AdminLevelAdmin,
|
|
Handler: HandleModifyCharacter,
|
|
},
|
|
{
|
|
Name: "spawn",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Modifies spawn attributes",
|
|
Usage: "/modify spawn <spawn_id> <attribute> <value>",
|
|
RequiredLevel: AdminLevelAdmin,
|
|
Handler: HandleModifySpawn,
|
|
},
|
|
{
|
|
Name: "zone",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Modifies zone attributes",
|
|
Usage: "/modify zone <zone_id> <attribute> <value>",
|
|
RequiredLevel: AdminLevelAdmin,
|
|
Handler: HandleModifyZone,
|
|
},
|
|
}
|
|
|
|
for _, subcmd := range subcommands {
|
|
if err := cm.RegisterSubCommand("modify", subcmd); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// registerSpawnSubcommands registers subcommands for the /spawn command
|
|
func registerSpawnSubcommands(cm *CommandManager) error {
|
|
subcommands := []*Command{
|
|
{
|
|
Name: "create",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Creates a new spawn",
|
|
Usage: "/spawn create <type> [options]",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleSpawnCreate,
|
|
},
|
|
{
|
|
Name: "remove",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Removes a spawn",
|
|
Usage: "/spawn remove <spawn_id>",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleSpawnRemove,
|
|
},
|
|
{
|
|
Name: "list",
|
|
Type: CommandTypeAdmin,
|
|
Description: "Lists spawns in area",
|
|
Usage: "/spawn list [radius]",
|
|
RequiredLevel: AdminLevelGM,
|
|
Handler: HandleSpawnList,
|
|
},
|
|
}
|
|
|
|
for _, subcmd := range subcommands {
|
|
if err := cm.RegisterSubCommand("spawn", subcmd); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleKick handles the /kick command
|
|
func HandleKick(ctx *CommandContext) error {
|
|
if err := ctx.ValidateArgumentCount(1, -1); err != nil {
|
|
ctx.AddErrorMessage("Usage: /kick <player> [reason]")
|
|
return nil
|
|
}
|
|
|
|
playerName := ctx.Arguments[0]
|
|
reason := "Kicked by administrator"
|
|
if ctx.ArgumentCount() > 1 {
|
|
reason = ctx.GetRemainingArguments(1)
|
|
}
|
|
|
|
// TODO: Implement actual kick functionality
|
|
ctx.AddStatusMessage(fmt.Sprintf("Kicked player '%s' with reason: %s", playerName, reason))
|
|
|
|
// TODO: Find and disconnect player
|
|
// if player := world.FindPlayerByName(playerName); player != nil {
|
|
// player.Disconnect(reason)
|
|
// broadcast to admins about kick
|
|
// } else {
|
|
// ctx.AddErrorMessage(fmt.Sprintf("Player '%s' not found", playerName))
|
|
// }
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleBan handles the /ban command
|
|
func HandleBan(ctx *CommandContext) error {
|
|
if err := ctx.ValidateArgumentCount(1, -1); err != nil {
|
|
ctx.AddErrorMessage("Usage: /ban <player> [duration] [reason]")
|
|
return nil
|
|
}
|
|
|
|
playerName := ctx.Arguments[0]
|
|
duration := "permanent"
|
|
reason := "Banned by administrator"
|
|
|
|
if ctx.ArgumentCount() > 1 {
|
|
duration = ctx.Arguments[1]
|
|
}
|
|
if ctx.ArgumentCount() > 2 {
|
|
reason = ctx.GetRemainingArguments(2)
|
|
}
|
|
|
|
// TODO: Implement actual ban functionality
|
|
ctx.AddStatusMessage(fmt.Sprintf("Banned player '%s' for %s with reason: %s",
|
|
playerName, duration, reason))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleUnban handles the /unban command
|
|
func HandleUnban(ctx *CommandContext) error {
|
|
if err := ctx.ValidateArgumentCount(1, 1); err != nil {
|
|
ctx.AddErrorMessage("Usage: /unban <player>")
|
|
return nil
|
|
}
|
|
|
|
playerName := ctx.Arguments[0]
|
|
|
|
// TODO: Implement actual unban functionality
|
|
ctx.AddStatusMessage(fmt.Sprintf("Unbanned player '%s'", playerName))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleSummon handles the /summon command
|
|
func HandleSummon(ctx *CommandContext) error {
|
|
if err := ctx.RequirePlayer(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := ctx.ValidateArgumentCount(1, 1); err != nil {
|
|
ctx.AddErrorMessage("Usage: /summon <player>")
|
|
return nil
|
|
}
|
|
|
|
targetName := ctx.Arguments[0]
|
|
|
|
// TODO: Implement actual summon functionality
|
|
ctx.AddStatusMessage(fmt.Sprintf("Summoned player '%s' to your location", targetName))
|
|
|
|
// TODO: Find target player and teleport to admin location
|
|
// if target := world.FindPlayerByName(targetName); target != nil {
|
|
// adminPos := ctx.Player.GetPosition()
|
|
// target.Teleport(adminPos.X, adminPos.Y, adminPos.Z, ctx.Zone.GetID())
|
|
// } else {
|
|
// ctx.AddErrorMessage(fmt.Sprintf("Player '%s' not found", targetName))
|
|
// }
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleGoto handles the /goto command
|
|
func HandleGoto(ctx *CommandContext) error {
|
|
if err := ctx.RequirePlayer(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := ctx.ValidateArgumentCount(1, 3); err != nil {
|
|
ctx.AddErrorMessage("Usage: /goto <player> or /goto <x> <y> <z>")
|
|
return nil
|
|
}
|
|
|
|
if ctx.ArgumentCount() == 1 {
|
|
// Go to player
|
|
targetName := ctx.Arguments[0]
|
|
// TODO: Implement teleport to player
|
|
ctx.AddStatusMessage(fmt.Sprintf("Teleported to player '%s'", targetName))
|
|
} else if ctx.ArgumentCount() == 3 {
|
|
// Go to coordinates
|
|
x := ctx.GetArgumentFloat(0, 0)
|
|
y := ctx.GetArgumentFloat(1, 0)
|
|
z := ctx.GetArgumentFloat(2, 0)
|
|
|
|
// TODO: Implement teleport to coordinates
|
|
ctx.AddStatusMessage(fmt.Sprintf("Teleported to coordinates (%.2f, %.2f, %.2f)", x, y, z))
|
|
} else {
|
|
ctx.AddErrorMessage("Usage: /goto <player> or /goto <x> <y> <z>")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleZonePlayer handles the /zone command
|
|
func HandleZonePlayer(ctx *CommandContext) error {
|
|
if err := ctx.ValidateArgumentCount(2, 2); err != nil {
|
|
ctx.AddErrorMessage("Usage: /zone <player> <zone_name>")
|
|
return nil
|
|
}
|
|
|
|
playerName := ctx.Arguments[0]
|
|
zoneName := ctx.Arguments[1]
|
|
|
|
// TODO: Implement zone transfer
|
|
ctx.AddStatusMessage(fmt.Sprintf("Zoned player '%s' to '%s'", playerName, zoneName))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleBroadcast handles the /broadcast command
|
|
func HandleBroadcast(ctx *CommandContext) error {
|
|
if err := ctx.ValidateArgumentCount(1, -1); err != nil {
|
|
ctx.AddErrorMessage("Usage: /broadcast <message>")
|
|
return nil
|
|
}
|
|
|
|
message := ctx.RawArguments
|
|
adminName := ctx.GetPlayerName()
|
|
|
|
// TODO: Implement server-wide broadcast
|
|
ctx.AddMessage(ChannelBroadcast, ColorYellow,
|
|
fmt.Sprintf("[BROADCAST] %s: %s", adminName, message))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleAnnounce handles the /announce command
|
|
func HandleAnnounce(ctx *CommandContext) error {
|
|
if err := ctx.ValidateArgumentCount(1, -1); err != nil {
|
|
ctx.AddErrorMessage("Usage: /announce <message>")
|
|
return nil
|
|
}
|
|
|
|
message := ctx.RawArguments
|
|
|
|
// TODO: Implement server announcement
|
|
ctx.AddMessage(ChannelBroadcast, ColorRed, fmt.Sprintf("[ANNOUNCEMENT] %s", message))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleSpawn handles the main /spawn command
|
|
func HandleSpawn(ctx *CommandContext) error {
|
|
if ctx.ArgumentCount() == 0 {
|
|
ctx.AddErrorMessage("Usage: /spawn <create|remove|list|set> [options]")
|
|
ctx.AddErrorMessage("Use /spawn <subcommand> for specific help")
|
|
return nil
|
|
}
|
|
|
|
// Subcommands are handled by the command manager
|
|
return fmt.Errorf("spawn subcommand '%s' not found", ctx.Arguments[0])
|
|
}
|
|
|
|
// HandleSpawnCreate handles the /spawn create subcommand
|
|
func HandleSpawnCreate(ctx *CommandContext) error {
|
|
if err := ctx.RequirePlayer(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := ctx.ValidateArgumentCount(1, -1); err != nil {
|
|
ctx.AddErrorMessage("Usage: /spawn create <type> [name] [level]")
|
|
return nil
|
|
}
|
|
|
|
spawnType := ctx.Arguments[0]
|
|
spawnName := "New Spawn"
|
|
spawnLevel := 1
|
|
|
|
if ctx.ArgumentCount() > 1 {
|
|
spawnName = ctx.Arguments[1]
|
|
}
|
|
if ctx.ArgumentCount() > 2 {
|
|
spawnLevel = ctx.GetArgumentInt(2, 1)
|
|
}
|
|
|
|
// TODO: Implement spawn creation
|
|
ctx.AddStatusMessage(fmt.Sprintf("Created %s spawn '%s' (level %d) at your location",
|
|
spawnType, spawnName, spawnLevel))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleSpawnRemove handles the /spawn remove subcommand
|
|
func HandleSpawnRemove(ctx *CommandContext) error {
|
|
if err := ctx.ValidateArgumentCount(1, 1); err != nil {
|
|
ctx.AddErrorMessage("Usage: /spawn remove <spawn_id>")
|
|
return nil
|
|
}
|
|
|
|
spawnID := ctx.GetArgumentInt(0, 0)
|
|
if spawnID <= 0 {
|
|
ctx.AddErrorMessage("Invalid spawn ID")
|
|
return nil
|
|
}
|
|
|
|
// TODO: Implement spawn removal
|
|
ctx.AddStatusMessage(fmt.Sprintf("Removed spawn with ID %d", spawnID))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleSpawnList handles the /spawn list subcommand
|
|
func HandleSpawnList(ctx *CommandContext) error {
|
|
if err := ctx.RequirePlayer(); err != nil {
|
|
return err
|
|
}
|
|
|
|
radius := 50.0 // Default radius
|
|
if ctx.ArgumentCount() > 0 {
|
|
radius = ctx.GetArgumentFloat(0, 50.0)
|
|
}
|
|
|
|
// TODO: Implement spawn listing
|
|
ctx.AddStatusMessage(fmt.Sprintf("Spawns within %.1f units:", radius))
|
|
ctx.AddStatusMessage(" ID: 1, Name: Test NPC, Level: 10, Distance: 5.2")
|
|
ctx.AddStatusMessage("Total: 1 spawn found")
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleNPC handles the /npc command
|
|
func HandleNPC(ctx *CommandContext) error {
|
|
if ctx.ArgumentCount() == 0 {
|
|
ctx.AddErrorMessage("Usage: /npc <create|remove|edit> [options]")
|
|
return nil
|
|
}
|
|
|
|
subCommand := strings.ToLower(ctx.Arguments[0])
|
|
|
|
switch subCommand {
|
|
case "create":
|
|
// TODO: Implement NPC creation
|
|
ctx.AddStatusMessage("NPC creation (not yet implemented)")
|
|
|
|
case "remove":
|
|
// TODO: Implement NPC removal
|
|
ctx.AddStatusMessage("NPC removal (not yet implemented)")
|
|
|
|
case "edit":
|
|
// TODO: Implement NPC editing
|
|
ctx.AddStatusMessage("NPC editing (not yet implemented)")
|
|
|
|
default:
|
|
ctx.AddErrorMessage("Usage: /npc <create|remove|edit> [options]")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleItem handles the /item command
|
|
func HandleItem(ctx *CommandContext) error {
|
|
if ctx.ArgumentCount() == 0 {
|
|
ctx.AddErrorMessage("Usage: /item <give|remove|create> [options]")
|
|
return nil
|
|
}
|
|
|
|
subCommand := strings.ToLower(ctx.Arguments[0])
|
|
|
|
switch subCommand {
|
|
case "give":
|
|
if ctx.ArgumentCount() < 3 {
|
|
ctx.AddErrorMessage("Usage: /item give <player> <item_id> [quantity]")
|
|
return nil
|
|
}
|
|
return handleItemGive(ctx)
|
|
|
|
case "remove":
|
|
// TODO: Implement item removal
|
|
ctx.AddStatusMessage("Item removal (not yet implemented)")
|
|
|
|
case "create":
|
|
// TODO: Implement item creation
|
|
ctx.AddStatusMessage("Item creation (not yet implemented)")
|
|
|
|
default:
|
|
ctx.AddErrorMessage("Usage: /item <give|remove|create> [options]")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// handleItemGive handles giving items to players
|
|
func handleItemGive(ctx *CommandContext) error {
|
|
playerName := ctx.Arguments[1]
|
|
itemID := ctx.GetArgumentInt(2, 0)
|
|
quantity := ctx.GetArgumentInt(3, 1)
|
|
|
|
if itemID <= 0 {
|
|
ctx.AddErrorMessage("Invalid item ID")
|
|
return nil
|
|
}
|
|
|
|
// TODO: Implement item giving
|
|
ctx.AddStatusMessage(fmt.Sprintf("Gave %d x item %d to player '%s'",
|
|
quantity, itemID, playerName))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleGiveItem handles the /giveitem command
|
|
func HandleGiveItem(ctx *CommandContext) error {
|
|
if err := ctx.ValidateArgumentCount(2, 3); err != nil {
|
|
ctx.AddErrorMessage("Usage: /giveitem <player> <item_id> [quantity]")
|
|
return nil
|
|
}
|
|
|
|
playerName := ctx.Arguments[0]
|
|
itemID := ctx.GetArgumentInt(1, 0)
|
|
quantity := ctx.GetArgumentInt(2, 1)
|
|
|
|
if itemID <= 0 {
|
|
ctx.AddErrorMessage("Invalid item ID")
|
|
return nil
|
|
}
|
|
|
|
// TODO: Implement item giving
|
|
ctx.AddStatusMessage(fmt.Sprintf("Gave %d x item %d to player '%s'",
|
|
quantity, itemID, playerName))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleModify handles the main /modify command
|
|
func HandleModify(ctx *CommandContext) error {
|
|
if ctx.ArgumentCount() == 0 {
|
|
ctx.AddErrorMessage("Usage: /modify <character|spawn|zone|quest|item> [options]")
|
|
return nil
|
|
}
|
|
|
|
// Subcommands are handled by the command manager
|
|
return fmt.Errorf("modify subcommand '%s' not found", ctx.Arguments[0])
|
|
}
|
|
|
|
// HandleModifyCharacter handles the /modify character subcommand
|
|
func HandleModifyCharacter(ctx *CommandContext) error {
|
|
if err := ctx.ValidateArgumentCount(3, 3); err != nil {
|
|
ctx.AddErrorMessage("Usage: /modify character <player> <attribute> <value>")
|
|
return nil
|
|
}
|
|
|
|
playerName := ctx.Arguments[0]
|
|
attribute := ctx.Arguments[1]
|
|
value := ctx.Arguments[2]
|
|
|
|
// TODO: Implement character modification
|
|
ctx.AddStatusMessage(fmt.Sprintf("Modified %s's %s to %s", playerName, attribute, value))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleModifySpawn handles the /modify spawn subcommand
|
|
func HandleModifySpawn(ctx *CommandContext) error {
|
|
if err := ctx.ValidateArgumentCount(3, 3); err != nil {
|
|
ctx.AddErrorMessage("Usage: /modify spawn <spawn_id> <attribute> <value>")
|
|
return nil
|
|
}
|
|
|
|
spawnID := ctx.GetArgumentInt(0, 0)
|
|
attribute := ctx.Arguments[1]
|
|
value := ctx.Arguments[2]
|
|
|
|
if spawnID <= 0 {
|
|
ctx.AddErrorMessage("Invalid spawn ID")
|
|
return nil
|
|
}
|
|
|
|
// TODO: Implement spawn modification
|
|
ctx.AddStatusMessage(fmt.Sprintf("Modified spawn %d's %s to %s", spawnID, attribute, value))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleModifyZone handles the /modify zone subcommand
|
|
func HandleModifyZone(ctx *CommandContext) error {
|
|
if err := ctx.ValidateArgumentCount(3, 3); err != nil {
|
|
ctx.AddErrorMessage("Usage: /modify zone <zone_id> <attribute> <value>")
|
|
return nil
|
|
}
|
|
|
|
zoneID := ctx.GetArgumentInt(0, 0)
|
|
attribute := ctx.Arguments[1]
|
|
value := ctx.Arguments[2]
|
|
|
|
if zoneID <= 0 {
|
|
ctx.AddErrorMessage("Invalid zone ID")
|
|
return nil
|
|
}
|
|
|
|
// TODO: Implement zone modification
|
|
ctx.AddStatusMessage(fmt.Sprintf("Modified zone %d's %s to %s", zoneID, attribute, value))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleSetLevel handles the /setlevel command
|
|
func HandleSetLevel(ctx *CommandContext) error {
|
|
if err := ctx.ValidateArgumentCount(2, 2); err != nil {
|
|
ctx.AddErrorMessage("Usage: /setlevel <player> <level>")
|
|
return nil
|
|
}
|
|
|
|
playerName := ctx.Arguments[0]
|
|
level := ctx.GetArgumentInt(1, 1)
|
|
|
|
if level < 1 || level > 100 {
|
|
ctx.AddErrorMessage("Level must be between 1 and 100")
|
|
return nil
|
|
}
|
|
|
|
// TODO: Implement level setting
|
|
ctx.AddStatusMessage(fmt.Sprintf("Set %s's level to %d", playerName, level))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleSetClass handles the /setclass command
|
|
func HandleSetClass(ctx *CommandContext) error {
|
|
if err := ctx.ValidateArgumentCount(2, 2); err != nil {
|
|
ctx.AddErrorMessage("Usage: /setclass <player> <class_id>")
|
|
return nil
|
|
}
|
|
|
|
playerName := ctx.Arguments[0]
|
|
classID := ctx.GetArgumentInt(1, 0)
|
|
|
|
if classID < 0 {
|
|
ctx.AddErrorMessage("Invalid class ID")
|
|
return nil
|
|
}
|
|
|
|
// TODO: Implement class setting
|
|
ctx.AddStatusMessage(fmt.Sprintf("Set %s's class to %d", playerName, classID))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleReload handles the /reload command
|
|
func HandleReload(ctx *CommandContext) error {
|
|
if err := ctx.ValidateArgumentCount(1, 1); err != nil {
|
|
ctx.AddErrorMessage("Usage: /reload <spells|quests|zones|items|all>")
|
|
return nil
|
|
}
|
|
|
|
reloadType := strings.ToLower(ctx.Arguments[0])
|
|
|
|
switch reloadType {
|
|
case "spells":
|
|
ctx.AddStatusMessage("Reloaded spells")
|
|
case "quests":
|
|
ctx.AddStatusMessage("Reloaded quests")
|
|
case "zones":
|
|
ctx.AddStatusMessage("Reloaded zones")
|
|
case "items":
|
|
ctx.AddStatusMessage("Reloaded items")
|
|
case "all":
|
|
ctx.AddStatusMessage("Reloaded all server data")
|
|
default:
|
|
ctx.AddErrorMessage("Usage: /reload <spells|quests|zones|items|all>")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleShutdown handles the /shutdown command
|
|
func HandleShutdown(ctx *CommandContext) error {
|
|
minutes := 5 // Default 5 minutes
|
|
reason := "Server maintenance"
|
|
|
|
if ctx.ArgumentCount() > 0 {
|
|
minutes = ctx.GetArgumentInt(0, 5)
|
|
}
|
|
if ctx.ArgumentCount() > 1 {
|
|
reason = ctx.GetRemainingArguments(1)
|
|
}
|
|
|
|
// TODO: Implement server shutdown
|
|
ctx.AddStatusMessage(fmt.Sprintf("Server shutdown scheduled in %d minutes. Reason: %s",
|
|
minutes, reason))
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleCancelShutdown handles the /cancelshutdown command
|
|
func HandleCancelShutdown(ctx *CommandContext) error {
|
|
// TODO: Implement shutdown cancellation
|
|
ctx.AddStatusMessage("Server shutdown cancelled")
|
|
return nil
|
|
}
|
|
|
|
// HandleInvisible handles the /invisible command
|
|
func HandleInvisible(ctx *CommandContext) error {
|
|
if err := ctx.RequirePlayer(); err != nil {
|
|
return err
|
|
}
|
|
|
|
// TODO: Toggle GM invisibility
|
|
ctx.AddStatusMessage("GM invisibility toggled")
|
|
return nil
|
|
}
|
|
|
|
// HandleInvulnerable handles the /invulnerable command
|
|
func HandleInvulnerable(ctx *CommandContext) error {
|
|
if err := ctx.RequirePlayer(); err != nil {
|
|
return err
|
|
}
|
|
|
|
// TODO: Toggle invulnerability
|
|
ctx.AddStatusMessage("Invulnerability toggled")
|
|
return nil
|
|
}
|
|
|
|
// HandleSpeed handles the /speed command
|
|
func HandleSpeed(ctx *CommandContext) error {
|
|
if err := ctx.RequirePlayer(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := ctx.ValidateArgumentCount(1, 1); err != nil {
|
|
ctx.AddErrorMessage("Usage: /speed <multiplier>")
|
|
return nil
|
|
}
|
|
|
|
multiplier := ctx.GetArgumentFloat(0, 1.0)
|
|
if multiplier < 0.1 || multiplier > 10.0 {
|
|
ctx.AddErrorMessage("Speed multiplier must be between 0.1 and 10.0")
|
|
return nil
|
|
}
|
|
|
|
// TODO: Set movement speed
|
|
ctx.AddStatusMessage(fmt.Sprintf("Movement speed set to %.1fx", multiplier))
|
|
return nil
|
|
}
|
|
|
|
// HandleFlyMode handles the /flymode command
|
|
func HandleFlyMode(ctx *CommandContext) error {
|
|
if err := ctx.RequirePlayer(); err != nil {
|
|
return err
|
|
}
|
|
|
|
// TODO: Toggle fly mode
|
|
ctx.AddStatusMessage("Fly mode toggled")
|
|
return nil
|
|
}
|
|
|
|
// HandleInfo handles the /info command
|
|
func HandleInfo(ctx *CommandContext) error {
|
|
// TODO: Show detailed target information
|
|
targetName := ctx.GetTargetName()
|
|
if targetName == "No Target" {
|
|
ctx.AddErrorMessage("You must target something to get info")
|
|
return nil
|
|
}
|
|
|
|
ctx.AddStatusMessage(fmt.Sprintf("Information for %s:", targetName))
|
|
ctx.AddStatusMessage(" ID: 12345")
|
|
ctx.AddStatusMessage(" Level: 25")
|
|
ctx.AddStatusMessage(" HP: 1250/1250")
|
|
ctx.AddStatusMessage(" Position: 100.5, 200.3, 150.7")
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleVersion handles the /version command
|
|
func HandleVersion(ctx *CommandContext) error {
|
|
// TODO: Get actual version information
|
|
ctx.AddStatusMessage("EQ2Go Server Version 1.0.0")
|
|
ctx.AddStatusMessage("Build: Development")
|
|
ctx.AddStatusMessage("Go Version: go1.24.5")
|
|
return nil
|
|
}
|
|
|
|
// HandleTest handles the /test command
|
|
func HandleTest(ctx *CommandContext) error {
|
|
ctx.AddStatusMessage("Test command executed successfully")
|
|
|
|
if ctx.ArgumentCount() > 0 {
|
|
ctx.AddStatusMessage(fmt.Sprintf("Arguments: %s", ctx.RawArguments))
|
|
}
|
|
|
|
// TODO: Add actual test functionality for development
|
|
return nil
|
|
}
|