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-09 11:02:18 +02:00
type command struct {
commandHandlerFunc commandHandlerFunc
2024-06-08 23:23:20 +02:00
description string
}
2024-06-09 11:02:18 +02:00
type commandHandlerFunc func ( args [ ] string , clientID int ) string
2024-06-08 11:52:12 +02:00
2024-06-09 11:02:18 +02:00
type commandRegistry struct {
commands map [ string ] command
2024-06-08 11:52:12 +02:00
mutex sync . Mutex // Mutex to safely access commands map
}
2024-06-09 11:02:18 +02:00
func newCommandRegistry ( ) * commandRegistry {
return & commandRegistry {
commands : make ( map [ string ] command ) ,
2024-06-08 11:52:12 +02:00
}
}
2024-06-09 11:02:18 +02:00
func ( cr * commandRegistry ) registerCommand ( commandName string , handler commandHandlerFunc , desc string ) {
2024-06-08 11:52:12 +02:00
cr . mutex . Lock ( )
defer cr . mutex . Unlock ( )
2024-06-09 11:02:18 +02:00
cr . commands [ commandName ] = command {
2024-06-08 23:23:20 +02:00
commandHandlerFunc : handler ,
description : desc ,
}
2024-06-08 11:52:12 +02:00
}
2024-06-09 11:02:18 +02:00
func ( cr * commandRegistry ) getCommandHandler ( command string , clientID int ) ( commandHandlerFunc , bool , int ) {
2024-06-08 11:52:12 +02:00
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
}
2024-06-09 11:02:18 +02:00
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) ` )
2024-06-08 11:52:12 +02:00
// Add more commands here...
}
2024-06-09 11:02:18 +02:00
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 {
2024-06-08 23:23:20 +02:00
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 {
2024-06-09 11:02:18 +02:00
clients [ clientID ] . match . sendMessage ( "\r\nUsing item " + clients [ clientID ] . items [ itemID ] . name ( ) , clients [ clientID ] )
2024-06-08 23:23:20 +02:00
clients [ clientID ] . items [ itemID ] . useItem ( param )
return "Used"
} else {
return "ERROR using item"
}
}
2024-06-09 11:02:18 +02:00
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
}
2024-06-08 13:52:22 +02:00
}
2024-06-09 11:02:18 +02:00
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 ] )
}
2024-06-08 13:52:22 +02:00
} else {
2024-06-09 11:02:18 +02:00
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 ] )
}
2024-06-08 13:52:22 +02:00
}
2024-06-09 11:02:18 +02:00
return "SHOT"
2024-06-08 13:52:22 +02:00
} else {
2024-06-09 11:02:18 +02:00
return "It is not your turn"
2024-06-08 13:52:22 +02:00
}
2024-06-09 11:02:18 +02:00
} else {
return "Your are not in a match"
2024-06-08 13:52:22 +02:00
}
}
2024-06-09 11:02:18 +02:00
func acceptCommand ( _ [ ] string , clientID int ) string {
2024-06-08 13:52:22 +02:00
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-09 11:02:18 +02:00
clients [ clientID ] . match . guestsTurn = false
clients [ clientID ] . match . start ( )
2024-06-08 13:52:22 +02:00
return "Accepted"
}
return "No match to accept"
}
2024-06-09 11:02:18 +02:00
func startCommand ( args [ ] string , clientID int ) string {
2024-06-08 13:52:22 +02:00
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-09 11:02:18 +02:00
match := match {
2024-06-08 13:52:22 +02:00
host : clients [ clientID ] ,
guest : clients [ targetID ] ,
2024-06-08 23:23:20 +02:00
round : 0 ,
2024-06-09 11:02:18 +02:00
gun : gun {
2024-06-08 13:52:22 +02:00
doubled : false ,
} ,
}
clientsMutex . Lock ( )
clients [ clientID ] . match = & match
clients [ targetID ] . match = & match
2024-06-09 11:02:18 +02:00
match . itemCount = 8
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-09 11:02:18 +02:00
func randomCommand ( args [ ] string , _ int ) string {
2024-06-08 11:52:12 +02:00
// 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"
}
2024-06-09 11:02:18 +02:00
func clearCommand ( _ [ ] string , _ int ) string {
2024-06-08 11:52:12 +02:00
// Handle help command
return "\033[H\033[2J\033[K"
}
2024-06-09 11:02:18 +02:00
func setNameCommand ( args [ ] string , clientID int ) string {
2024-06-08 11:52:12 +02:00
// 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"
}
2024-06-09 11:02:18 +02:00
func listClientsCommand ( _ [ ] string , _ int ) string {
var message strings . Builder
2024-06-08 11:52:12 +02:00
for i , client := range clients {
2024-06-09 11:02:18 +02:00
message . WriteString ( strconv . Itoa ( i ) + ": " + client . Username + "\n" )
2024-06-08 11:52:12 +02:00
}
2024-06-09 11:02:18 +02:00
return message . String ( )
2024-06-08 11:52:12 +02:00
}
2024-06-09 11:02:18 +02:00
func tellClientCommand ( args [ ] string , clientID int ) string {
2024-06-08 11:52:12 +02:00
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-09 11:02:18 +02:00
var newMessage strings . Builder
2024-06-08 11:52:12 +02:00
//all the remaining arguments are a part of the message, join them with space
for i , arg := range args {
if i > 0 {
2024-06-09 11:02:18 +02:00
newMessage . WriteString ( arg + " " )
2024-06-08 11:52:12 +02:00
}
}
2024-06-09 11:02:18 +02:00
clients [ toClientID ] . sendMessage ( newMessage . String ( ) , clients [ clientID ] )
2024-06-08 11:52:12 +02:00
return "Message sent to " + toClientName
} else {
message = "Invalid recipient"
}
}
return message
}