Various changes

1. Make lobby a struct containing the players and a mutex used to lock
   itself
2. Wait for websocket connections to be established by both players
   before starting the game.
3. Add methods to write to and read from players
This commit is contained in:
Marco 2023-05-30 22:01:20 +02:00
parent 5b6cb566ec
commit 6cbd7d37aa
5 changed files with 89 additions and 44 deletions

13
main.go
View File

@ -37,9 +37,12 @@ func main() {
}
func registerForRandomGame(c *gin.Context) {
player := server.NewPlayer(uuid.New())
lobby := server.GetLobby()
lobby.Lock()
server.GetLobby().RegisterPlayer(player)
lobby.Unlock()
log.Println("responding with player id ", player.Uuid)
@ -49,7 +52,6 @@ func registerForRandomGame(c *gin.Context) {
}
func registerWebSocketConnection(c *gin.Context) {
// w http.ResponseWriter, r *http.Request
webSocketConn, err := websocket.Accept(c.Writer, c.Request, nil)
if err != nil {
log.Println(err)
@ -59,8 +61,6 @@ func registerWebSocketConnection(c *gin.Context) {
}
func waitForAndHandlePlayerID(ctx context.Context, conn websocket.Conn) {
// var playerInfo server.PlayerInfo
msgType, id, err := conn.Read(ctx)
log.Println("read from websocket: ", msgType, id, err)
@ -74,7 +74,7 @@ func waitForAndHandlePlayerID(ctx context.Context, conn websocket.Conn) {
}
lobby := server.GetLobby()
player, found := lobby[uuid]
player, found := lobby.GetPlayer(uuid)
if !found {
conn.Close(websocket.StatusCode(400), "player not found")
return
@ -82,5 +82,6 @@ func waitForAndHandlePlayerID(ctx context.Context, conn websocket.Conn) {
if player.Conn != nil {
player.Conn.Close(websocket.StatusCode(400), "closing existing connection")
}
player.Conn = &conn
player.SetConnection(ctx, conn)
log.Println("player after setting connection: ", player)
}

View File

@ -25,13 +25,25 @@ func NewGame() *Game {
return &game
}
func (game Game) getPlayer1() *Player {
return &game.players[0]
}
func (game Game) getPlayer2() *Player {
return &game.players[1]
}
func (game *Game) handle() {
defer log.Println("Game ", game.id, ": handle() ended")
<-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.players[0]
game.currentTurnPlayer = *game.getPlayer1()
var move *Move
var messageType int
var receivedMessage []byte
for {
@ -39,7 +51,7 @@ func (game *Game) handle() {
switch gameState {
case PlayerToMove:
var err error
messageType, receivedMessage, err = ReadMessageFromPlayer(&game.currentTurnPlayer)
_, receivedMessage, err = game.currentTurnPlayer.ReadMessageFromPlayer()
if err != nil {
log.Println("Error while reading message:", err)
// At the moment, we return when there is an error while reading a message.
@ -63,12 +75,12 @@ func (game *Game) handle() {
game.currentTurnPlayer = game.players[0]
}
err := WriteMessageToPlayer(&game.players[0], receivedMessage, messageType)
err := game.getPlayer1().WriteMessageToPlayer(receivedMessage)
if err != nil {
log.Println("Error during message writing:", err)
continue
}
err = WriteMessageToPlayer(&game.players[1], receivedMessage, messageType)
err = game.getPlayer2().WriteMessageToPlayer(receivedMessage)
if err != nil {
log.Println("Error during message writing:", err)
continue
@ -87,15 +99,11 @@ 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 _, player := range players {
player.InGame = true
for i := range players {
players[i].InGame = true
}
game.players = players
go game.handle()
}
func removePlayersFromLobby(players [2]Player) {
panic("not yet implemented")
}

View File

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

@ -1,14 +1,19 @@
package server
import (
"context"
"log"
"github.com/google/uuid"
"nhooyr.io/websocket"
)
type Player struct {
Uuid uuid.UUID
Conn *websocket.Conn
InGame bool
Uuid uuid.UUID
Conn *websocket.Conn
InGame bool
wsConnEstablished chan bool
context context.Context
}
type PlayerInfo struct {
@ -17,6 +22,28 @@ type PlayerInfo struct {
func NewPlayer(uuid uuid.UUID) *Player {
return &Player{
Uuid: uuid,
Uuid: uuid,
Conn: nil,
InGame: false,
wsConnEstablished: make(chan bool),
}
}
func (p *Player) SetConnection(ctx context.Context, conn websocket.Conn) {
p.Conn = &conn
p.context = ctx
p.wsConnEstablished <- true
}
func (p *Player) WriteMessageToPlayer(msg []byte) error {
log.Printf("Writing message: %s to player %d", string(msg), p.Uuid)
return p.Conn.Write(p.context, websocket.MessageText, msg)
}
func (p *Player) ReadMessageFromPlayer() (websocket.MessageType, []byte, error) {
msgType, msg, err := p.Conn.Read(p.context)
log.Printf("Reading message: %s (with messagetype %d) from player %d", string(msg), msgType, p.Uuid)
return msgType, msg, err
}

View File

@ -9,11 +9,3 @@ var AppPath = "/home/m/projects/programming/flutter_projects/mchess/build/web"
func PlayHandler(w http.ResponseWriter, r *http.Request) {
}
func WriteMessageToPlayer(player *Player, msg []byte, msgType int) error {
panic("Not implemented")
}
func ReadMessageFromPlayer(player *Player) (messageType int, p []byte, err error) {
panic("Not implemented")
}