From 6cbd7d37aa03ae68634d3c981cfa77a6d257f534 Mon Sep 17 00:00:00 2001 From: Marco Date: Tue, 30 May 2023 22:01:20 +0200 Subject: [PATCH] Various changes 1. Make lobby a struct containing the players and a mutex used to lock itself 2. Wait for websocket connections to be established by both players before starting the game. 3. Add methods to write to and read from players --- main.go | 13 +++++++------ server/game.go | 30 +++++++++++++++++++----------- server/lobby.go | 47 ++++++++++++++++++++++++++++++++--------------- server/player.go | 35 +++++++++++++++++++++++++++++++---- server/server.go | 8 -------- 5 files changed, 89 insertions(+), 44 deletions(-) diff --git a/main.go b/main.go index 9788631..714e683 100644 --- a/main.go +++ b/main.go @@ -37,9 +37,12 @@ func main() { } func registerForRandomGame(c *gin.Context) { - player := server.NewPlayer(uuid.New()) + + lobby := server.GetLobby() + lobby.Lock() server.GetLobby().RegisterPlayer(player) + lobby.Unlock() log.Println("responding with player id ", player.Uuid) @@ -49,7 +52,6 @@ func registerForRandomGame(c *gin.Context) { } func registerWebSocketConnection(c *gin.Context) { - // w http.ResponseWriter, r *http.Request webSocketConn, err := websocket.Accept(c.Writer, c.Request, nil) if err != nil { log.Println(err) @@ -59,8 +61,6 @@ func registerWebSocketConnection(c *gin.Context) { } func waitForAndHandlePlayerID(ctx context.Context, conn websocket.Conn) { - // var playerInfo server.PlayerInfo - msgType, id, err := conn.Read(ctx) log.Println("read from websocket: ", msgType, id, err) @@ -74,7 +74,7 @@ func waitForAndHandlePlayerID(ctx context.Context, conn websocket.Conn) { } lobby := server.GetLobby() - player, found := lobby[uuid] + player, found := lobby.GetPlayer(uuid) if !found { conn.Close(websocket.StatusCode(400), "player not found") return @@ -82,5 +82,6 @@ func waitForAndHandlePlayerID(ctx context.Context, conn websocket.Conn) { if player.Conn != nil { player.Conn.Close(websocket.StatusCode(400), "closing existing connection") } - player.Conn = &conn + player.SetConnection(ctx, conn) + log.Println("player after setting connection: ", player) } diff --git a/server/game.go b/server/game.go index f5bcbce..fdbb7b9 100644 --- a/server/game.go +++ b/server/game.go @@ -25,13 +25,25 @@ func NewGame() *Game { return &game } +func (game Game) getPlayer1() *Player { + return &game.players[0] +} + +func (game Game) getPlayer2() *Player { + return &game.players[1] +} + func (game *Game) handle() { defer log.Println("Game ", game.id, ": handle() ended") + <-game.getPlayer1().wsConnEstablished + log.Println("WS connection for player 1 established") + <-game.getPlayer2().wsConnEstablished + log.Println("WS connection for player 2 established") + gameState := PlayerToMove - game.currentTurnPlayer = game.players[0] + game.currentTurnPlayer = *game.getPlayer1() var move *Move - var messageType int var receivedMessage []byte for { @@ -39,7 +51,7 @@ func (game *Game) handle() { switch gameState { case PlayerToMove: var err error - messageType, receivedMessage, err = ReadMessageFromPlayer(&game.currentTurnPlayer) + _, receivedMessage, err = game.currentTurnPlayer.ReadMessageFromPlayer() if err != nil { log.Println("Error while reading message:", err) // At the moment, we return when there is an error while reading a message. @@ -63,12 +75,12 @@ func (game *Game) handle() { game.currentTurnPlayer = game.players[0] } - err := WriteMessageToPlayer(&game.players[0], receivedMessage, messageType) + err := game.getPlayer1().WriteMessageToPlayer(receivedMessage) if err != nil { log.Println("Error during message writing:", err) continue } - err = WriteMessageToPlayer(&game.players[1], receivedMessage, messageType) + err = game.getPlayer2().WriteMessageToPlayer(receivedMessage) if err != nil { log.Println("Error during message writing:", err) continue @@ -87,15 +99,11 @@ func (game *Game) handle() { func (game *Game) addPlayersToGame(players [2]Player) { log.Printf("Adding players %s and %s to new game", players[0].Uuid.String(), players[1].Uuid.String()) - for _, player := range players { - player.InGame = true + for i := range players { + players[i].InGame = true } game.players = players go game.handle() } - -func removePlayersFromLobby(players [2]Player) { - panic("not yet implemented") -} diff --git a/server/lobby.go b/server/lobby.go index b9aca41..0a27c0c 100644 --- a/server/lobby.go +++ b/server/lobby.go @@ -1,14 +1,19 @@ package server import ( + "sync" + "github.com/google/uuid" ) -type Lobby map[uuid.UUID]Player +type Lobby struct { + players map[uuid.UUID]*Player + mutex sync.Mutex +} -var lobbyInstance Lobby = nil +var lobbyInstance *Lobby = nil -func GetLobby() Lobby { +func GetLobby() *Lobby { if lobbyInstance == nil { lobbyInstance = newLobby() } @@ -16,28 +21,40 @@ func GetLobby() Lobby { return lobbyInstance } -func newLobby() Lobby { - lobby := make(map[uuid.UUID]Player, 0) - return lobby +func newLobby() *Lobby { + return &Lobby{ + players: make(map[uuid.UUID]*Player, 0), + } } -func (lobby Lobby) RegisterPlayer(player *Player) { - lobby[player.Uuid] = *player +func (l *Lobby) RegisterPlayer(player *Player) { + l.players[player.Uuid] = player - var players []Player + var playersToBeAddedToGame []Player - for _, player := range lobby { + for _, player := range l.players { if !player.InGame { - players = append(players, player) + playersToBeAddedToGame = append(playersToBeAddedToGame, *player) } } - if len(players) < 2 { + if len(playersToBeAddedToGame) < 2 { return } game := NewGame() - - game.addPlayersToGame([2]Player(players[:2])) - + game.addPlayersToGame([2]Player(playersToBeAddedToGame[:2])) +} + +func (l *Lobby) GetPlayer(playerID uuid.UUID) (*Player, bool) { + player, found := l.players[playerID] + return player, found +} + +func (l *Lobby) Lock() { + l.mutex.Lock() +} + +func (l *Lobby) Unlock() { + l.mutex.Unlock() } diff --git a/server/player.go b/server/player.go index e4936aa..77ba137 100644 --- a/server/player.go +++ b/server/player.go @@ -1,14 +1,19 @@ package server import ( + "context" + "log" + "github.com/google/uuid" "nhooyr.io/websocket" ) type Player struct { - Uuid uuid.UUID - Conn *websocket.Conn - InGame bool + Uuid uuid.UUID + Conn *websocket.Conn + InGame bool + wsConnEstablished chan bool + context context.Context } type PlayerInfo struct { @@ -17,6 +22,28 @@ type PlayerInfo struct { func NewPlayer(uuid uuid.UUID) *Player { return &Player{ - Uuid: uuid, + Uuid: uuid, + Conn: nil, + InGame: false, + wsConnEstablished: make(chan bool), } } + +func (p *Player) SetConnection(ctx context.Context, conn websocket.Conn) { + p.Conn = &conn + p.context = ctx + p.wsConnEstablished <- true +} + +func (p *Player) WriteMessageToPlayer(msg []byte) error { + log.Printf("Writing message: %s to player %d", string(msg), p.Uuid) + + return p.Conn.Write(p.context, websocket.MessageText, msg) +} + +func (p *Player) ReadMessageFromPlayer() (websocket.MessageType, []byte, error) { + msgType, msg, err := p.Conn.Read(p.context) + log.Printf("Reading message: %s (with messagetype %d) from player %d", string(msg), msgType, p.Uuid) + + return msgType, msg, err +} diff --git a/server/server.go b/server/server.go index 7af7cdb..ecbaa55 100644 --- a/server/server.go +++ b/server/server.go @@ -9,11 +9,3 @@ var AppPath = "/home/m/projects/programming/flutter_projects/mchess/build/web" func PlayHandler(w http.ResponseWriter, r *http.Request) { } - -func WriteMessageToPlayer(player *Player, msg []byte, msgType int) error { - panic("Not implemented") -} - -func ReadMessageFromPlayer(player *Player) (messageType int, p []byte, err error) { - panic("Not implemented") -}