mchess-server/chess/player.go

166 lines
3.6 KiB
Go
Raw Normal View History

package chess
2023-04-18 20:19:28 +00:00
import (
"context"
2023-06-08 18:20:37 +00:00
"encoding/json"
"errors"
"log"
2023-06-25 14:11:29 +00:00
"mchess_server/api"
"mchess_server/connection"
2023-06-25 14:11:29 +00:00
"mchess_server/types"
2023-04-18 20:19:28 +00:00
"github.com/google/uuid"
gorillaws "github.com/gorilla/websocket"
2023-04-18 20:19:28 +00:00
)
type Player struct {
Uuid uuid.UUID
Conn *connection.Connection
color types.ChessColor
disconnectCallback func(p *Player)
}
2023-04-18 20:19:28 +00:00
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
}
err = p.writeMessage(messageToSend)
if err != nil {
log.Println("Error during message writing:", err)
return err
}
return nil
}
2023-08-13 22:05:47 +00:00
func (p *Player) SendMoveAndPosition(move types.Move, boardPosition string) error {
2023-06-08 18:20:37 +00:00
messageToSend, err := json.Marshal(api.WebsocketMessage{
2023-10-12 19:03:12 +00:00
Type: api.MoveMessage,
Move: &move,
Position: &boardPosition,
2023-06-08 18:20:37 +00:00
})
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) 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
}
err = p.writeMessage(messageToSend)
if err != nil {
log.Println("Error during message writing:", err)
return err
}
return nil
}
2023-06-08 18:20:37 +00:00
func (p *Player) writeMessage(msg []byte) error {
return p.Conn.Write(msg)
}
2023-06-08 18:20:37 +00:00
func (p *Player) ReadMove() (types.Move, error) {
receivedMessage, err := p.readMessage()
2023-06-08 18:20:37 +00:00
if err != nil {
return types.Move{}, err
}
var msg api.WebsocketMessage
err = json.Unmarshal(receivedMessage, &msg)
if err != nil {
return types.Move{}, err
}
2023-10-12 19:03:12 +00:00
if !msg.IsValid() {
2023-06-08 18:20:37 +00:00
return types.Move{}, errors.New("not a valid move")
}
return *msg.Move, nil
}
func (p *Player) readMessage() ([]byte, error) {
msg, err := p.Conn.Read()
log.Printf("Reading message from %s: %s", p.color.String(), string(msg))
return msg, err
}