154 lines
3.3 KiB
Go
154 lines
3.3 KiB
Go
package chess
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"log"
|
|
"mchess_server/api"
|
|
"mchess_server/connection"
|
|
"mchess_server/types"
|
|
|
|
"github.com/google/uuid"
|
|
gorillaws "github.com/gorilla/websocket"
|
|
)
|
|
|
|
type Player struct {
|
|
Uuid uuid.UUID
|
|
Conn *connection.Connection
|
|
color types.ChessColor
|
|
disconnectCallback func(p *Player)
|
|
}
|
|
|
|
func NewPlayer(uuid uuid.UUID) *Player {
|
|
player := &Player{
|
|
Uuid: uuid,
|
|
Conn: connection.NewConnection(
|
|
connection.WithContext(context.Background())),
|
|
}
|
|
|
|
return player
|
|
}
|
|
|
|
func (p Player) hasWebsocketConnection() bool {
|
|
return p.Conn.HasWebsocketConnection()
|
|
}
|
|
|
|
func (p *Player) SetWebsocketConnection(ctx context.Context, ws *gorillaws.Conn) {
|
|
p.Conn.SetWebsocketConnection(ws)
|
|
p.Conn.SetForColor(p.color)
|
|
}
|
|
|
|
func (p *Player) SetWebsocketConnectionAndSendBoardState(
|
|
ctx context.Context,
|
|
ws *gorillaws.Conn,
|
|
board *Board,
|
|
) {
|
|
p.SetWebsocketConnection(ctx, ws)
|
|
p.SendBoardState(board.getLastMove(), board.PGN(), board.colorToMove)
|
|
}
|
|
|
|
func (p *Player) SetColor(color types.ChessColor) {
|
|
p.color = color
|
|
p.Conn.SetForColor(p.color)
|
|
}
|
|
|
|
func (p *Player) GetColor() types.ChessColor {
|
|
return p.color
|
|
}
|
|
|
|
func (p *Player) SetDisconnectCallback(cb func(*Player)) {
|
|
// Todo: Fucking complicated
|
|
p.Conn.SetDisconnectCallback(p.PlayerDisconnectedCallback)
|
|
p.disconnectCallback = cb
|
|
}
|
|
|
|
func (p *Player) PlayerDisconnectedCallback() {
|
|
p.disconnectCallback(p)
|
|
}
|
|
|
|
func (p *Player) IsInGame() bool {
|
|
return p.hasWebsocketConnection()
|
|
}
|
|
|
|
func (p *Player) SendBoardState(move types.Move, boardPosition string, turnColor types.ChessColor) error {
|
|
var pColor = p.GetColor()
|
|
if p.GetColor() == "" { // we default to white if we do not know the color yet
|
|
pColor = types.White
|
|
}
|
|
|
|
messageToSend, err := json.Marshal(api.WebsocketMessage{
|
|
Move: &move,
|
|
Type: api.BoardStateMessage,
|
|
TurnColor: &turnColor,
|
|
PlayerColor: &pColor,
|
|
Position: &boardPosition,
|
|
})
|
|
if err != nil {
|
|
log.Println("Error while marshalling: ", err)
|
|
return err
|
|
}
|
|
|
|
p.writeMessage(string(messageToSend))
|
|
|
|
return nil
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
p.writeMessage(string(messageToSend))
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *Player) SendGameEnded(reason GameEndedReason) error {
|
|
reasonToSend := reason.String()
|
|
messageToSend, err := json.Marshal(api.WebsocketMessage{
|
|
Type: api.GameEnded,
|
|
Reason: &reasonToSend,
|
|
})
|
|
if err != nil {
|
|
log.Println("Error while marshalling: ", err)
|
|
return err
|
|
}
|
|
p.writeMessage(string(messageToSend))
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *Player) writeMessage(msg string) {
|
|
p.Conn.Write(msg)
|
|
}
|
|
|
|
func (p *Player) ReadMove() (types.Move, error) {
|
|
receivedMessage := p.readMessage()
|
|
|
|
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 {
|
|
msg := p.Conn.Read()
|
|
log.Printf("Reading message from %s: %s", p.color.String(), string(msg))
|
|
|
|
return msg
|
|
}
|