package games import ( "battlecamp-go-server/board" "battlecamp-go-server/player" "encoding/json" "log" "math/rand" "sync" "time" "github.com/go-stomp/stomp" ) type Game struct { Id int64 `json:"id"` StartTime int64 `json:"startTime"` EndTime int64 `json:"endTime"` Board *board.Board `json:"board"` Players []*player.Player `json:"-"` mutex sync.Mutex Winner *player.Player `json:"winner,omitempty"` } func NewGame(cols, rows int) *Game { createTime := time.Now().Unix() game := &Game{ StartTime: createTime, Board: board.New(cols, rows), Players: make([]*player.Player, 0), } return game } func (g *Game) Join(p *player.Player) { g.mutex.Lock() g.placePlayer(p) g.Players = append(g.Players, p) g.mutex.Unlock() } func (g *Game) placePlayer(p *player.Player) { xRange := g.Board.Width / 5 yRange := g.Board.Height for { x := rand.Intn(xRange) y := rand.Intn(yRange) if g.isValidPlayerPos(x, y) { p.Pos.X = x p.Pos.Y = y return } } } type updatePlayers struct { GameId int64 `json:"gameId"` Players []*player.Player `json:"players"` } type stompGameEnd struct { Type string `json:"type"` GameId int64 `json:"gameId"` Payload string `json:"payload"` } func (g *Game) Move(p *player.Player, direction string, sc *stomp.Conn) bool { if !(direction == "N" || direction == "W" || direction == "S" || direction == "E") { log.Printf("Illigal direction %v", direction) return false } newX := p.Pos.X newY := p.Pos.Y switch direction { case "N": newY-- case "W": newX-- case "S": newY++ case "E": newX++ } //TODO make thread safe if !g.isValidPlayerPos(newX, newY) { log.Printf("Illigal player pos oldX %v oldY %v newX %v newY %v dir %v ", p.Pos.X, p.Pos.Y, newX, newY, direction) return false } p.Pos.X = newX p.Pos.Y = newY // END TODO make tread safe up := updatePlayers{ GameId: g.Id, Players: g.Players, } b, _ := json.Marshal(up) sc.Send("/topic/go-battlecamp.update", "application/json;charset=utf-8", b, stomp.SendOpt.NoContentLength) if g.isWinner(p) { g.EndTime = time.Now().Unix() g.Winner = p ge := stompGameEnd{ Type: "GAME_END", GameId: g.Id, Payload: g.Winner.Id, } c, _ := json.Marshal(ge) sc.Send("/topic/go-battlecamp.game", "application/json;charset=utf-8", c, stomp.SendOpt.NoContentLength) } return true } func (g *Game) isWinner(p *player.Player) bool { return g.Board.Finish.X == p.Pos.X && g.Board.Finish.Y == p.Pos.Y } func (g *Game) isValidPlayerPos(x, y int) bool { if x < 0 || y < 0 || x >= g.Board.Width || y >= g.Board.Height { return false } t := g.Board.Get(x, y) if t == board.Rock { return false } return g.getPlayerAt(x, y) == nil } func (g *Game) getPlayerAt(x, y int) *player.Player { for _, p := range g.Players { if p.Pos.X == x && p.Pos.Y == y { return p } } return nil } func (g *Game) GetPlayer(playerId string) *player.Player { for _, p := range g.Players { if p.Id == playerId { return p } } return nil }