From aac428baab6106db58ad4402d1682f313fa52b22 Mon Sep 17 00:00:00 2001 From: Marco Date: Wed, 31 May 2023 23:55:40 +0200 Subject: [PATCH] First changes to move away from central registry of all players 1. Introduce 'usher' that opens lobbies and fills it and waits for them to be filled 2. Add global registry of all games --- {server => chess}/chess_move.go | 2 +- {server => chess}/lobby.go | 2 +- server/game.go => chess/match.go | 2 +- {server => chess}/player.go | 5 +++- {server => chess}/server.go | 2 +- lobby_registry/lobby.go | 33 +++++++++++++++++++++++++ lobby_registry/registry.go | 41 ++++++++++++++++++++++++++++++++ main.go | 25 ++++++++++++------- usher/usher.go | 39 ++++++++++++++++++++++++++++++ 9 files changed, 138 insertions(+), 13 deletions(-) rename {server => chess}/chess_move.go (94%) rename {server => chess}/lobby.go (98%) rename server/game.go => chess/match.go (99%) rename {server => chess}/player.go (93%) rename {server => chess}/server.go (91%) create mode 100644 lobby_registry/lobby.go create mode 100644 lobby_registry/registry.go create mode 100644 usher/usher.go diff --git a/server/chess_move.go b/chess/chess_move.go similarity index 94% rename from server/chess_move.go rename to chess/chess_move.go index 6a1f5d8..837d99c 100644 --- a/server/chess_move.go +++ b/chess/chess_move.go @@ -1,4 +1,4 @@ -package server +package chess type Move struct { StartSquare Coordinate `json:"startSquare"` diff --git a/server/lobby.go b/chess/lobby.go similarity index 98% rename from server/lobby.go rename to chess/lobby.go index 0a27c0c..2e524c4 100644 --- a/server/lobby.go +++ b/chess/lobby.go @@ -1,4 +1,4 @@ -package server +package chess import ( "sync" diff --git a/server/game.go b/chess/match.go similarity index 99% rename from server/game.go rename to chess/match.go index fdbb7b9..70d7f63 100644 --- a/server/game.go +++ b/chess/match.go @@ -1,4 +1,4 @@ -package server +package chess import ( "log" diff --git a/server/player.go b/chess/player.go similarity index 93% rename from server/player.go rename to chess/player.go index 77ba137..cc49a39 100644 --- a/server/player.go +++ b/chess/player.go @@ -1,4 +1,4 @@ -package server +package chess import ( "context" @@ -14,6 +14,8 @@ type Player struct { InGame bool wsConnEstablished chan bool context context.Context + + JoinedLobby chan bool } type PlayerInfo struct { @@ -26,6 +28,7 @@ func NewPlayer(uuid uuid.UUID) *Player { Conn: nil, InGame: false, wsConnEstablished: make(chan bool), + JoinedLobby: make(chan bool), } } diff --git a/server/server.go b/chess/server.go similarity index 91% rename from server/server.go rename to chess/server.go index ecbaa55..592e1c0 100644 --- a/server/server.go +++ b/chess/server.go @@ -1,4 +1,4 @@ -package server +package chess import ( "net/http" diff --git a/lobby_registry/lobby.go b/lobby_registry/lobby.go new file mode 100644 index 0000000..1037ccc --- /dev/null +++ b/lobby_registry/lobby.go @@ -0,0 +1,33 @@ +package lobby_registry + +import ( + "local/m/mchess_server/chess" + + "github.com/google/uuid" +) + +type Lobby struct { + uuid uuid.UUID + players []*chess.Player +} + +func NewEmptyLobbyByUUID(uuid uuid.UUID) *Lobby { + return &Lobby{uuid: uuid} +} + +func (w *Lobby) AddPlayer(player *chess.Player) { + w.players = append(w.players, player) + player.JoinedLobby <- true +} + +func (w *Lobby) IsFull() bool { + return len(w.players) == 2 +} + +func (l *Lobby) GetPlayer1() *chess.Player { + return l.players[0] +} + +func (l *Lobby) GetPlayer2() *chess.Player { + return l.players[1] +} diff --git a/lobby_registry/registry.go b/lobby_registry/registry.go new file mode 100644 index 0000000..9449d16 --- /dev/null +++ b/lobby_registry/registry.go @@ -0,0 +1,41 @@ +package lobby_registry + +import ( + "github.com/google/uuid" +) + +type LobbyRegistry struct { + lobbies map[uuid.UUID]*Lobby +} + +var instance *LobbyRegistry + +func GetLobbyRegistry() *LobbyRegistry { + if instance == nil { + instance = newLobbyRegistry() + } + + return instance +} + +func newLobbyRegistry() *LobbyRegistry { + return &LobbyRegistry{lobbies: make(map[uuid.UUID]*Lobby)} +} + +func (r *LobbyRegistry) GetLobbyForPlayer() *Lobby { + for _, lobby := range r.lobbies { + if !lobby.IsFull() { + return lobby + } + } + + newLobby := NewEmptyLobbyByUUID(uuid.New()) + r.addNewLobby(newLobby) + return newLobby +} + +func (r *LobbyRegistry) addNewLobby(lobby *Lobby) uuid.UUID { + uuid := uuid.New() + r.lobbies[uuid] = lobby + return uuid +} diff --git a/main.go b/main.go index 8aae7d0..d4d5a43 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,8 @@ package main import ( "context" - "local/m/mchess_server/server" + "local/m/mchess_server/chess" + "local/m/mchess_server/usher" "log" "net/http" "os" @@ -50,16 +51,21 @@ func registerForRandomGame(c *gin.Context) { 3. Only after a second player joins, respond with player id and game id. */ - player := server.NewPlayer(uuid.New()) + player := chess.NewPlayer(uuid.New()) - lobby := server.GetLobby() - lobby.Lock() - server.GetLobby().RegisterPlayer(player) - lobby.Unlock() + usher := usher.GetUsher() + lobby := usher.WelcomeNewPlayer(player) + usher.AddPlayerToLobby(player, lobby) + + // Counter point to this approach: + // Waiting for two players might not be necessary. + // Just open the lobby and respond with lobby/game id and player id + // The waiting can be done in the game handler until both players opened a ws connection + usher.WaitForTwoPlayersInLobby(lobby) log.Println("responding with player id ", player.Uuid) - c.IndentedJSON(http.StatusOK, server.PlayerInfo{ + c.IndentedJSON(http.StatusOK, chess.PlayerInfo{ PlayerID: player.Uuid, }) } @@ -86,7 +92,10 @@ func waitForAndHandlePlayerID(ctx context.Context, conn websocket.Conn) { return } - lobby := server.GetLobby() + // since we cannot use the lobby anymore (it does not exist anymore after this change) the client needs to + // send game id and player id so we can make the connection to the player + //lobby := chess.GetLobby() + player, found := lobby.GetPlayer(uuid) if !found { conn.Close(websocket.StatusCode(400), "player not found") diff --git a/usher/usher.go b/usher/usher.go new file mode 100644 index 0000000..e612392 --- /dev/null +++ b/usher/usher.go @@ -0,0 +1,39 @@ +package usher + +import ( + "local/m/mchess_server/chess" + lobbies "local/m/mchess_server/lobby_registry" +) + +type Usher struct { +} + +var instance *Usher + +func NewUsher() *Usher { + return &Usher{} +} + +func GetUsher() *Usher { + if instance == nil { + instance = NewUsher() + } + return instance +} + +func (u *Usher) WelcomeNewPlayer(player *chess.Player) *lobbies.Lobby { + lobby := lobbies.GetLobbyRegistry().GetLobbyForPlayer() + return lobby +} + +func (u *Usher) AddPlayerToLobby(player *chess.Player, lobby *lobbies.Lobby) { + lobby.AddPlayer(player) +} + +func (u *Usher) WaitForTwoPlayersInLobby(lobby *lobbies.Lobby) { + player1 := lobby.GetPlayer1() + <-player1.JoinedLobby + + player2 := lobby.GetPlayer2() + <-player2.JoinedLobby +}