252 lines
7.5 KiB
Go
252 lines
7.5 KiB
Go
package main
|
|
|
|
import (
|
|
"math/rand"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
type command struct {
|
|
commandHandlerFunc commandHandlerFunc
|
|
description string
|
|
}
|
|
|
|
type commandHandlerFunc func(args []string, clientID int) string
|
|
|
|
type commandRegistry struct {
|
|
commands map[string]command
|
|
mutex sync.Mutex // Mutex to safely access commands map
|
|
}
|
|
|
|
func newCommandRegistry() *commandRegistry {
|
|
return &commandRegistry{
|
|
commands: make(map[string]command),
|
|
}
|
|
}
|
|
|
|
func (cr *commandRegistry) registerCommand(commandName string, handler commandHandlerFunc, desc string) {
|
|
cr.mutex.Lock()
|
|
defer cr.mutex.Unlock()
|
|
cr.commands[commandName] = command{
|
|
commandHandlerFunc: handler,
|
|
description: desc,
|
|
}
|
|
}
|
|
|
|
func (cr *commandRegistry) getCommandHandler(command string, clientID int) (commandHandlerFunc, bool, int) {
|
|
cr.mutex.Lock()
|
|
defer cr.mutex.Unlock()
|
|
commandEntry, ok := cr.commands[command]
|
|
handler := commandEntry.commandHandlerFunc
|
|
return handler, ok, clientID
|
|
}
|
|
|
|
func registerCommands(registry *commandRegistry) {
|
|
registry.registerCommand("clear", clearCommand, `Clears your screen (clear)`)
|
|
registry.registerCommand("setname", setNameCommand, `Sets your name (setname yourname[string])`)
|
|
registry.registerCommand("list", listClientsCommand, `Lists clients (list)`)
|
|
registry.registerCommand("rng", randomCommand, `Generates a random integer (rng from[int] to[int{bigger than from}], both need to be above zero)`)
|
|
registry.registerCommand("tell", tellClientCommand, `Tell a client (tell client[id or string{username}])`)
|
|
registry.registerCommand("challenge", startCommand, `Challenge a client (challenge client[id or string{username}])`)
|
|
registry.registerCommand("accept", acceptCommand, `Accepts a challenge (accept)`)
|
|
registry.registerCommand("shoot", shootCommand, `Shoots at a client (shoot target[int or string], accepts self as a parameter) {Shooting self with a blank keeps your turn}`)
|
|
registry.registerCommand("useitem", useItemCommand, `Uses an item in a match (useitem index[number])`)
|
|
registry.registerCommand("status", statusCommand, `Prints the game status (status)`)
|
|
// Add more commands here...
|
|
}
|
|
|
|
func statusCommand(_ []string, clientID int) string {
|
|
if clients[clientID].match != nil && clients[clientID].match.round > 0 {
|
|
clients[clientID].match.announceHP()
|
|
clients[clientID].match.announceItems()
|
|
clients[clientID].match.announceRounds()
|
|
clients[clientID].match.announceTurn()
|
|
return ""
|
|
} else {
|
|
return "Not in match"
|
|
}
|
|
}
|
|
|
|
func useItemCommand(args []string, clientID int) string {
|
|
param := -1
|
|
itemID := -1
|
|
if len(args) >= 2 {
|
|
var err error
|
|
param, err = strconv.Atoi(args[1])
|
|
if err != nil {
|
|
param = -1
|
|
}
|
|
}
|
|
if len(args) >= 1 {
|
|
var err error
|
|
itemID, err = strconv.Atoi(args[0])
|
|
if err != nil {
|
|
itemID = -1
|
|
}
|
|
}
|
|
if itemID >= 0 && itemID < clients[clientID].match.itemCount {
|
|
clients[clientID].match.sendMessage("\r\nUsing item "+clients[clientID].items[itemID].name(), clients[clientID])
|
|
clients[clientID].items[itemID].useItem(param)
|
|
return "Used"
|
|
} else {
|
|
return "ERROR using item"
|
|
}
|
|
}
|
|
|
|
func shootCommand(args []string, clientID int) string {
|
|
if clients[clientID].match != nil && clients[clientID].match.round > 0 {
|
|
if clients[clientID].match.guestsTurn != clients[clientID].isHost {
|
|
defer clients[clientID].match.checkStatus()
|
|
defer clients[clientID].match.announceHP()
|
|
defer clients[clientID].match.announceRounds()
|
|
self := false
|
|
if len(args) == 1 {
|
|
if strings.ToLower(args[0]) == "self" {
|
|
self = true
|
|
} else if getByIDOrName(args[0]) == clientID {
|
|
self = true
|
|
}
|
|
}
|
|
var fired int
|
|
var target *client
|
|
if self {
|
|
target = clients[clientID]
|
|
fired = clients[clientID].match.gun.shoot(target)
|
|
if fired == 1 {
|
|
clients[clientID].match.guestsTurn = clients[clientID].isHost
|
|
clients[clientID].match.sendMessage("Shot myself with a live", clients[clientID])
|
|
} else {
|
|
clients[clientID].match.sendMessage("Shot myself with a blank", clients[clientID])
|
|
}
|
|
} else {
|
|
if clients[clientID].isHost {
|
|
target = clients[clientID].match.guest
|
|
} else {
|
|
target = clients[clientID].match.host
|
|
}
|
|
fired = clients[clientID].match.gun.shoot(target)
|
|
if fired == 1 {
|
|
clients[clientID].match.guestsTurn = clients[clientID].isHost
|
|
clients[clientID].match.sendMessage("Shot "+target.Username+"("+strconv.Itoa(target.ID)+")"+"with a live", clients[clientID])
|
|
} else {
|
|
clients[clientID].match.guestsTurn = clients[clientID].isHost
|
|
clients[clientID].match.sendMessage("Shot "+target.Username+"("+strconv.Itoa(target.ID)+")"+"with a blank", clients[clientID])
|
|
}
|
|
}
|
|
return "SHOT"
|
|
} else {
|
|
return "It is not your turn"
|
|
}
|
|
} else {
|
|
return "Your are not in a match"
|
|
|
|
}
|
|
}
|
|
|
|
func acceptCommand(_ []string, clientID int) string {
|
|
clientsMutex.Lock()
|
|
defer clientsMutex.Unlock()
|
|
matchesMutex.Lock()
|
|
defer matchesMutex.Unlock()
|
|
if clients[clientID].match != nil && clients[clientID].match.guest == clients[clientID] {
|
|
clients[clientID].match.host.sendMessage("Accepted", clients[clientID])
|
|
clients[clientID].isHost = false
|
|
clients[clientID].match.guestsTurn = false
|
|
clients[clientID].match.start()
|
|
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 && targetID != clientID && (clients[clientID].match == nil || clients[clientID].match.round <= 0) {
|
|
match := match{
|
|
host: clients[clientID],
|
|
guest: clients[targetID],
|
|
round: 0,
|
|
gun: gun{
|
|
doubled: false,
|
|
},
|
|
}
|
|
clientsMutex.Lock()
|
|
clients[clientID].match = &match
|
|
clients[targetID].match = &match
|
|
match.itemCount = 8
|
|
clients[clientID].isHost = true
|
|
clients[targetID].sendMessage("Type \"accept\" to accept a match.", clients[clientID])
|
|
clientsMutex.Unlock()
|
|
matchesMutex.Lock()
|
|
matches = append(matches, &match)
|
|
matchesMutex.Unlock()
|
|
return "Successfully challenged"
|
|
} else {
|
|
return "Unknown user"
|
|
}
|
|
}
|
|
return "Invalid argument"
|
|
}
|
|
|
|
func randomCommand(args []string, _ 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(_ []string, _ 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(_ []string, _ int) string {
|
|
var message strings.Builder
|
|
for i, client := range clients {
|
|
message.WriteString(strconv.Itoa(i) + ": " + client.Username + "\n")
|
|
}
|
|
return message.String()
|
|
}
|
|
|
|
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
|
|
var newMessage strings.Builder
|
|
//all the remaining arguments are a part of the message, join them with space
|
|
for i, arg := range args {
|
|
if i > 0 {
|
|
newMessage.WriteString(arg + " ")
|
|
}
|
|
}
|
|
clients[toClientID].sendMessage(newMessage.String(), clients[clientID])
|
|
return "Message sent to " + toClientName
|
|
} else {
|
|
message = "Invalid recipient"
|
|
}
|
|
}
|
|
return message
|
|
}
|