diff --git a/client.go b/client.go index 6be4994..b2a9bde 100644 --- a/client.go +++ b/client.go @@ -6,18 +6,21 @@ import ( ) type Client struct { - Client telnet.Client + Client *telnet.Client Username string ID int History []string HistoryIndex int - context telnet.Context - writer telnet.Writer - reader telnet.Reader + context *telnet.Context + writer *telnet.Writer + reader *telnet.Reader + match *Match + isHost bool + hp int // Add more fields as needed } -func NewClient(context telnet.Context, writer telnet.Writer, reader telnet.Reader) int { +func NewClient(context *telnet.Context, writer *telnet.Writer, reader *telnet.Reader) int { client := Client{} clientsMutex.Lock() @@ -30,6 +33,8 @@ func NewClient(context telnet.Context, writer telnet.Writer, reader telnet.Reade clients[clientID].context = context clients[clientID].writer = writer clients[clientID].reader = reader + clients[clientID].isHost = false + clients[clientID].hp = -1 return clientID } @@ -40,7 +45,12 @@ func RemoveClient(clientID int) { } func (client Client) send(message string) { - client.writer.Write([]byte(message)) + writer := *(client.writer) + writer.Write([]byte(message)) +} + +func (client Client) sendMessage(message string, sender *Client) { + client.send("\a\r\n<" + sender.Username + "(" + strconv.Itoa(sender.ID) + ")> " + message + "\r\n") } func getIDByName(name string) int { @@ -53,3 +63,16 @@ func getIDByName(name string) int { } return -1 } + +func getByIDOrName(by string) int { + //if integer assume clientID + var toClientID int + toClientID, err := strconv.Atoi(by) + if err != nil { + toClientID = getIDByName(by) + } + if toClientID < len(clients) && toClientID >= 0 { + return toClientID + } + return -1 +} diff --git a/commands.go b/commands.go index 115ec8b..63106ca 100644 --- a/commands.go +++ b/commands.go @@ -3,6 +3,7 @@ package main import ( "math/rand" "strconv" + "strings" "sync" ) @@ -39,9 +40,88 @@ func RegisterCommands(registry *CommandRegistry) { 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 { @@ -92,18 +172,9 @@ func ListClientsCommand(args []string, clientID int) string { func TellClientCommand(args []string, clientID int) string { message := "Message not delivered" if len(args) >= 2 { - clientTo := args[0] - //if integer assume clientID - var toClientID int - var toClientName string - toClientID, err := strconv.Atoi(clientTo) - if err != nil { - toClientID = getIDByName(clientTo) - toClientName = clientTo - } - if toClientID < len(clients) && toClientID >= 0 { - toClientName = clients[toClientID].Username - myUsername := clients[clientID].Username + 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 { @@ -111,7 +182,7 @@ func TellClientCommand(args []string, clientID int) string { newMessage += arg + " " } } - clients[toClientID].send("\a\r\n<" + myUsername + "(" + strconv.Itoa(clientID) + ")> " + newMessage + "\r\n") + clients[toClientID].sendMessage(newMessage, clients[clientID]) return "Message sent to " + toClientName } else { message = "Invalid recipient" diff --git a/gun.go b/gun.go new file mode 100644 index 0000000..0ca61e6 --- /dev/null +++ b/gun.go @@ -0,0 +1,32 @@ +package main + +import "math/rand" + +type Gun struct { + doubled bool + magazine []bool +} + +// fire +func (g Gun) Shoot(target *Client) bool { + shot := false + if g.magazine[len(g.magazine)-1] { + shot = true + if g.doubled { + target.hp -= 2 + } else { + target.hp -= 1 + } + } + g.magazine = g.magazine[:len(g.magazine)-1] + + g.doubled = false + return shot +} + +func (g Gun) Reload(count int) { + g.magazine = make([]bool, count) + for i := 0; i < count; i++ { + g.magazine[i] = rand.Intn(2) == 1 + } +} diff --git a/item.go b/item.go new file mode 100644 index 0000000..dd66d71 --- /dev/null +++ b/item.go @@ -0,0 +1,22 @@ +package main + +type Item struct { + kind int + match *Match +} + +func (i Item) name() string { + switch i.kind { + case 0: + return "Doubler" + default: + return "None" + } +} + +func (i Item) useItem(param1 int) { + switch i.kind { + case 0: + i.match.gun.doubled = true + } +} diff --git a/main.go b/main.go index 143e20b..bd92b7d 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,8 @@ import ( var clients []*Client var clientsMutex sync.Mutex +var matches []*Match +var matchesMutex sync.Mutex func main() { addr := ":6969" diff --git a/match.go b/match.go new file mode 100644 index 0000000..0958a8b --- /dev/null +++ b/match.go @@ -0,0 +1,8 @@ +package main + +type Match struct { + host *Client + guest *Client + round int + gun Gun +} diff --git a/terminal_handler.go b/terminal_handler.go index 4726312..461b7b3 100644 --- a/terminal_handler.go +++ b/terminal_handler.go @@ -21,7 +21,7 @@ func NewInternalTerminalHandler(shellCharacter, welcomeMessage string, commandRe } func (handler *InternalTerminalHandler) ServeTELNET(ctx telnet.Context, w telnet.Writer, r telnet.Reader) { - clientID := NewClient(ctx, w, r) + clientID := NewClient(&ctx, &w, &r) defer RemoveClient(clientID) w.RawWrite([]byte{0xff, 0xfb, 0x03}) //send char by char