Scrap 2-player waiting room and make it simple.
This commit is contained in:
parent
aac428baab
commit
78ddd4f90f
1
api_types/player_info.go
Normal file
1
api_types/player_info.go
Normal file
@ -0,0 +1 @@
|
||||
package api_types
|
@ -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)
|
||||
}
|
@ -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()
|
||||
}
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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]
|
||||
}
|
||||
|
@ -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
72
main.go
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user