2024-06-08 11:52:12 +02:00
package main
import (
"math/rand"
"strconv"
2024-06-08 13:52:22 +02:00
"strings"
2024-06-08 11:52:12 +02:00
"sync"
)
2024-06-08 23:23:20 +02:00
type Command struct {
commandHandlerFunc CommandHandlerFunc
description string
}
2024-06-08 11:52:12 +02:00
type CommandHandlerFunc func ( args [ ] string , clientID int ) string
type CommandRegistry struct {
2024-06-08 23:23:20 +02:00
commands map [ string ] Command
2024-06-08 11:52:12 +02:00
mutex sync . Mutex // Mutex to safely access commands map
}
func NewCommandRegistry ( ) * CommandRegistry {
return & CommandRegistry {
2024-06-08 23:23:20 +02:00
commands : make ( map [ string ] Command ) ,
2024-06-08 11:52:12 +02:00
}
}
2024-06-08 23:23:20 +02:00
func ( cr * CommandRegistry ) RegisterCommand ( command string , handler CommandHandlerFunc , desc string ) {
2024-06-08 11:52:12 +02:00
cr . mutex . Lock ( )
defer cr . mutex . Unlock ( )
2024-06-08 23:23:20 +02:00
cr . commands [ command ] = Command {
commandHandlerFunc : handler ,
description : desc ,
}
2024-06-08 11:52:12 +02:00
}
func ( cr * CommandRegistry ) GetCommandHandler ( command string , clientID int ) ( CommandHandlerFunc , bool , int ) {
cr . mutex . Lock ( )
defer cr . mutex . Unlock ( )
2024-06-08 23:23:20 +02:00
commandEntry , ok := cr . commands [ command ]
handler := commandEntry . commandHandlerFunc
2024-06-08 11:52:12 +02:00
return handler , ok , clientID
}
func RegisterCommands ( registry * CommandRegistry ) {
2024-06-08 23:23:20 +02:00
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]) ` )
2024-06-08 11:52:12 +02:00
// Add more commands here...
}
2024-06-08 23:23:20 +02:00
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 ] . items [ itemID ] . useItem ( param )
clients [ clientID ] . match . SendMessage ( "\r\nUsing item " + clients [ clientID ] . items [ itemID ] . name ( ) , clients [ clientID ] )
return "Used"
} else {
return "ERROR using item"
}
}
2024-06-08 13:52:22 +02:00
func ShootCommand ( args [ ] string , clientID int ) string {
2024-06-08 23:23:20 +02:00
if clients [ clientID ] . match != nil && clients [ clientID ] . match . round > 0 && clients [ clientID ] . match . Guestturn != clients [ clientID ] . isHost {
defer clients [ clientID ] . match . CheckStatus ( )
defer clients [ clientID ] . match . announceHP ( )
defer clients [ clientID ] . match . announceRounds ( )
2024-06-08 13:52:22 +02:00
self := false
if len ( args ) == 1 {
if strings . ToLower ( args [ 0 ] ) == "self" {
self = true
} else if getByIDOrName ( args [ 0 ] ) == clientID {
self = true
}
}
2024-06-08 23:23:20 +02:00
var fired int
var target * Client
2024-06-08 13:52:22 +02:00
if self {
2024-06-08 23:23:20 +02:00
target = clients [ clientID ]
fired , clients [ clientID ] . match . gun . magazine = clients [ clientID ] . match . gun . Shoot ( target )
if fired == 1 {
clients [ clientID ] . match . Guestturn = clients [ clientID ] . isHost
clients [ clientID ] . match . SendMessage ( "Shot myself with a live" , clients [ clientID ] )
2024-06-08 13:52:22 +02:00
} else {
2024-06-08 23:23:20 +02:00
clients [ clientID ] . match . SendMessage ( "Shot myself with a blank" , clients [ clientID ] )
2024-06-08 13:52:22 +02:00
}
} else {
if clients [ clientID ] . isHost {
2024-06-08 23:23:20 +02:00
target = clients [ clientID ] . match . guest
2024-06-08 13:52:22 +02:00
} else {
2024-06-08 23:23:20 +02:00
target = clients [ clientID ] . match . host
2024-06-08 13:52:22 +02:00
}
2024-06-08 23:23:20 +02:00
fired , clients [ clientID ] . match . gun . magazine = clients [ clientID ] . match . gun . Shoot ( target )
if fired == 1 {
clients [ clientID ] . match . Guestturn = clients [ clientID ] . isHost
clients [ clientID ] . match . SendMessage ( "Shot " + target . Username + "(" + strconv . Itoa ( target . ID ) + ")" + "with a live" , clients [ clientID ] )
2024-06-08 13:52:22 +02:00
} else {
2024-06-08 23:23:20 +02:00
clients [ clientID ] . match . Guestturn = clients [ clientID ] . isHost
clients [ clientID ] . match . SendMessage ( "Shot " + target . Username + "(" + strconv . Itoa ( target . ID ) + ")" + "with a blank" , clients [ clientID ] )
2024-06-08 13:52:22 +02:00
}
}
2024-06-08 23:23:20 +02:00
return "SHOT"
2024-06-08 13:52:22 +02:00
}
return "Error"
}
func AcceptCommand ( args [ ] string , clientID int ) string {
clientsMutex . Lock ( )
defer clientsMutex . Unlock ( )
matchesMutex . Lock ( )
defer matchesMutex . Unlock ( )
2024-06-08 23:23:20 +02:00
if clients [ clientID ] . match != nil && clients [ clientID ] . match . guest == clients [ clientID ] {
2024-06-08 13:52:22 +02:00
clients [ clientID ] . match . host . sendMessage ( "Accepted" , clients [ clientID ] )
clients [ clientID ] . isHost = false
2024-06-08 23:23:20 +02:00
clients [ clientID ] . match . Guestturn = false
clients [ clientID ] . match . Start ( )
2024-06-08 13:52:22 +02:00
return "Accepted"
}
return "No match to accept"
}
func StartCommand ( args [ ] string , clientID int ) string {
if len ( args ) == 1 {
targetID := getByIDOrName ( args [ 0 ] )
2024-06-08 23:23:20 +02:00
if targetID >= 0 && targetID != clientID && ( clients [ clientID ] . match == nil || clients [ clientID ] . match . round <= 0 ) {
2024-06-08 13:52:22 +02:00
match := Match {
host : clients [ clientID ] ,
guest : clients [ targetID ] ,
2024-06-08 23:23:20 +02:00
round : 0 ,
2024-06-08 13:52:22 +02:00
gun : Gun {
doubled : false ,
} ,
}
clientsMutex . Lock ( )
clients [ clientID ] . match = & match
clients [ targetID ] . match = & match
2024-06-08 23:23:20 +02:00
clients [ clientID ] . isHost = true
2024-06-08 13:52:22 +02:00
clients [ targetID ] . sendMessage ( "Type \"accept\" to accept a match." , clients [ clientID ] )
clientsMutex . Unlock ( )
matchesMutex . Lock ( )
matches = append ( matches , & match )
matchesMutex . Unlock ( )
2024-06-08 23:23:20 +02:00
return "Successfully challenged"
2024-06-08 13:52:22 +02:00
} else {
return "Unknown user"
}
}
return "Invalid argument"
}
2024-06-08 11:52:12 +02:00
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
2024-06-08 23:23:20 +02:00
if len ( args ) >= 1 {
2024-06-08 11:52:12 +02:00
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 {
2024-06-08 13:52:22 +02:00
toClientID := getByIDOrName ( args [ 0 ] )
if toClientID >= 0 {
toClientName := clients [ toClientID ] . Username
2024-06-08 11:52:12 +02:00
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 + " "
}
}
2024-06-08 13:52:22 +02:00
clients [ toClientID ] . sendMessage ( newMessage , clients [ clientID ] )
2024-06-08 11:52:12 +02:00
return "Message sent to " + toClientName
} else {
message = "Invalid recipient"
}
}
return message
}