snengame/internal/coordinator/session.go

143 lines
3.9 KiB
Go

package coordinator
import (
"fmt"
"time"
"git.saintnet.tech/stryan/snengame/internal/game"
"github.com/google/uuid"
)
type SessionCmd string
type SessionResp string
const (
SessionCmdQuery SessionCmd = "query"
SessionCmdJoin = "join"
SessionCmdLeave = "leave"
SessionCmdPlay = "play"
SessionCmdPoll = "poll"
SessionCmdReady = "ready"
)
const (
SessionRespFound SessionResp = "found"
SessionRespJoined1 = "joined p1"
SessionRespJoined2 = "joined p2"
SessionRespReady = "game ready"
SessionRespJoinError = "join error"
SessionRespLeft = "left"
SessionRespPlayed = "played"
SessionRespError = "generic error"
SessionRespBroadcastSenTurn = "Sentinal turn"
SessionRespBroadcastScoTrun = "Scourge turn"
SessionRespBroadcastSenWin = "Sentinal wins"
SessionRespBroadcastScoWin = "Scourge wins"
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 {
ID uuid.UUID
p1 uuid.UUID
p2 uuid.UUID
pMap map[uuid.UUID]int
Active bool
Game *game.Game
Watcher chan bool
Broadcasts map[uuid.UUID]chan SessionResp
LastMove time.Time
}
func NewSession() *Session {
return &Session{
ID: uuid.New(),
p1: uuid.Nil,
p2: uuid.Nil,
pMap: make(map[uuid.UUID]int),
Active: false,
Game: nil,
Watcher: make(chan bool),
Broadcasts: make(map[uuid.UUID]chan SessionResp),
LastMove: time.Now(),
}
}
func (s *Session) Join(id uuid.UUID) SessionResp {
if s.p1 == uuid.Nil {
s.p1 = id
s.pMap[id] = game.SentinalID
for _, v := range s.Broadcasts {
v <- SessionRespBroadcastSenJoin
}
return SessionRespJoined1
} else if s.p2 == uuid.Nil {
s.p2 = id
s.pMap[id] = game.ScourgeID
for _, v := range s.Broadcasts {
v <- SessionRespBroadcastScoJoin
}
return SessionRespJoined2
} else {
return SessionRespJoinError
}
}
func (s *Session) Leave(id uuid.UUID) {
if id == s.p1 {
s.p1 = uuid.Nil
} else if id == s.p2 {
s.p2 = uuid.Nil
}
delete(s.Broadcasts, id)
if s.p1 == uuid.Nil && s.p2 == uuid.Nil {
s.Game = nil
} else if s.Game.Status != game.StatusDraw || s.Game.Status != game.StatusScourgeWin || s.Game.Status != game.StatusSentinalWin {
s.Game.Status = game.StatusStop
}
}
func (s *Session) Play(id uuid.UUID, cmd *game.Command) *game.CommandResult {
if s.pMap[id] != cmd.PlayerID {
return nil
}
if cmd.Type != SessionCmdPoll {
s.LastMove = time.Now()
}
res := s.Game.Parse(cmd)
return res
}
func (s *Session) PlayerIn(id uuid.UUID) bool {
_, exists := s.pMap[id]
return exists
}
type SessionCommand struct {
ID uuid.UUID `json:"player_id"`
MatchID uuid.UUID `json:"match_id"`
Command SessionCmd `json:"command"`
GameCommand *game.Command `json:"game_command,omitempty"`
}
func (s *SessionCommand) String() string {
return fmt.Sprintf("%v %v %v\n", s.ID, s.Command, s.GameCommand)
}
type SessionCommandResult struct {
ID uuid.UUID `json:"player_id"`
MatchID uuid.UUID `json:"match_id"`
Result SessionResp `json:"result"`
GameResult *game.CommandResult `json:"game_result,omitempty"`
}
func (s *SessionCommandResult) String() string {
return fmt.Sprintf("%v %v %v\n", s.ID, s.Result, s.GameResult)
}