initial migration
This commit is contained in:
commit
e6661a26f4
16
Makefile
Normal file
16
Makefile
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#set variables
|
||||||
|
GIT_COMMIT := $(shell git rev-list -1 HEAD)
|
||||||
|
ifeq ($(PREFIX),) # PREFIX is environment variable, but if it is not set, then set default value
|
||||||
|
PREFIX := /usr/local
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: client client2
|
||||||
|
|
||||||
|
client: $(wildcard client/*.go)
|
||||||
|
go build -ldflags "-X main.GitCommit=$(GIT_COMMIT)" ./client
|
||||||
|
client2: $(wildcard client2/*.go)
|
||||||
|
go build -ldflags "-X main.GitCommit=$(GIT_COMMIT)" ./client2
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f client client2
|
||||||
|
|
244
client/main.go
Normal file
244
client/main.go
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"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 coordinator.SessionCommandResult
|
||||||
|
err := connection.ReadJSON(&resp)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error in receive:", err)
|
||||||
|
}
|
||||||
|
switch resp.Result {
|
||||||
|
case coordinator.SessionRespJoined1:
|
||||||
|
pid = game.SentinalID
|
||||||
|
output <- "joined as sentinal"
|
||||||
|
case coordinator.SessionRespJoined2:
|
||||||
|
pid = game.ScourgeID
|
||||||
|
output <- "joined as scourge"
|
||||||
|
case coordinator.SessionRespFound:
|
||||||
|
matchID = resp.MatchID
|
||||||
|
output <- "game found"
|
||||||
|
case coordinator.SessionRespJoinError:
|
||||||
|
output <- "error joining game"
|
||||||
|
case coordinator.SessionRespPlayed:
|
||||||
|
if resp.GameResult != nil {
|
||||||
|
output <- "played succesfully"
|
||||||
|
switch resp.GameResult.ResultType {
|
||||||
|
case game.ActCmd:
|
||||||
|
output <- resp.GameResult.ActionResult.String()
|
||||||
|
case game.StateCmd:
|
||||||
|
output <- resp.GameResult.StateResult.String()
|
||||||
|
case game.DebugCmd:
|
||||||
|
output <- resp.GameResult.DebugResult.String()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output <- "error playing"
|
||||||
|
}
|
||||||
|
case coordinator.SessionRespLeft:
|
||||||
|
output <- "game left"
|
||||||
|
break
|
||||||
|
case coordinator.SessionRespBroadcastSenTurn:
|
||||||
|
output <- "Sentinal may take their turn"
|
||||||
|
case coordinator.SessionRespBroadcastScoTrun:
|
||||||
|
output <- "Scourge may take their turn"
|
||||||
|
case coordinator.SessionRespBroadcastSenWin:
|
||||||
|
output <- "Sentinal wins!"
|
||||||
|
case coordinator.SessionRespBroadcastScoWin:
|
||||||
|
output <- "Scourge wins!"
|
||||||
|
case coordinator.SessionRespBroadcastUpdate:
|
||||||
|
//we don't handle updates
|
||||||
|
case coordinator.SessionRespBroadcastScoJoin:
|
||||||
|
output <- "Scourge has joined the game"
|
||||||
|
case coordinator.SessionRespBroadcastSenJoin:
|
||||||
|
output <- "Sentinal has joined the game"
|
||||||
|
case coordinator.SessionRespBroadcastScoLeft:
|
||||||
|
output <- "Scourge has left the game"
|
||||||
|
case coordinator.SessionRespBroadcastSenLeft:
|
||||||
|
output <- "Sentinal has left the game"
|
||||||
|
case coordinator.SessionRespBroadcastSenReady:
|
||||||
|
output <- "Sentinal is ready"
|
||||||
|
case coordinator.SessionRespBroadcastScoReady:
|
||||||
|
output <- "scourge is ready"
|
||||||
|
case coordinator.SessionRespBroadcastNone:
|
||||||
|
|
||||||
|
case coordinator.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 coordinator.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 coordinator.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 == coordinator.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(coordinator.SessionCommand{
|
||||||
|
ID: id,
|
||||||
|
Command: coordinator.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(coordinator.SessionCommand{
|
||||||
|
ID: id,
|
||||||
|
MatchID: matchID,
|
||||||
|
Command: coordinator.SessionCmdPoll,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error writing to websocket:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCommand(uid uuid.UUID, resp chan coordinator.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 coordinator.SessionCmd(cmd) {
|
||||||
|
case coordinator.SessionCmdQuery:
|
||||||
|
resp <- coordinator.SessionCommand{
|
||||||
|
ID: uid,
|
||||||
|
Command: coordinator.SessionCmdQuery,
|
||||||
|
}
|
||||||
|
case coordinator.SessionCmdJoin:
|
||||||
|
resp <- coordinator.SessionCommand{
|
||||||
|
ID: uid,
|
||||||
|
MatchID: matchID,
|
||||||
|
Command: coordinator.SessionCmdJoin,
|
||||||
|
}
|
||||||
|
case coordinator.SessionCmdLeave:
|
||||||
|
resp <- coordinator.SessionCommand{
|
||||||
|
ID: uid,
|
||||||
|
MatchID: matchID,
|
||||||
|
Command: coordinator.SessionCmdLeave,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
//state
|
||||||
|
resp <- coordinator.SessionCommand{
|
||||||
|
ID: uid,
|
||||||
|
MatchID: matchID,
|
||||||
|
Command: coordinator.SessionCmdPlay,
|
||||||
|
GameCommand: &game.Command{
|
||||||
|
PlayerID: pid,
|
||||||
|
Type: game.StateCmd,
|
||||||
|
Cmd: cmd,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
//action
|
||||||
|
resp <- coordinator.SessionCommand{
|
||||||
|
ID: uid,
|
||||||
|
MatchID: matchID,
|
||||||
|
Command: coordinator.SessionCmdPlay,
|
||||||
|
GameCommand: &game.Command{
|
||||||
|
PlayerID: pid,
|
||||||
|
Type: game.ActCmd,
|
||||||
|
Cmd: cmd,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func trimFirstRune(s string) string {
|
||||||
|
_, i := utf8.DecodeRuneInString(s)
|
||||||
|
return s[i:]
|
||||||
|
}
|
260
client2/backend.go
Normal file
260
client2/backend.go
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"git.saintnet.tech/stryan/snengame/internal/coordinator"
|
||||||
|
"git.saintnet.tech/stryan/snengame/internal/game"
|
||||||
|
"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, container *UIContainer) {
|
||||||
|
defer close(done)
|
||||||
|
for {
|
||||||
|
var resp coordinator.SessionCommandResult
|
||||||
|
err := connection.ReadJSON(&resp)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error in receive:", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch resp.Result {
|
||||||
|
case coordinator.SessionRespJoined1:
|
||||||
|
pid = game.SentinalID
|
||||||
|
container.Output <- "joined as sentinal"
|
||||||
|
case coordinator.SessionRespJoined2:
|
||||||
|
pid = game.ScourgeID
|
||||||
|
container.Output <- "joined as scourge"
|
||||||
|
case coordinator.SessionRespFound:
|
||||||
|
matchID = resp.MatchID
|
||||||
|
container.Output <- "game found"
|
||||||
|
case coordinator.SessionRespPlayed:
|
||||||
|
if resp.GameResult != nil {
|
||||||
|
switch resp.GameResult.ResultType {
|
||||||
|
case game.ActCmd:
|
||||||
|
container.Output <- resp.GameResult.ActionResult.String()
|
||||||
|
case game.StateCmd:
|
||||||
|
container.State = resp.GameResult.StateResult
|
||||||
|
container.Updated <- true
|
||||||
|
case game.DebugCmd:
|
||||||
|
container.Output <- resp.GameResult.DebugResult.String()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
container.Output <- "error playing"
|
||||||
|
}
|
||||||
|
case coordinator.SessionRespLeft:
|
||||||
|
container.Output <- "game left"
|
||||||
|
matchID = uuid.Nil
|
||||||
|
return
|
||||||
|
case coordinator.SessionRespBroadcastSenTurn:
|
||||||
|
container.Output <- "Sentinal may take their turn"
|
||||||
|
case coordinator.SessionRespBroadcastScoTrun:
|
||||||
|
container.Output <- "Scourge may take their turn"
|
||||||
|
case coordinator.SessionRespBroadcastSenWin:
|
||||||
|
container.Output <- "Sentinal wins!"
|
||||||
|
case coordinator.SessionRespBroadcastScoWin:
|
||||||
|
container.Output <- "Scourge wins!"
|
||||||
|
case coordinator.SessionRespBroadcastUpdate:
|
||||||
|
container.GetUpdate <- true
|
||||||
|
case coordinator.SessionRespBroadcastScoJoin:
|
||||||
|
container.Output <- "Scourge has joined the game"
|
||||||
|
case coordinator.SessionRespBroadcastSenJoin:
|
||||||
|
container.Output <- "Sentinal has joined the game"
|
||||||
|
case coordinator.SessionRespBroadcastScoLeft:
|
||||||
|
container.Output <- "Scourge has left the game"
|
||||||
|
case coordinator.SessionRespBroadcastSenLeft:
|
||||||
|
container.Output <- "Sentinal has left the game"
|
||||||
|
case coordinator.SessionRespBroadcastSenReady:
|
||||||
|
container.Output <- "Sentinal is ready"
|
||||||
|
case coordinator.SessionRespBroadcastScoReady:
|
||||||
|
container.Output <- "scourge is ready"
|
||||||
|
case coordinator.SessionRespBroadcastNone:
|
||||||
|
|
||||||
|
case coordinator.SessionRespError:
|
||||||
|
container.Output <- "generic error"
|
||||||
|
|
||||||
|
default:
|
||||||
|
container.Output <- "Received a server response we don't know how to handle"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func backend(container *UIContainer) {
|
||||||
|
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 coordinator.SessionCommand)
|
||||||
|
|
||||||
|
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"
|
||||||
|
id := uuid.New()
|
||||||
|
conn, _, err := websocket.DefaultDialer.Dial(socketUrl, nil)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Error connecting to Websocket Server:", err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
go receiveHandler(conn, container)
|
||||||
|
go GetCommand(id, cmd, container)
|
||||||
|
ticker := time.NewTicker(2 * time.Second)
|
||||||
|
// Our main loop for the client
|
||||||
|
// We send our relevant packets here
|
||||||
|
for {
|
||||||
|
var c coordinator.SessionCommand
|
||||||
|
select {
|
||||||
|
case c = <-cmd:
|
||||||
|
err := conn.WriteJSON(c)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error during writing to websocket:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if c.Command == coordinator.SessionCmdLeave {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case <-container.GetUpdate:
|
||||||
|
if container.State != nil {
|
||||||
|
err = conn.WriteJSON(&coordinator.SessionCommand{
|
||||||
|
ID: id,
|
||||||
|
MatchID: matchID,
|
||||||
|
Command: coordinator.SessionCmdPlay,
|
||||||
|
GameCommand: &game.Command{
|
||||||
|
PlayerID: pid,
|
||||||
|
Type: game.StateCmd,
|
||||||
|
Cmd: "g",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error during writing to websocker:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
container.Updated <- true
|
||||||
|
}
|
||||||
|
|
||||||
|
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(coordinator.SessionCommand{
|
||||||
|
ID: id,
|
||||||
|
Command: coordinator.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:
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
if matchID != uuid.Nil {
|
||||||
|
err := conn.WriteJSON(coordinator.SessionCommand{
|
||||||
|
ID: id,
|
||||||
|
MatchID: matchID,
|
||||||
|
Command: coordinator.SessionCmdPoll,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error writing to websocket:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCommand(uid uuid.UUID, resp chan coordinator.SessionCommand, container *UIContainer) {
|
||||||
|
for {
|
||||||
|
var cmd string
|
||||||
|
var t int
|
||||||
|
input := <-container.Input
|
||||||
|
input_s := strings.Split(input, " ")
|
||||||
|
t, err := strconv.Atoi(input_s[0])
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cmd = trimFirstRune(input)
|
||||||
|
|
||||||
|
cmd = strings.TrimSpace(cmd)
|
||||||
|
switch t {
|
||||||
|
case 0:
|
||||||
|
//session
|
||||||
|
switch coordinator.SessionCmd(cmd) {
|
||||||
|
case coordinator.SessionCmdQuery:
|
||||||
|
resp <- coordinator.SessionCommand{
|
||||||
|
ID: uid,
|
||||||
|
Command: coordinator.SessionCmdQuery,
|
||||||
|
}
|
||||||
|
case coordinator.SessionCmdJoin:
|
||||||
|
resp <- coordinator.SessionCommand{
|
||||||
|
ID: uid,
|
||||||
|
MatchID: matchID,
|
||||||
|
Command: coordinator.SessionCmdJoin,
|
||||||
|
}
|
||||||
|
case coordinator.SessionCmdLeave:
|
||||||
|
resp <- coordinator.SessionCommand{
|
||||||
|
ID: uid,
|
||||||
|
MatchID: matchID,
|
||||||
|
Command: coordinator.SessionCmdLeave,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
//state
|
||||||
|
resp <- coordinator.SessionCommand{
|
||||||
|
ID: uid,
|
||||||
|
MatchID: matchID,
|
||||||
|
Command: coordinator.SessionCmdPlay,
|
||||||
|
GameCommand: &game.Command{
|
||||||
|
PlayerID: pid,
|
||||||
|
Type: game.StateCmd,
|
||||||
|
Cmd: cmd,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
//action
|
||||||
|
resp <- coordinator.SessionCommand{
|
||||||
|
ID: uid,
|
||||||
|
MatchID: matchID,
|
||||||
|
Command: coordinator.SessionCmdPlay,
|
||||||
|
GameCommand: &game.Command{
|
||||||
|
PlayerID: pid,
|
||||||
|
Type: game.ActCmd,
|
||||||
|
Cmd: cmd,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func trimFirstRune(s string) string {
|
||||||
|
_, i := utf8.DecodeRuneInString(s)
|
||||||
|
return s[i:]
|
||||||
|
}
|
131
client2/main.go
Normal file
131
client2/main.go
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"code.rocketnine.space/tslocum/cview"
|
||||||
|
"git.saintnet.tech/stryan/snengame/internal/game"
|
||||||
|
"github.com/gdamore/tcell/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UIContainer struct {
|
||||||
|
State *game.GameView
|
||||||
|
Updated chan bool
|
||||||
|
Output chan string
|
||||||
|
Input chan string
|
||||||
|
GetUpdate chan bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := cview.NewApplication()
|
||||||
|
app.EnableMouse(true)
|
||||||
|
container := &UIContainer{
|
||||||
|
State: nil,
|
||||||
|
Updated: make(chan bool),
|
||||||
|
Output: make(chan string),
|
||||||
|
Input: make(chan string),
|
||||||
|
GetUpdate: make(chan bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
grid := cview.NewGrid()
|
||||||
|
grid.SetRows(3, 0, 0, 3, 3)
|
||||||
|
grid.SetColumns(30, 0, 30)
|
||||||
|
grid.SetBorders(true)
|
||||||
|
|
||||||
|
board := cview.NewTable()
|
||||||
|
board.SetBorders(true)
|
||||||
|
hand := cview.NewTable()
|
||||||
|
hand.SetBorders(true)
|
||||||
|
playerside := cview.NewTextView()
|
||||||
|
playerside.SetText("Game has not started")
|
||||||
|
playerside.SetTextAlign(cview.AlignCenter)
|
||||||
|
commandinput := cview.NewInputField()
|
||||||
|
commandoutput := cview.NewTextView()
|
||||||
|
commandinput.SetDoneFunc(func(key tcell.Key) {
|
||||||
|
container.Input <- commandinput.GetText()
|
||||||
|
commandinput.SetText("")
|
||||||
|
})
|
||||||
|
commandoutput.SetChangedFunc(func() {
|
||||||
|
app.Draw()
|
||||||
|
})
|
||||||
|
playerside.SetChangedFunc(func() {
|
||||||
|
app.Draw()
|
||||||
|
})
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-container.Updated:
|
||||||
|
playerside.Clear()
|
||||||
|
var pv string
|
||||||
|
if container.State != nil && container.State.Player != nil {
|
||||||
|
ct := "Noone"
|
||||||
|
if container.State.CurrentTurn == game.SentinalID {
|
||||||
|
ct = "Sentinal"
|
||||||
|
} else if container.State.CurrentTurn == game.ScourgeID {
|
||||||
|
ct = "Scourge"
|
||||||
|
}
|
||||||
|
pv = fmt.Sprintf("Your Life: %v\nEnemy Life: %v\nEnemy Hand size: %v\nEnemy Deck Size: %v\n\nCT:%v CD: %v, HD %v, Status: %v\n", container.State.Player.Life, container.State.EnemyLife, container.State.EnemyHandSize, container.State.EnemyDeckSize, ct, container.State.CanDraw, container.State.HasDrawn, container.State.Status)
|
||||||
|
} else {
|
||||||
|
pv = fmt.Sprintf("%v", "Awaiting player info")
|
||||||
|
}
|
||||||
|
fmt.Fprintf(playerside, "%v", pv)
|
||||||
|
|
||||||
|
for c := 0; c < 4; c++ {
|
||||||
|
color := tcell.ColorWhite.TrueColor()
|
||||||
|
be := "_"
|
||||||
|
if container.State != nil && container.State.Board != nil {
|
||||||
|
be = container.State.Board.Sentinal[c].String()
|
||||||
|
}
|
||||||
|
cell := cview.NewTableCell(be)
|
||||||
|
cell.SetTextColor(color)
|
||||||
|
cell.SetAlign(cview.AlignCenter)
|
||||||
|
board.SetCell(0, c, cell)
|
||||||
|
}
|
||||||
|
for c := 0; c < 4; c++ {
|
||||||
|
color := tcell.ColorWhite.TrueColor()
|
||||||
|
be := "_"
|
||||||
|
if container.State != nil && container.State.Board != nil {
|
||||||
|
be = container.State.Board.Scourge[c].String()
|
||||||
|
}
|
||||||
|
cell := cview.NewTableCell(be)
|
||||||
|
cell.SetTextColor(color)
|
||||||
|
cell.SetAlign(cview.AlignCenter)
|
||||||
|
board.SetCell(1, c, cell)
|
||||||
|
}
|
||||||
|
cols := 0
|
||||||
|
if container.State != nil && container.State.Player != nil && container.State.Player.Hand != nil {
|
||||||
|
cols = len(container.State.Player.Hand)
|
||||||
|
}
|
||||||
|
hand.Clear()
|
||||||
|
for c := 0; c < cols; c++ {
|
||||||
|
color := tcell.ColorWhite.TrueColor()
|
||||||
|
ce := "_"
|
||||||
|
if container.State != nil && container.State.Player != nil && container.State.Player.Hand != nil {
|
||||||
|
ce = container.State.Player.Hand[c].String()
|
||||||
|
}
|
||||||
|
cell := cview.NewTableCell(ce)
|
||||||
|
cell.SetTextColor(color)
|
||||||
|
cell.SetAlign(cview.AlignCenter)
|
||||||
|
hand.SetCell(0, c, cell)
|
||||||
|
}
|
||||||
|
app.Draw()
|
||||||
|
case o := <-container.Output:
|
||||||
|
commandoutput.Clear()
|
||||||
|
fmt.Fprintf(commandoutput, "Result: %v", o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
grid.AddItem(playerside, 1, 0, 2, 1, 0, 100, false)
|
||||||
|
grid.AddItem(board, 1, 1, 1, 1, 0, 100, false)
|
||||||
|
grid.AddItem(hand, 2, 1, 1, 1, 0, 100, false)
|
||||||
|
grid.AddItem(commandinput, 3, 0, 1, 3, 0, 0, true)
|
||||||
|
grid.AddItem(commandoutput, 4, 0, 1, 3, 0, 0, false)
|
||||||
|
container.Updated <- true
|
||||||
|
go backend(container)
|
||||||
|
app.SetRoot(grid, true)
|
||||||
|
if err := app.Run(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user