Marco
26242424ed
This implements a ringbuffer that is used to decouple the raw websocket connection from the messages that the game handler handles.
102 lines
2.1 KiB
Go
102 lines
2.1 KiB
Go
package chess
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"log"
|
|
"mchess_server/api"
|
|
conn "mchess_server/connection"
|
|
"mchess_server/types"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"nhooyr.io/websocket"
|
|
)
|
|
|
|
type Player struct {
|
|
Uuid uuid.UUID
|
|
Conn *conn.Connection
|
|
InGame bool
|
|
wsConnEstablished chan bool
|
|
context context.Context
|
|
}
|
|
|
|
func NewPlayer(uuid uuid.UUID) *Player {
|
|
return &Player{
|
|
Uuid: uuid,
|
|
Conn: nil,
|
|
InGame: false,
|
|
wsConnEstablished: make(chan bool),
|
|
context: context.Background(),
|
|
}
|
|
}
|
|
|
|
func (p *Player) SetConnection(ctx context.Context, ws *websocket.Conn) {
|
|
p.Conn = conn.NewConnection(conn.WithWebsocket(ws), conn.WithContext(p.context))
|
|
p.context = ctx
|
|
p.wsConnEstablished <- true
|
|
}
|
|
|
|
func (p *Player) SendMoveAndPosition(move types.Move, boardPosition string) error {
|
|
messageToSend, err := json.Marshal(api.WebsocketMessage{
|
|
Type: api.MoveMessage,
|
|
Move: &move,
|
|
Position: &boardPosition,
|
|
})
|
|
if err != nil {
|
|
log.Println("Error while marshalling: ", err)
|
|
return err
|
|
}
|
|
|
|
err = p.writeMessage(messageToSend)
|
|
if err != nil {
|
|
log.Println("Error during message writing:", err)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *Player) writeMessage(msg []byte) error {
|
|
log.Printf("Writing message: %s to player %s", string(msg), p.Uuid.String())
|
|
|
|
return p.Conn.Write(p.context, msg)
|
|
}
|
|
|
|
func (p *Player) ReadMove() (types.Move, error) {
|
|
receivedMessage, err := p.readMessage()
|
|
if err != nil {
|
|
return types.Move{}, err
|
|
}
|
|
|
|
var msg api.WebsocketMessage
|
|
err = json.Unmarshal(receivedMessage, &msg)
|
|
if err != nil {
|
|
return types.Move{}, err
|
|
}
|
|
|
|
if !msg.IsValid() {
|
|
return types.Move{}, errors.New("not a valid move")
|
|
}
|
|
|
|
return *msg.Move, nil
|
|
}
|
|
|
|
func (p *Player) readMessage() ([]byte, error) {
|
|
msg, err := p.Conn.Read(p.context)
|
|
log.Printf("Reading message: %s from player %s", string(msg), p.Uuid.String())
|
|
|
|
return msg, err
|
|
}
|
|
|
|
func (p *Player) WaitForWebsocketConnection(c chan bool) {
|
|
timer := time.NewTimer(5 * time.Second)
|
|
|
|
select {
|
|
case <-p.wsConnEstablished:
|
|
c <- true
|
|
case <-timer.C:
|
|
return
|
|
}
|
|
}
|