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
This commit is contained in:
parent
71ca61f047
commit
aac428baab
@ -1,4 +1,4 @@
|
||||
package server
|
||||
package chess
|
||||
|
||||
type Move struct {
|
||||
StartSquare Coordinate `json:"startSquare"`
|
@ -1,4 +1,4 @@
|
||||
package server
|
||||
package chess
|
||||
|
||||
import (
|
||||
"sync"
|
@ -1,4 +1,4 @@
|
||||
package server
|
||||
package chess
|
||||
|
||||
import (
|
||||
"log"
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package server
|
||||
package chess
|
||||
|
||||
import (
|
||||
"net/http"
|
33
lobby_registry/lobby.go
Normal file
33
lobby_registry/lobby.go
Normal file
@ -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]
|
||||
}
|
41
lobby_registry/registry.go
Normal file
41
lobby_registry/registry.go
Normal file
@ -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
|
||||
}
|
25
main.go
25
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")
|
||||
|
39
usher/usher.go
Normal file
39
usher/usher.go
Normal file
@ -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
|
||||
}
|
Loading…
Reference in New Issue
Block a user