2023-05-31 21:55:40 +00:00
|
|
|
package chess
|
2022-12-14 21:19:47 +00:00
|
|
|
|
2023-04-18 20:19:28 +00:00
|
|
|
import (
|
2023-05-30 20:01:20 +00:00
|
|
|
"context"
|
2023-06-08 18:20:37 +00:00
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
2023-06-29 20:20:41 +00:00
|
|
|
"log"
|
2023-06-25 14:11:29 +00:00
|
|
|
"mchess_server/api"
|
2023-11-20 00:25:27 +00:00
|
|
|
"mchess_server/connection"
|
2023-06-25 14:11:29 +00:00
|
|
|
"mchess_server/types"
|
2023-05-30 20:01:20 +00:00
|
|
|
|
2023-04-18 20:19:28 +00:00
|
|
|
"github.com/google/uuid"
|
2023-04-22 19:41:24 +00:00
|
|
|
"nhooyr.io/websocket"
|
2023-04-18 20:19:28 +00:00
|
|
|
)
|
2022-12-14 21:19:47 +00:00
|
|
|
|
|
|
|
type Player struct {
|
2023-11-20 00:25:27 +00:00
|
|
|
Uuid uuid.UUID
|
|
|
|
Conn *connection.Connection
|
|
|
|
color types.ChessColor
|
|
|
|
disconnectCallback func(p *Player)
|
2023-04-22 19:41:24 +00:00
|
|
|
}
|
|
|
|
|
2023-04-18 20:19:28 +00:00
|
|
|
func NewPlayer(uuid uuid.UUID) *Player {
|
2023-11-20 00:25:27 +00:00
|
|
|
player := &Player{
|
|
|
|
Uuid: uuid,
|
|
|
|
Conn: connection.NewConnection(
|
|
|
|
connection.WithContext(context.Background())),
|
2022-12-14 21:19:47 +00:00
|
|
|
}
|
2023-11-20 00:25:27 +00:00
|
|
|
|
|
|
|
return player
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p Player) hasWebsocketConnection() bool {
|
|
|
|
return p.Conn.HasWebsocketConnection()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Player) SetWebsocketConnection(ctx context.Context, ws *websocket.Conn) {
|
|
|
|
p.Conn.SetWebsocketConnection(ws)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Player) SetWebsocketConnectionAndSendBoardState(
|
|
|
|
ctx context.Context,
|
|
|
|
ws *websocket.Conn,
|
|
|
|
boardPosition string,
|
|
|
|
turnColor types.ChessColor,
|
|
|
|
) {
|
|
|
|
p.SetWebsocketConnection(ctx, ws)
|
2023-12-25 16:52:32 +00:00
|
|
|
p.SendBoardState(types.Move{}, boardPosition, turnColor)
|
2023-11-20 00:25:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2022-12-14 21:19:47 +00:00
|
|
|
}
|
2023-05-30 20:01:20 +00:00
|
|
|
|
2023-11-20 00:25:27 +00:00
|
|
|
func (p *Player) IsInGame() bool {
|
|
|
|
return p.hasWebsocketConnection()
|
|
|
|
}
|
|
|
|
|
2023-12-25 16:52:32 +00:00
|
|
|
func (p *Player) SendBoardState(move types.Move, boardPosition string, turnColor types.ChessColor) error {
|
2023-11-20 00:25:27 +00:00
|
|
|
var pColor = p.color
|
|
|
|
if p.color == "" { // we default to white if we do not know the color yet
|
|
|
|
pColor = types.White
|
|
|
|
}
|
|
|
|
|
|
|
|
messageToSend, err := json.Marshal(api.WebsocketMessage{
|
2023-12-25 16:52:32 +00:00
|
|
|
Move: &move,
|
2023-11-20 00:25:27 +00:00
|
|
|
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-05-30 20:01:20 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2024-01-17 16:38:06 +00:00
|
|
|
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 {
|
2023-11-20 00:25:27 +00:00
|
|
|
return p.Conn.Write(msg)
|
2023-05-30 20:01:20 +00:00
|
|
|
}
|
|
|
|
|
2023-06-08 18:20:37 +00:00
|
|
|
func (p *Player) ReadMove() (types.Move, error) {
|
2023-11-20 00:25:27 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2023-11-20 00:25:27 +00:00
|
|
|
func (p *Player) readMessage() ([]byte, error) {
|
|
|
|
msg, err := p.Conn.Read()
|
2023-06-08 18:20:37 +00:00
|
|
|
log.Printf("Reading message: %s from player %s", string(msg), p.Uuid.String())
|
2023-05-30 20:01:20 +00:00
|
|
|
|
2023-11-20 00:25:27 +00:00
|
|
|
return msg, err
|
2023-05-30 20:01:20 +00:00
|
|
|
}
|
2023-06-06 20:58:33 +00:00
|
|
|
|
2023-11-20 00:25:27 +00:00
|
|
|
func (p Player) GetPlayerColor() string {
|
|
|
|
return string(p.color)
|
2023-06-06 20:58:33 +00:00
|
|
|
}
|