package main import ( "math/rand" "strconv" "strings" "sync" ) type CommandHandlerFunc func(args []string, clientID int) string type CommandRegistry struct { commands map[string]CommandHandlerFunc mutex sync.Mutex // Mutex to safely access commands map } func NewCommandRegistry() *CommandRegistry { return &CommandRegistry{ commands: make(map[string]CommandHandlerFunc), } } func (cr *CommandRegistry) RegisterCommand(command string, handler CommandHandlerFunc) { cr.mutex.Lock() defer cr.mutex.Unlock() cr.commands[command] = handler } func (cr *CommandRegistry) GetCommandHandler(command string, clientID int) (CommandHandlerFunc, bool, int) { cr.mutex.Lock() defer cr.mutex.Unlock() handler, ok := cr.commands[command] return handler, ok, clientID } func RegisterCommands(registry *CommandRegistry) { registry.RegisterCommand("help", HelpCommand) registry.RegisterCommand("setname", SetNameCommand) registry.RegisterCommand("list", ListClientsCommand) registry.RegisterCommand("tell", TellClientCommand) registry.RegisterCommand("clear", ClearCommand) registry.RegisterCommand("rng", RandomCommand) registry.RegisterCommand("challenge", StartCommand) registry.RegisterCommand("accept", AcceptCommand) registry.RegisterCommand("shoot", ShootCommand) // Add more commands here... } func ShootCommand(args []string, clientID int) string { if clients[clientID].match.round >= 0 { self := false if len(args) == 1 { if strings.ToLower(args[0]) == "self" { self = true } else if getByIDOrName(args[0]) == clientID { self = true } } var fired bool if self { fired = clients[clientID].match.gun.Shoot(clients[clientID]) if fired { return "Shot self with a live" } else { return "Shot self with a blank" } } else { if clients[clientID].isHost { fired = clients[clientID].match.gun.Shoot(clients[clientID].match.guest) } else { fired = clients[clientID].match.gun.Shoot(clients[clientID].match.host) } if fired { return "Shot " + args[0] + "with a live" } else { return "Shot " + args[0] + "with a blank" } } } return "Error" } func AcceptCommand(args []string, clientID int) string { clientsMutex.Lock() defer clientsMutex.Unlock() matchesMutex.Lock() defer matchesMutex.Unlock() if clients[clientID].match.guest == clients[clientID] { clients[clientID].match.round = 0 clients[clientID].match.host.sendMessage("Accepted", clients[clientID]) clients[clientID].isHost = false clients[clientID].match.gun.Reload(8) return "Accepted" } return "No match to accept" } func StartCommand(args []string, clientID int) string { if len(args) == 1 { targetID := getByIDOrName(args[0]) if targetID >= 0 { match := Match{ host: clients[clientID], guest: clients[targetID], round: -1, gun: Gun{ doubled: false, }, } clientsMutex.Lock() clients[clientID].match = &match clients[targetID].match = &match clients[targetID].sendMessage("Type \"accept\" to accept a match.", clients[clientID]) clientsMutex.Unlock() matchesMutex.Lock() matches = append(matches, &match) matchesMutex.Unlock() } else { return "Unknown user" } } return "Invalid argument" } func HelpCommand(args []string, clientID int) string { // Handle help command if len(clients) > 0 { return "Just help yourself, " + clients[clientID].Username } return "No clients available" } func RandomCommand(args []string, clientID int) string { // Handle help command if len(args) == 2 { from, err1 := strconv.Atoi(args[0]) to, err2 := strconv.Atoi(args[1]) if err1 != nil || err2 != nil { return "Invalid argument" } if to-from <= 0 { return "Invalid range" } return "The number is " + strconv.Itoa(rand.Intn(to-from)+from) } return "No range provided" } func ClearCommand(args []string, clientID int) string { // Handle help command return "\033[H\033[2J\033[K" } func SetNameCommand(args []string, clientID int) string { // Handle help command if len(args) == 1 { newName := args[0] clients[clientID].Username = newName return "Name set to " + newName } return "No name provided" } func ListClientsCommand(args []string, clientID int) string { message := "" for i, client := range clients { message += strconv.Itoa(i) + ": " + client.Username + "\n" } return message } func TellClientCommand(args []string, clientID int) string { message := "Message not delivered" if len(args) >= 2 { toClientID := getByIDOrName(args[0]) if toClientID >= 0 { toClientName := clients[toClientID].Username newMessage := "" //all the remaining arguments are a part of the message, join them with space for i, arg := range args { if i > 0 { newMessage += arg + " " } } clients[toClientID].sendMessage(newMessage, clients[clientID]) return "Message sent to " + toClientName } else { message = "Invalid recipient" } } return message }