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 +}