more broadcasts, tui client running
This commit is contained in:
parent
379719a2e2
commit
f06754fcfe
4
Makefile
4
Makefile
@ -6,10 +6,12 @@ ifeq ($(PREFIX),) # PREFIX is environment variable, but if it is not set, then s
|
|||||||
PREFIX := /usr/local
|
PREFIX := /usr/local
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: client server engine
|
all: client client2 server engine
|
||||||
|
|
||||||
client: $(GAMEFILES) $(wildcard cmd/client/*.go)
|
client: $(GAMEFILES) $(wildcard cmd/client/*.go)
|
||||||
go build -ldflags "-X main.GitCommit=$(GIT_COMMIT)" ./cmd/client
|
go build -ldflags "-X main.GitCommit=$(GIT_COMMIT)" ./cmd/client
|
||||||
|
client2: $(GAMEFILES) $(wildcard cmd/client2/*.go)
|
||||||
|
go build -ldflags "-X main.GitCommit=$(GIT_COMMIT)" ./cmd/client2
|
||||||
server: $(GAMEFILES) $(COORDFILEs) $(wildcard cmd/server/*.go)
|
server: $(GAMEFILES) $(COORDFILEs) $(wildcard cmd/server/*.go)
|
||||||
go build -ldflags "-X main.GitCommit=$(GIT_COMMIT)" ./cmd/server
|
go build -ldflags "-X main.GitCommit=$(GIT_COMMIT)" ./cmd/server
|
||||||
engine: $(GAMEFILES)
|
engine: $(GAMEFILES)
|
||||||
|
@ -66,6 +66,20 @@ func receiveHandler(connection *websocket.Conn, output chan string) {
|
|||||||
output <- "Sentinal wins!"
|
output <- "Sentinal wins!"
|
||||||
case coordinator.SessionRespBroadcastScoWin:
|
case coordinator.SessionRespBroadcastScoWin:
|
||||||
output <- "Scourge wins!"
|
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.SessionRespBroadcastNone:
|
||||||
|
|
||||||
case coordinator.SessionRespError:
|
case coordinator.SessionRespError:
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"code.rocketnine.space/tslocum/cview"
|
|
||||||
"git.saintnet.tech/stryan/snengame/internal/coordinator"
|
"git.saintnet.tech/stryan/snengame/internal/coordinator"
|
||||||
"git.saintnet.tech/stryan/snengame/internal/game"
|
"git.saintnet.tech/stryan/snengame/internal/game"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@ -22,7 +21,7 @@ var interrupt chan os.Signal
|
|||||||
var pid int
|
var pid int
|
||||||
var matchID uuid.UUID
|
var matchID uuid.UUID
|
||||||
|
|
||||||
func receiveHandler(connection *websocket.Conn, output chan string) {
|
func receiveHandler(connection *websocket.Conn, container *UIContainer) {
|
||||||
defer close(done)
|
defer close(done)
|
||||||
for {
|
for {
|
||||||
var resp coordinator.SessionCommandResult
|
var resp coordinator.SessionCommandResult
|
||||||
@ -33,54 +32,67 @@ func receiveHandler(connection *websocket.Conn, output chan string) {
|
|||||||
switch resp.Result {
|
switch resp.Result {
|
||||||
case coordinator.SessionRespJoined1:
|
case coordinator.SessionRespJoined1:
|
||||||
pid = game.SentinalID
|
pid = game.SentinalID
|
||||||
output <- "joined as sentinal"
|
container.Output <- "joined as sentinal"
|
||||||
case coordinator.SessionRespJoined2:
|
case coordinator.SessionRespJoined2:
|
||||||
pid = game.ScourgeID
|
pid = game.ScourgeID
|
||||||
output <- "joined as scourge"
|
container.Output <- "joined as scourge"
|
||||||
case coordinator.SessionRespFound:
|
case coordinator.SessionRespFound:
|
||||||
matchID = resp.MatchID
|
matchID = resp.MatchID
|
||||||
output <- "game found"
|
container.Output <- "game found"
|
||||||
case coordinator.SessionRespPlayed:
|
case coordinator.SessionRespPlayed:
|
||||||
if resp.GameResult != nil {
|
if resp.GameResult != nil {
|
||||||
output <- "played succesfully"
|
|
||||||
switch resp.GameResult.ResultType {
|
switch resp.GameResult.ResultType {
|
||||||
case game.ActCmd:
|
case game.ActCmd:
|
||||||
output <- resp.GameResult.ActionResult.String()
|
container.Output <- resp.GameResult.ActionResult.String()
|
||||||
case game.StateCmd:
|
case game.StateCmd:
|
||||||
output <- resp.GameResult.StateResult.String()
|
container.State = resp.GameResult.StateResult
|
||||||
|
container.Updated <- true
|
||||||
case game.DebugCmd:
|
case game.DebugCmd:
|
||||||
output <- resp.GameResult.DebugResult.String()
|
container.Output <- resp.GameResult.DebugResult.String()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
output <- "error playing"
|
container.Output <- "error playing"
|
||||||
}
|
}
|
||||||
case coordinator.SessionRespLeft:
|
case coordinator.SessionRespLeft:
|
||||||
output <- "game left"
|
container.Output <- "game left"
|
||||||
break
|
break
|
||||||
case coordinator.SessionRespBroadcastSenTurn:
|
case coordinator.SessionRespBroadcastSenTurn:
|
||||||
output <- "Sentinal may take their turn"
|
container.Output <- "Sentinal may take their turn"
|
||||||
case coordinator.SessionRespBroadcastScoTrun:
|
case coordinator.SessionRespBroadcastScoTrun:
|
||||||
output <- "Scourge may take their turn"
|
container.Output <- "Scourge may take their turn"
|
||||||
case coordinator.SessionRespBroadcastSenWin:
|
case coordinator.SessionRespBroadcastSenWin:
|
||||||
output <- "Sentinal wins!"
|
container.Output <- "Sentinal wins!"
|
||||||
case coordinator.SessionRespBroadcastScoWin:
|
case coordinator.SessionRespBroadcastScoWin:
|
||||||
output <- "Scourge wins!"
|
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.SessionRespBroadcastNone:
|
||||||
|
|
||||||
case coordinator.SessionRespError:
|
case coordinator.SessionRespError:
|
||||||
output <- "generic error"
|
container.Output <- "generic error"
|
||||||
|
|
||||||
default:
|
default:
|
||||||
output <- "Received a server response we don't know how to handle"
|
container.Output <- "Received a server response we don't know how to handle"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func backend(input chan string, outputview *cview.TextView) {
|
func backend(container *UIContainer) {
|
||||||
done = make(chan interface{}) // Channel to indicate that the receiverHandler is done
|
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
|
interrupt = make(chan os.Signal) // Channel to listen for interrupt signal to terminate gracefully
|
||||||
cmd := make(chan coordinator.SessionCommand)
|
cmd := make(chan coordinator.SessionCommand)
|
||||||
output := make(chan string)
|
|
||||||
|
|
||||||
signal.Notify(interrupt, os.Interrupt) // Notify the interrupt channel for SIGINT
|
signal.Notify(interrupt, os.Interrupt) // Notify the interrupt channel for SIGINT
|
||||||
hostname := flag.String("host", "localhost", "server hostname to connect to")
|
hostname := flag.String("host", "localhost", "server hostname to connect to")
|
||||||
@ -89,21 +101,20 @@ func backend(input chan string, outputview *cview.TextView) {
|
|||||||
flag.Parse()
|
flag.Parse()
|
||||||
port_s := strconv.Itoa(*port)
|
port_s := strconv.Itoa(*port)
|
||||||
socketUrl := "ws://" + *hostname + ":" + port_s + "/ws"
|
socketUrl := "ws://" + *hostname + ":" + port_s + "/ws"
|
||||||
conn, _, err := websocket.DefaultDialer.Dial(socketUrl, nil)
|
|
||||||
id := uuid.New()
|
id := uuid.New()
|
||||||
|
conn, _, err := websocket.DefaultDialer.Dial(socketUrl, nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Error connecting to Websocket Server:", err)
|
log.Fatal("Error connecting to Websocket Server:", err)
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
go receiveHandler(conn, output)
|
go receiveHandler(conn, container)
|
||||||
go GetCommand(id, cmd, input)
|
go GetCommand(id, cmd, container)
|
||||||
ticker := time.NewTicker(1 * time.Second)
|
ticker := time.NewTicker(2 * time.Second)
|
||||||
// Our main loop for the client
|
// Our main loop for the client
|
||||||
// We send our relevant packets here
|
// We send our relevant packets here
|
||||||
for {
|
for {
|
||||||
var c coordinator.SessionCommand
|
var c coordinator.SessionCommand
|
||||||
var o string
|
|
||||||
select {
|
select {
|
||||||
case c = <-cmd:
|
case c = <-cmd:
|
||||||
err := conn.WriteJSON(c)
|
err := conn.WriteJSON(c)
|
||||||
@ -114,8 +125,25 @@ func backend(input chan string, outputview *cview.TextView) {
|
|||||||
if c.Command == coordinator.SessionCmdLeave {
|
if c.Command == coordinator.SessionCmdLeave {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case o = <-output:
|
case <-container.GetUpdate:
|
||||||
outputview.SetText(o)
|
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:
|
case <-interrupt:
|
||||||
// We received a SIGINT (Ctrl + C). Terminate gracefully...
|
// We received a SIGINT (Ctrl + C). Terminate gracefully...
|
||||||
log.Println("Received SIGINT interrupt signal. Closing all pending connections")
|
log.Println("Received SIGINT interrupt signal. Closing all pending connections")
|
||||||
@ -153,11 +181,11 @@ func backend(input chan string, outputview *cview.TextView) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCommand(uid uuid.UUID, resp chan coordinator.SessionCommand, inputchan chan string) {
|
func GetCommand(uid uuid.UUID, resp chan coordinator.SessionCommand, container *UIContainer) {
|
||||||
for {
|
for {
|
||||||
var cmd string
|
var cmd string
|
||||||
var t int
|
var t int
|
||||||
input := <-inputchan
|
input := <-container.Input
|
||||||
input_s := strings.Split(input, " ")
|
input_s := strings.Split(input, " ")
|
||||||
t, err := strconv.Atoi(input_s[0])
|
t, err := strconv.Atoi(input_s[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,20 +1,32 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"code.rocketnine.space/tslocum/cview"
|
"code.rocketnine.space/tslocum/cview"
|
||||||
|
"git.saintnet.tech/stryan/snengame/internal/game"
|
||||||
"github.com/gdamore/tcell/v2"
|
"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() {
|
func main() {
|
||||||
app := cview.NewApplication()
|
app := cview.NewApplication()
|
||||||
app.EnableMouse(true)
|
app.EnableMouse(true)
|
||||||
newPrimitive := func(text string) cview.Primitive {
|
container := &UIContainer{
|
||||||
tv := cview.NewTextView()
|
State: nil,
|
||||||
tv.SetTextAlign(cview.AlignCenter)
|
Updated: make(chan bool),
|
||||||
tv.SetText(text)
|
Output: make(chan string),
|
||||||
return tv
|
Input: make(chan string),
|
||||||
|
GetUpdate: make(chan bool),
|
||||||
}
|
}
|
||||||
inputchan := make(chan string)
|
|
||||||
grid := cview.NewGrid()
|
grid := cview.NewGrid()
|
||||||
grid.SetRows(3, 0, 0, 3, 3)
|
grid.SetRows(3, 0, 0, 3, 3)
|
||||||
grid.SetColumns(30, 0, 30)
|
grid.SetColumns(30, 0, 30)
|
||||||
@ -22,55 +34,95 @@ func main() {
|
|||||||
|
|
||||||
board := cview.NewTable()
|
board := cview.NewTable()
|
||||||
board.SetBorders(true)
|
board.SetBorders(true)
|
||||||
cols, rows := 4, 2
|
|
||||||
for r := 0; r < rows; r++ {
|
|
||||||
for c := 0; c < cols; c++ {
|
|
||||||
color := tcell.ColorWhite.TrueColor()
|
|
||||||
if c < 1 || r < 1 {
|
|
||||||
color = tcell.ColorYellow.TrueColor()
|
|
||||||
}
|
|
||||||
cell := cview.NewTableCell("test")
|
|
||||||
cell.SetTextColor(color)
|
|
||||||
cell.SetAlign(cview.AlignCenter)
|
|
||||||
board.SetCell(r, c, cell)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rows = 1
|
|
||||||
hand := cview.NewTable()
|
hand := cview.NewTable()
|
||||||
hand.SetBorders(true)
|
hand.SetBorders(true)
|
||||||
for r := 0; r < rows; r++ {
|
playerside := cview.NewTextView()
|
||||||
for c := 0; c < cols; c++ {
|
playerside.SetText("Game has not started")
|
||||||
color := tcell.ColorWhite.TrueColor()
|
playerside.SetTextAlign(cview.AlignCenter)
|
||||||
if c < 1 || r < 1 {
|
|
||||||
color = tcell.ColorYellow.TrueColor()
|
|
||||||
}
|
|
||||||
cell := cview.NewTableCell("test")
|
|
||||||
cell.SetTextColor(color)
|
|
||||||
cell.SetAlign(cview.AlignCenter)
|
|
||||||
hand.SetCell(r, c, cell)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
playerside := newPrimitive("Player")
|
|
||||||
oppside := newPrimitive("Opponent")
|
|
||||||
commandinput := cview.NewInputField()
|
commandinput := cview.NewInputField()
|
||||||
commandoutput := cview.NewTextView()
|
commandoutput := cview.NewTextView()
|
||||||
commandinput.SetDoneFunc(func(key tcell.Key) {
|
commandinput.SetDoneFunc(func(key tcell.Key) {
|
||||||
inputchan <- commandinput.GetText()
|
container.Input <- commandinput.GetText()
|
||||||
commandinput.SetText("")
|
commandinput.SetText("")
|
||||||
})
|
})
|
||||||
commandoutput.SetChangedFunc(func() {
|
commandoutput.SetChangedFunc(func() {
|
||||||
app.Draw()
|
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)
|
||||||
|
}
|
||||||
|
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(playerside, 1, 0, 2, 1, 0, 100, false)
|
||||||
grid.AddItem(board, 1, 1, 1, 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(hand, 2, 1, 1, 1, 0, 100, false)
|
||||||
grid.AddItem(oppside, 1, 2, 2, 1, 0, 100, false)
|
|
||||||
grid.AddItem(commandinput, 3, 0, 1, 3, 0, 0, true)
|
grid.AddItem(commandinput, 3, 0, 1, 3, 0, 0, true)
|
||||||
grid.AddItem(commandoutput, 4, 0, 1, 3, 0, 0, false)
|
grid.AddItem(commandoutput, 4, 0, 1, 3, 0, 0, false)
|
||||||
go backend(inputchan, commandoutput)
|
container.Updated <- true
|
||||||
|
go backend(container)
|
||||||
app.SetRoot(grid, true)
|
app.SetRoot(grid, true)
|
||||||
if err := app.Run(); err != nil {
|
if err := app.Run(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
2
go.mod
2
go.mod
@ -3,6 +3,8 @@ module git.saintnet.tech/stryan/snengame
|
|||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
code.rocketnine.space/tslocum/cview v1.5.6 // indirect
|
||||||
|
github.com/gdamore/tcell/v2 v2.4.0 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
)
|
)
|
||||||
|
34
go.sum
34
go.sum
@ -1,4 +1,38 @@
|
|||||||
|
code.rocketnine.space/tslocum/cbind v0.1.5 h1:i6NkeLLNPNMS4NWNi3302Ay3zSU6MrqOT+yJskiodxE=
|
||||||
|
code.rocketnine.space/tslocum/cbind v0.1.5/go.mod h1:LtfqJTzM7qhg88nAvNhx+VnTjZ0SXBJtxBObbfBWo/M=
|
||||||
|
code.rocketnine.space/tslocum/cview v1.5.6 h1:W0HJFIIgly3LzYoTitZIIaYDDqW0u/qmA0B6jWzw6R0=
|
||||||
|
code.rocketnine.space/tslocum/cview v1.5.6/go.mod h1:RogJMObbKuGiP8+9WsFsHpPeQQqgkCXgvTLxh7IH5eE=
|
||||||
|
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||||
|
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||||
|
github.com/gdamore/tcell/v2 v2.2.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU=
|
||||||
|
github.com/gdamore/tcell/v2 v2.3.11 h1:ECO6WqHGbKZ3HrSL7bG/zArMCmLaNr5vcjjMVnLHpzc=
|
||||||
|
github.com/gdamore/tcell/v2 v2.3.11/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU=
|
||||||
|
github.com/gdamore/tcell/v2 v2.4.0 h1:W6dxJEmaxYvhICFoTY3WrLLEXsQ11SaFnKGVEXW57KM=
|
||||||
|
github.com/gdamore/tcell/v2 v2.4.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
|
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||||
|
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||||
|
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
|
||||||
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
@ -148,10 +148,29 @@ func (c *Coordinator) Coordinate(cmd *SessionCommand) *SessionCommandResult {
|
|||||||
func MatchWatcher(m *Session) {
|
func MatchWatcher(m *Session) {
|
||||||
ticker := time.NewTicker(1 * time.Second)
|
ticker := time.NewTicker(1 * time.Second)
|
||||||
old_turn := -1
|
old_turn := -1
|
||||||
|
var old_board *game.Board
|
||||||
|
old_sen_hand := -1
|
||||||
|
old_sco_hand := -1
|
||||||
|
old_sen_life := -1
|
||||||
|
old_sco_life := -1
|
||||||
|
sen_ready := false
|
||||||
|
sco_ready := false
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
if m.Active && m.Game != nil {
|
if m.Active && m.Game != nil {
|
||||||
|
if m.Game.Status == game.StatusLobby && !sen_ready && m.Game.SentinalPlayer.Ready {
|
||||||
|
for _, v := range m.Broadcasts {
|
||||||
|
v <- SessionRespBroadcastSenReady
|
||||||
|
}
|
||||||
|
sen_ready = true
|
||||||
|
}
|
||||||
|
if m.Game.Status == game.StatusLobby && !sco_ready && m.Game.ScourgePlayer.Ready {
|
||||||
|
for _, v := range m.Broadcasts {
|
||||||
|
v <- SessionRespBroadcastScoReady
|
||||||
|
}
|
||||||
|
sco_ready = true
|
||||||
|
}
|
||||||
if m.Game.Status == game.StatusSentinalWin {
|
if m.Game.Status == game.StatusSentinalWin {
|
||||||
for _, v := range m.Broadcasts {
|
for _, v := range m.Broadcasts {
|
||||||
v <- SessionRespBroadcastSenWin
|
v <- SessionRespBroadcastSenWin
|
||||||
@ -162,6 +181,33 @@ func MatchWatcher(m *Session) {
|
|||||||
v <- SessionRespBroadcastScoWin
|
v <- SessionRespBroadcastScoWin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if m.p1 == uuid.Nil && sen_ready {
|
||||||
|
for _, v := range m.Broadcasts {
|
||||||
|
v <- SessionRespBroadcastSenLeft
|
||||||
|
}
|
||||||
|
sen_ready = false
|
||||||
|
}
|
||||||
|
if m.p2 == uuid.Nil && sco_ready {
|
||||||
|
for _, v := range m.Broadcasts {
|
||||||
|
v <- SessionRespBroadcastScoLeft
|
||||||
|
}
|
||||||
|
sco_ready = false
|
||||||
|
}
|
||||||
|
if old_board == nil || old_board.Sentinal != m.Game.GameBoard.Sentinal || old_board.Scourge != m.Game.GameBoard.Scourge || old_sen_hand != len(m.Game.SentinalPlayer.Hand) || old_sco_hand != len(m.Game.ScourgePlayer.Hand) || old_sen_life != m.Game.SentinalPlayer.Life || old_sco_life != m.Game.ScourgePlayer.Life {
|
||||||
|
if old_board == nil {
|
||||||
|
old_board = m.Game.GameBoard
|
||||||
|
} else {
|
||||||
|
old_board.Sentinal = m.Game.GameBoard.Sentinal
|
||||||
|
old_board.Scourge = m.Game.GameBoard.Scourge
|
||||||
|
}
|
||||||
|
old_sen_hand = len(m.Game.SentinalPlayer.Hand)
|
||||||
|
old_sco_hand = len(m.Game.ScourgePlayer.Hand)
|
||||||
|
old_sen_life = m.Game.SentinalPlayer.Life
|
||||||
|
old_sco_life = m.Game.ScourgePlayer.Life
|
||||||
|
for _, v := range m.Broadcasts {
|
||||||
|
v <- SessionRespBroadcastUpdate
|
||||||
|
}
|
||||||
|
}
|
||||||
if old_turn != m.Game.CurrentTurn {
|
if old_turn != m.Game.CurrentTurn {
|
||||||
old_turn = m.Game.CurrentTurn
|
old_turn = m.Game.CurrentTurn
|
||||||
if old_turn == game.SentinalID {
|
if old_turn == game.SentinalID {
|
||||||
|
@ -19,18 +19,25 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SessionRespFound SessionResp = "found"
|
SessionRespFound SessionResp = "found"
|
||||||
SessionRespJoined1 = "joined p1"
|
SessionRespJoined1 = "joined p1"
|
||||||
SessionRespJoined2 = "joined p2"
|
SessionRespJoined2 = "joined p2"
|
||||||
SessionRespJoinError = "join error"
|
SessionRespJoinError = "join error"
|
||||||
SessionRespLeft = "left"
|
SessionRespLeft = "left"
|
||||||
SessionRespPlayed = "played"
|
SessionRespPlayed = "played"
|
||||||
SessionRespError = "generic error"
|
SessionRespError = "generic error"
|
||||||
SessionRespBroadcastSenTurn = "Sentinal turn"
|
SessionRespBroadcastSenTurn = "Sentinal turn"
|
||||||
SessionRespBroadcastScoTrun = "Scourge turn"
|
SessionRespBroadcastScoTrun = "Scourge turn"
|
||||||
SessionRespBroadcastSenWin = "Sentinal wins"
|
SessionRespBroadcastSenWin = "Sentinal wins"
|
||||||
SessionRespBroadcastScoWin = "Scourge wins"
|
SessionRespBroadcastScoWin = "Scourge wins"
|
||||||
SessionRespBroadcastNone = ""
|
SessionRespBroadcastUpdate = "update"
|
||||||
|
SessionRespBroadcastSenJoin = "Sentinal joined"
|
||||||
|
SessionRespBroadcastScoJoin = "Scourge joined"
|
||||||
|
SessionRespBroadcastSenReady = "Sentinal player is ready"
|
||||||
|
SessionRespBroadcastScoReady = "Scourge player is ready"
|
||||||
|
SessionRespBroadcastSenLeft = "Sentinal player has left"
|
||||||
|
SessionRespBroadcastScoLeft = "Scourge player has left"
|
||||||
|
SessionRespBroadcastNone = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
type Session struct {
|
type Session struct {
|
||||||
@ -61,11 +68,17 @@ func (s *Session) Join(id uuid.UUID) SessionResp {
|
|||||||
if s.p1 == uuid.Nil {
|
if s.p1 == uuid.Nil {
|
||||||
s.p1 = id
|
s.p1 = id
|
||||||
s.pMap[id] = game.SentinalID
|
s.pMap[id] = game.SentinalID
|
||||||
|
for _, v := range s.Broadcasts {
|
||||||
|
v <- SessionRespBroadcastSenJoin
|
||||||
|
}
|
||||||
s.Broadcasts[id] = make(chan SessionResp)
|
s.Broadcasts[id] = make(chan SessionResp)
|
||||||
return SessionRespJoined1
|
return SessionRespJoined1
|
||||||
} else if s.p2 == uuid.Nil {
|
} else if s.p2 == uuid.Nil {
|
||||||
s.p2 = id
|
s.p2 = id
|
||||||
s.pMap[id] = game.ScourgeID
|
s.pMap[id] = game.ScourgeID
|
||||||
|
for _, v := range s.Broadcasts {
|
||||||
|
v <- SessionRespBroadcastScoJoin
|
||||||
|
}
|
||||||
s.Broadcasts[id] = make(chan SessionResp)
|
s.Broadcasts[id] = make(chan SessionResp)
|
||||||
return SessionRespJoined2
|
return SessionRespJoined2
|
||||||
} else {
|
} else {
|
||||||
@ -79,6 +92,7 @@ func (s *Session) Leave(id uuid.UUID) {
|
|||||||
} else if id == s.p2 {
|
} else if id == s.p2 {
|
||||||
s.p2 = uuid.Nil
|
s.p2 = uuid.Nil
|
||||||
}
|
}
|
||||||
|
delete(s.Broadcasts, id)
|
||||||
if s.p1 == uuid.Nil && s.p2 == uuid.Nil {
|
if s.p1 == uuid.Nil && s.p2 == uuid.Nil {
|
||||||
s.Game = nil
|
s.Game = nil
|
||||||
} else if s.Game.Status != game.StatusDraw || s.Game.Status != game.StatusScourgeWin || s.Game.Status != game.StatusSentinalWin {
|
} else if s.Game.Status != game.StatusDraw || s.Game.Status != game.StatusScourgeWin || s.Game.Status != game.StatusSentinalWin {
|
||||||
|
@ -158,18 +158,34 @@ func (g *Game) PlayerStateAct(id int, cmd string) *GameView {
|
|||||||
return NewView(id, g)
|
return NewView(id, g)
|
||||||
case "b":
|
case "b":
|
||||||
//begin game
|
//begin game
|
||||||
g.Status = StatusReady
|
if g.SentinalPlayer.Ready && g.ScourgePlayer.Ready && g.Status == StatusLobby {
|
||||||
//TODO check for ready on both accounts first
|
g.Status = StatusReady
|
||||||
g.SentinalPlayer.Hand = g.SentinalDeck.Cards[len(g.SentinalDeck.Cards)-5 : len(g.SentinalDeck.Cards)]
|
if id == SentinalID {
|
||||||
g.SentinalDeck.Cards = g.SentinalDeck.Cards[0 : len(g.SentinalDeck.Cards)-5]
|
g.SentinalPlayer.Hand = g.SentinalDeck.Cards[len(g.SentinalDeck.Cards)-5 : len(g.SentinalDeck.Cards)]
|
||||||
|
g.SentinalDeck.Cards = g.SentinalDeck.Cards[0 : len(g.SentinalDeck.Cards)-5]
|
||||||
|
|
||||||
g.ScourgePlayer.Hand = g.ScourgeDeck.Cards[len(g.ScourgeDeck.Cards)-5 : len(g.ScourgeDeck.Cards)]
|
g.ScourgePlayer.Hand = g.ScourgeDeck.Cards[len(g.ScourgeDeck.Cards)-6 : len(g.ScourgeDeck.Cards)]
|
||||||
g.ScourgeDeck.Cards = g.ScourgeDeck.Cards[0 : len(g.ScourgeDeck.Cards)-5]
|
g.ScourgeDeck.Cards = g.ScourgeDeck.Cards[0 : len(g.ScourgeDeck.Cards)-6]
|
||||||
|
g.CurrentTurn = SentinalID
|
||||||
|
} else {
|
||||||
|
g.SentinalPlayer.Hand = g.SentinalDeck.Cards[len(g.SentinalDeck.Cards)-6 : len(g.SentinalDeck.Cards)]
|
||||||
|
g.SentinalDeck.Cards = g.SentinalDeck.Cards[0 : len(g.SentinalDeck.Cards)-6]
|
||||||
|
|
||||||
|
g.ScourgePlayer.Hand = g.ScourgeDeck.Cards[len(g.ScourgeDeck.Cards)-5 : len(g.ScourgeDeck.Cards)]
|
||||||
|
g.ScourgeDeck.Cards = g.ScourgeDeck.Cards[0 : len(g.ScourgeDeck.Cards)-5]
|
||||||
|
g.CurrentTurn = ScourgeID
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if id == SentinalID {
|
||||||
|
g.SentinalPlayer.Ready = true
|
||||||
|
} else if id == ScourgeID {
|
||||||
|
g.ScourgePlayer.Ready = true
|
||||||
|
}
|
||||||
|
}
|
||||||
case "s":
|
case "s":
|
||||||
//start turn
|
//start turn
|
||||||
if g.Status == StatusReady { //first turn
|
if g.Status == StatusReady { //first turn
|
||||||
g.Status = StatusPlaying
|
g.Status = StatusPlaying
|
||||||
g.CurrentTurn = id
|
|
||||||
}
|
}
|
||||||
g.CanDraw = true
|
g.CanDraw = true
|
||||||
g.HasDrawn = false
|
g.HasDrawn = false
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
package game
|
package game
|
||||||
|
|
||||||
type Player struct {
|
type Player struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Id int `json:"id"`
|
Id int `json:"id"`
|
||||||
Hand []*Card `json:"hand"`
|
Hand []*Card `json:"hand"`
|
||||||
Life int `json:"life"`
|
Life int `json:"life"`
|
||||||
|
Ready bool `json:"ready"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPlayer(name string, id int) *Player {
|
func NewPlayer(name string, id int) *Player {
|
||||||
return &Player{
|
return &Player{
|
||||||
Name: name,
|
Name: name,
|
||||||
Id: id,
|
Id: id,
|
||||||
Hand: []*Card{},
|
Hand: []*Card{},
|
||||||
Life: 3,
|
Life: 3,
|
||||||
|
Ready: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user