Scrap 2-player waiting room and make it simple.

This commit is contained in:
Marco 2023-06-02 21:14:02 +02:00
parent aac428baab
commit 78ddd4f90f
8 changed files with 80 additions and 137 deletions

1
api_types/player_info.go Normal file
View File

@ -0,0 +1 @@
package api_types

View File

@ -8,8 +8,8 @@ import (
type Game struct {
id uuid.UUID
players [2]Player
currentTurnPlayer Player
players []*Player
currentTurnPlayer *Player
}
const (
@ -26,23 +26,24 @@ func NewGame() *Game {
}
func (game Game) getPlayer1() *Player {
return &game.players[0]
return game.players[0]
}
func (game Game) getPlayer2() *Player {
return &game.players[1]
return game.players[1]
}
func (game *Game) handle() {
func (game *Game) Handle() {
defer log.Println("Game ", game.id, ": handle() ended")
log.Println("Game ", game.id, " started")
<-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.getPlayer1()
game.currentTurnPlayer = game.getPlayer1()
var move *Move
var receivedMessage []byte
@ -96,14 +97,6 @@ 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 i := range players {
players[i].InGame = true
}
game.players = players
go game.handle()
func (game *Game) AddPlayersToGame(player *Player) {
game.players = append(game.players, player)
}

View File

@ -1,60 +0,0 @@
package chess
import (
"sync"
"github.com/google/uuid"
)
type Lobby struct {
players map[uuid.UUID]*Player
mutex sync.Mutex
}
var lobbyInstance *Lobby = nil
func GetLobby() *Lobby {
if lobbyInstance == nil {
lobbyInstance = newLobby()
}
return lobbyInstance
}
func newLobby() *Lobby {
return &Lobby{
players: make(map[uuid.UUID]*Player, 0),
}
}
func (l *Lobby) RegisterPlayer(player *Player) {
l.players[player.Uuid] = player
var playersToBeAddedToGame []Player
for _, player := range l.players {
if !player.InGame {
playersToBeAddedToGame = append(playersToBeAddedToGame, *player)
}
}
if len(playersToBeAddedToGame) < 2 {
return
}
game := NewGame()
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()
}

View File

@ -14,12 +14,11 @@ type Player struct {
InGame bool
wsConnEstablished chan bool
context context.Context
JoinedLobby chan bool
}
type PlayerInfo struct {
PlayerID uuid.UUID `json:"playerID"`
LobbyID uuid.UUID `json:"lobbyID"`
}
func NewPlayer(uuid uuid.UUID) *Player {
@ -28,7 +27,6 @@ func NewPlayer(uuid uuid.UUID) *Player {
Conn: nil,
InGame: false,
wsConnEstablished: make(chan bool),
JoinedLobby: make(chan bool),
}
}

View File

@ -7,23 +7,43 @@ import (
)
type Lobby struct {
uuid uuid.UUID
Uuid uuid.UUID
players []*chess.Player
Game chess.Game
PlayerJoined chan bool
}
func NewEmptyLobbyByUUID(uuid uuid.UUID) *Lobby {
return &Lobby{uuid: uuid}
func NewEmptyLobbyWithUUID(uuid uuid.UUID) *Lobby {
return &Lobby{
Uuid: uuid,
Game: *chess.NewGame(),
PlayerJoined: make(chan bool),
}
}
func (w *Lobby) AddPlayer(player *chess.Player) {
func (w *Lobby) AddPlayerAndStartGameIfFull(player *chess.Player) {
w.players = append(w.players, player)
player.JoinedLobby <- true
w.Game.AddPlayersToGame(player)
if w.IsFull() {
go w.Game.Handle()
}
}
func (w *Lobby) IsFull() bool {
return len(w.players) == 2
}
func (l *Lobby) GetPlayerByUUID(uuid uuid.UUID) (*chess.Player, bool) {
for _, player := range l.players {
if player.Uuid == uuid {
return player, true
}
}
return nil, false
}
func (l *Lobby) GetPlayer1() *chess.Player {
return l.players[0]
}

View File

@ -29,13 +29,16 @@ func (r *LobbyRegistry) GetLobbyForPlayer() *Lobby {
}
}
newLobby := NewEmptyLobbyByUUID(uuid.New())
newLobby := NewEmptyLobbyWithUUID(uuid.New())
r.addNewLobby(newLobby)
return newLobby
}
func (r *LobbyRegistry) addNewLobby(lobby *Lobby) uuid.UUID {
uuid := uuid.New()
r.lobbies[uuid] = lobby
return uuid
func (r *LobbyRegistry) GetLobbyByUUID(uuid uuid.UUID) *Lobby {
return r.lobbies[uuid]
}
func (r *LobbyRegistry) addNewLobby(lobby *Lobby) uuid.UUID {
r.lobbies[lobby.Uuid] = lobby
return lobby.Uuid
}

72
main.go
View File

@ -2,11 +2,15 @@ package main
import (
"context"
"encoding/json"
"fmt"
"local/m/mchess_server/chess"
lobbies "local/m/mchess_server/lobby_registry"
"local/m/mchess_server/usher"
"log"
"net/http"
"os"
"sync"
"github.com/gin-gonic/autotls"
"github.com/gin-gonic/gin"
@ -37,41 +41,29 @@ func main() {
}
}
var mut sync.Mutex
func registerForRandomGame(c *gin.Context) {
/*
What should be done:
1. Register player
2. Check if there is a game open that lacks one player
3. Fill open game, then respond with player id and game id.
OR
1. Register player
2. If there is no open game, open a game and wait for a second player to join
3. Only after a second player joins, respond with player id and game id.
*/
player := chess.NewPlayer(uuid.New())
usher := usher.GetUsher()
mut.Lock()
lobby := usher.WelcomeNewPlayer(player)
usher.AddPlayerToLobby(player, lobby)
usher.AddPlayerToLobbyAndStartGameIfFull(player, lobby)
mut.Unlock()
// 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, chess.PlayerInfo{
info := chess.PlayerInfo{
PlayerID: player.Uuid,
})
LobbyID: lobby.Uuid,
}
log.Println("responding with info ", info)
c.Header("Access-Control-Allow-Origin", "*")
c.IndentedJSON(http.StatusOK, info)
}
func registerWebSocketConnection(c *gin.Context) {
webSocketConn, err := websocket.Accept(c.Writer, c.Request, nil)
webSocketConn, err := websocket.Accept(c.Writer, c.Request, &websocket.AcceptOptions{OriginPatterns: []string{"localhost:*"}})
if err != nil {
log.Println(err)
return
@ -80,23 +72,27 @@ func registerWebSocketConnection(c *gin.Context) {
}
func waitForAndHandlePlayerID(ctx context.Context, conn websocket.Conn) {
msgType, id, err := conn.Read(ctx)
log.Println("read from websocket: ", msgType, id, err)
log.Println("id as string", string(id))
uuid, err := uuid.ParseBytes(id)
msgType, msg, err := conn.Read(ctx)
if err != nil {
log.Println(err)
conn.Close(websocket.StatusCode(400), err.Error())
errorMessage := fmt.Sprintf("Reading from websocket connection did not work: %s", err)
log.Println(errorMessage)
conn.Close(websocket.StatusCode(400), errorMessage)
return
}
// 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()
log.Println("read from websocket: ", msgType, string(msg), err)
player, found := lobby.GetPlayer(uuid)
var info chess.PlayerInfo
err = json.Unmarshal(msg, &info)
if err != nil {
errorMessage := fmt.Sprintf("Unmarshaling message did not work: %s", err)
log.Println(errorMessage)
conn.Close(websocket.StatusCode(400), errorMessage)
return
}
lobby := lobbies.GetLobbyRegistry().GetLobbyByUUID(info.LobbyID)
player, found := lobby.GetPlayerByUUID(info.PlayerID)
if !found {
conn.Close(websocket.StatusCode(400), "player not found")
return

View File

@ -26,14 +26,6 @@ func (u *Usher) WelcomeNewPlayer(player *chess.Player) *lobbies.Lobby {
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
func (u *Usher) AddPlayerToLobbyAndStartGameIfFull(player *chess.Player, lobby *lobbies.Lobby) {
lobby.AddPlayerAndStartGameIfFull(player)
}