246 lines
6.1 KiB
Go
246 lines
6.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
"unicode/utf8"
|
|
|
|
"git.saintnet.tech/tomecraft/tome_lib"
|
|
"github.com/google/uuid"
|
|
"github.com/gorilla/websocket"
|
|
)
|
|
|
|
var done chan interface{}
|
|
var interrupt chan os.Signal
|
|
var pid int
|
|
var matchID uuid.UUID
|
|
|
|
func receiveHandler(connection *websocket.Conn, output chan string) {
|
|
defer close(done)
|
|
for {
|
|
var resp tome_lib.SessionCommandResult
|
|
err := connection.ReadJSON(&resp)
|
|
if err != nil {
|
|
log.Println("Error in receive:", err)
|
|
}
|
|
switch resp.Result {
|
|
case tome_lib.SessionRespJoined1:
|
|
pid = tome_lib.SentinalID
|
|
output <- "joined as sentinal"
|
|
case tome_lib.SessionRespJoined2:
|
|
pid = tome_lib.ScourgeID
|
|
output <- "joined as scourge"
|
|
case tome_lib.SessionRespFound:
|
|
matchID = resp.MatchID
|
|
output <- "tome_lib found"
|
|
case tome_lib.SessionRespJoinError:
|
|
output <- "error joining game"
|
|
case tome_lib.SessionRespPlayed:
|
|
if resp.GameResult != nil {
|
|
output <- "played succesfully"
|
|
switch resp.GameResult.ResultType {
|
|
case tome_lib.ActCmd:
|
|
output <- resp.GameResult.ActionResult.String()
|
|
case tome_lib.StateCmd:
|
|
output <- resp.GameResult.StateResult.String()
|
|
case tome_lib.DebugCmd:
|
|
output <- "debug response" //resp.GameResult.DebugResult
|
|
}
|
|
} else {
|
|
output <- "error playing"
|
|
}
|
|
case tome_lib.SessionRespLeft:
|
|
output <- "tome_lib left"
|
|
break
|
|
case tome_lib.SessionRespBroadcastSenTurn:
|
|
output <- "Sentinal may take their turn"
|
|
case tome_lib.SessionRespBroadcastScoTrun:
|
|
output <- "Scourge may take their turn"
|
|
case tome_lib.SessionRespBroadcastSenWin:
|
|
output <- "Sentinal wins!"
|
|
case tome_lib.SessionRespBroadcastScoWin:
|
|
output <- "Scourge wins!"
|
|
case tome_lib.SessionRespBroadcastUpdate:
|
|
//we don't handle updates
|
|
case tome_lib.SessionRespBroadcastScoJoin:
|
|
output <- "Scourge has joined the game"
|
|
case tome_lib.SessionRespBroadcastSenJoin:
|
|
output <- "Sentinal has joined the game"
|
|
case tome_lib.SessionRespBroadcastScoLeft:
|
|
output <- "Scourge has left the game"
|
|
case tome_lib.SessionRespBroadcastSenLeft:
|
|
output <- "Sentinal has left the game"
|
|
case tome_lib.SessionRespBroadcastSenReady:
|
|
output <- "Sentinal is ready"
|
|
case tome_lib.SessionRespBroadcastScoReady:
|
|
output <- "scourge is ready"
|
|
case tome_lib.SessionRespBroadcastNone:
|
|
|
|
case tome_lib.SessionRespError:
|
|
output <- "generic error"
|
|
|
|
default:
|
|
output <- "Received a server response we don't know how to handle"
|
|
}
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
done = make(chan interface{}) // Channel to indicate that the receiverHandler is done
|
|
interrupt = make(chan os.Signal) // Channel to listen for interrupt signal to terminate gracefully
|
|
cmd := make(chan tome_lib.SessionCommand)
|
|
output := make(chan string)
|
|
|
|
signal.Notify(interrupt, os.Interrupt) // Notify the interrupt channel for SIGINT
|
|
hostname := flag.String("host", "localhost", "server hostname to connect to")
|
|
port := flag.Int("port", 7636, "port to connect to")
|
|
|
|
flag.Parse()
|
|
port_s := strconv.Itoa(*port)
|
|
socketUrl := "ws://" + *hostname + ":" + port_s + "/ws"
|
|
conn, _, err := websocket.DefaultDialer.Dial(socketUrl, nil)
|
|
id := uuid.New()
|
|
|
|
if err != nil {
|
|
log.Fatal("Error connecting to Websocket Server:", err)
|
|
}
|
|
defer conn.Close()
|
|
go receiveHandler(conn, output)
|
|
go GetCommand(id, cmd)
|
|
ticker := time.NewTicker(1 * time.Second)
|
|
// Our main loop for the client
|
|
// We send our relevant packets here
|
|
for {
|
|
var c tome_lib.SessionCommand
|
|
var o string
|
|
select {
|
|
case c = <-cmd:
|
|
err := conn.WriteJSON(c)
|
|
if err != nil {
|
|
log.Println("Error during writing to websocket:", err)
|
|
return
|
|
}
|
|
if c.Command == tome_lib.SessionCmdLeave {
|
|
break
|
|
}
|
|
case o = <-output:
|
|
fmt.Println(o)
|
|
case <-interrupt:
|
|
// We received a SIGINT (Ctrl + C). Terminate gracefully...
|
|
log.Println("Received SIGINT interrupt signal. Closing all pending connections")
|
|
|
|
// Close our websocket connection
|
|
err := conn.WriteJSON(tome_lib.SessionCommand{
|
|
ID: id,
|
|
Command: tome_lib.SessionCmdLeave,
|
|
})
|
|
if err != nil {
|
|
log.Println("Error during closing websocket:", err)
|
|
return
|
|
}
|
|
|
|
select {
|
|
case <-done:
|
|
log.Println("Receiver Channel Closed! Exiting....")
|
|
case <-time.After(time.Duration(1) * time.Second):
|
|
log.Println("Timeout in closing receiving channel. Exiting....")
|
|
}
|
|
return
|
|
case <-ticker.C:
|
|
if matchID != uuid.Nil {
|
|
err := conn.WriteJSON(tome_lib.SessionCommand{
|
|
ID: id,
|
|
MatchID: matchID,
|
|
Command: tome_lib.SessionCmdPoll,
|
|
})
|
|
if err != nil {
|
|
log.Println("Error writing to websocket:", err)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func GetCommand(uid uuid.UUID, resp chan tome_lib.SessionCommand) {
|
|
for {
|
|
var cmd string
|
|
var t int
|
|
fmt.Print("> ")
|
|
_, err := fmt.Scanf("%d", &t)
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
if t == -1 {
|
|
panic("quitting")
|
|
}
|
|
cmd, err = bufio.NewReader(os.Stdin).ReadString('\n')
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
cmd = strings.TrimSpace(cmd)
|
|
switch t {
|
|
case 0:
|
|
//session
|
|
switch tome_lib.SessionCmd(cmd) {
|
|
case tome_lib.SessionCmdQuery:
|
|
resp <- tome_lib.SessionCommand{
|
|
ID: uid,
|
|
Command: tome_lib.SessionCmdQuery,
|
|
}
|
|
case tome_lib.SessionCmdJoin:
|
|
resp <- tome_lib.SessionCommand{
|
|
ID: uid,
|
|
MatchID: matchID,
|
|
Command: tome_lib.SessionCmdJoin,
|
|
}
|
|
case tome_lib.SessionCmdLeave:
|
|
resp <- tome_lib.SessionCommand{
|
|
ID: uid,
|
|
MatchID: matchID,
|
|
Command: tome_lib.SessionCmdLeave,
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
case 1:
|
|
//state
|
|
resp <- tome_lib.SessionCommand{
|
|
ID: uid,
|
|
MatchID: matchID,
|
|
Command: tome_lib.SessionCmdPlay,
|
|
GameCommand: &tome_lib.Command{
|
|
PlayerID: pid,
|
|
Type: tome_lib.StateCmd,
|
|
Cmd: cmd,
|
|
},
|
|
}
|
|
case 2:
|
|
//action
|
|
resp <- tome_lib.SessionCommand{
|
|
ID: uid,
|
|
MatchID: matchID,
|
|
Command: tome_lib.SessionCmdPlay,
|
|
GameCommand: &tome_lib.Command{
|
|
PlayerID: pid,
|
|
Type: tome_lib.ActCmd,
|
|
Cmd: cmd,
|
|
},
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
func trimFirstRune(s string) string {
|
|
_, i := utf8.DecodeRuneInString(s)
|
|
return s[i:]
|
|
}
|