Compare commits
2 Commits
efefa4ced5
...
45fac78e06
Author | SHA1 | Date | |
---|---|---|---|
45fac78e06 | |||
cce0aa8162 |
14
api/move.go
14
api/move.go
@ -6,16 +6,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type WebsocketMessage struct {
|
type WebsocketMessage struct {
|
||||||
Type MessageType `json:"messageType"`
|
Type MessageType `json:"messageType"`
|
||||||
Move *types.Move `json:"move,omitempty"`
|
Move *types.Move `json:"move,omitempty"`
|
||||||
Color *types.ChessColor `json:"color,omitempty"`
|
TurnColor *types.ChessColor `json:"turnColor,omitempty"`
|
||||||
Reason *string `json:"reason,omitempty"`
|
PlayerColor *types.ChessColor `json:"playerColor,omitempty"`
|
||||||
Position *string `json:"position,omitempty"`
|
Reason *string `json:"reason,omitempty"`
|
||||||
|
Position *string `json:"position,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MessageType string
|
type MessageType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
PositionMessage MessageType = "position"
|
||||||
MoveMessage MessageType = "move"
|
MoveMessage MessageType = "move"
|
||||||
InvalidMoveMessage MessageType = "invalidMove"
|
InvalidMoveMessage MessageType = "invalidMove"
|
||||||
ColorDetermined MessageType = "colorDetermined"
|
ColorDetermined MessageType = "colorDetermined"
|
||||||
@ -36,7 +38,7 @@ func (m WebsocketMessage) IsValidMoveMessage() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetColorDeterminedMessage(color types.ChessColor) ([]byte, error) {
|
func GetColorDeterminedMessage(color types.ChessColor) ([]byte, error) {
|
||||||
return json.Marshal(WebsocketMessage{Type: ColorDetermined, Color: &color})
|
return json.Marshal(WebsocketMessage{Type: ColorDetermined, TurnColor: &color})
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetInvalidMoveMessage(move types.Move, reason string) ([]byte, error) {
|
func GetInvalidMoveMessage(move types.Move, reason string) ([]byte, error) {
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package chess
|
package chess
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"mchess_server/api"
|
"mchess_server/api"
|
||||||
"mchess_server/types"
|
"mchess_server/types"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
"nhooyr.io/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Game struct {
|
type Game struct {
|
||||||
@ -15,6 +18,7 @@ type Game struct {
|
|||||||
players []*Player
|
players []*Player
|
||||||
currentTurnPlayer *Player
|
currentTurnPlayer *Player
|
||||||
gameState int
|
gameState int
|
||||||
|
isBeingHandled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -57,16 +61,28 @@ func (game *Game) prepare() {
|
|||||||
game.players[0].color = types.White
|
game.players[0].color = types.White
|
||||||
game.players[1].color = types.Black
|
game.players[1].color = types.Black
|
||||||
|
|
||||||
|
game.players[0].SetDisconnectCallback(game.playerDisconnected)
|
||||||
|
game.players[1].SetDisconnectCallback(game.playerDisconnected)
|
||||||
|
|
||||||
err := game.notifyPlayersAboutGameStart()
|
err := game.notifyPlayersAboutGameStart()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (game *Game) StartHandling() {
|
||||||
|
if game.isBeingHandled {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
game.isBeingHandled = true
|
||||||
|
go game.Handle()
|
||||||
|
}
|
||||||
|
|
||||||
func (game *Game) Handle() {
|
func (game *Game) Handle() {
|
||||||
defer game.killGame()
|
defer game.killGame()
|
||||||
|
|
||||||
game.prepare()
|
game.prepare()
|
||||||
|
|
||||||
var receivedMove types.Move
|
var receivedMove types.Move
|
||||||
var err error
|
var err error
|
||||||
@ -161,3 +177,15 @@ func (game Game) broadcastMove(move types.Move) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (game *Game) playerDisconnected(p *Player) {
|
||||||
|
log.Println(string(p.color), " disconnected")
|
||||||
|
playerStillInGame := lo.Filter(game.players, func(player *Player, _ int) bool {
|
||||||
|
return player.color != p.color
|
||||||
|
})
|
||||||
|
game.players = playerStillInGame
|
||||||
|
}
|
||||||
|
|
||||||
|
func (game *Game) SetWebsocketConnectionFor(ctx context.Context, p *Player, ws *websocket.Conn) {
|
||||||
|
p.SetWebsocketConnectionAndSendBoardState(ctx, ws, game.board.PGN(), game.board.colorToMove)
|
||||||
|
}
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"mchess_server/api"
|
"mchess_server/api"
|
||||||
conn "mchess_server/connection"
|
"mchess_server/connection"
|
||||||
"mchess_server/types"
|
"mchess_server/types"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@ -14,18 +14,20 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Player struct {
|
type Player struct {
|
||||||
Uuid uuid.UUID
|
Uuid uuid.UUID
|
||||||
Conn *conn.Connection
|
Conn *connection.Connection
|
||||||
InGame bool
|
color types.ChessColor
|
||||||
color types.ChessColor
|
disconnectCallback func(p *Player)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPlayer(uuid uuid.UUID) *Player {
|
func NewPlayer(uuid uuid.UUID) *Player {
|
||||||
return &Player{
|
player := &Player{
|
||||||
Uuid: uuid,
|
Uuid: uuid,
|
||||||
Conn: conn.NewConnection(conn.WithContext(context.Background())),
|
Conn: connection.NewConnection(
|
||||||
InGame: false,
|
connection.WithContext(context.Background())),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return player
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Player) HasWebsocketConnection() bool {
|
func (p Player) HasWebsocketConnection() bool {
|
||||||
@ -36,6 +38,51 @@ func (p *Player) SetWebsocketConnection(ctx context.Context, ws *websocket.Conn)
|
|||||||
p.Conn.SetWebsocketConnection(ws)
|
p.Conn.SetWebsocketConnection(ws)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Player) SetWebsocketConnectionAndSendBoardState(
|
||||||
|
ctx context.Context,
|
||||||
|
ws *websocket.Conn,
|
||||||
|
boardPosition string,
|
||||||
|
turnColor types.ChessColor,
|
||||||
|
) {
|
||||||
|
p.SetWebsocketConnection(ctx, ws)
|
||||||
|
p.SendPosition(boardPosition, turnColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
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) SendPosition(boardPosition string, turnColor types.ChessColor) error {
|
||||||
|
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{
|
||||||
|
Type: api.PositionMessage,
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Player) SendMoveAndPosition(move types.Move, boardPosition string) error {
|
func (p *Player) SendMoveAndPosition(move types.Move, boardPosition string) error {
|
||||||
messageToSend, err := json.Marshal(api.WebsocketMessage{
|
messageToSend, err := json.Marshal(api.WebsocketMessage{
|
||||||
Type: api.MoveMessage,
|
Type: api.MoveMessage,
|
||||||
|
@ -12,6 +12,7 @@ type Connection struct {
|
|||||||
wsConnectionEstablished chan bool
|
wsConnectionEstablished chan bool
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
buffer MessageBuffer
|
buffer MessageBuffer
|
||||||
|
disconnectCallback func()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnection(options ...func(*Connection)) *Connection {
|
func NewConnection(options ...func(*Connection)) *Connection {
|
||||||
@ -39,6 +40,18 @@ func WithContext(ctx context.Context) func(*Connection) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithDisconnectCallback(cb func()) func(*Connection) {
|
||||||
|
return func(c *Connection) {
|
||||||
|
if cb != nil {
|
||||||
|
c.disconnectCallback = cb
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conn *Connection) SetDisconnectCallback(cb func()) {
|
||||||
|
conn.disconnectCallback = cb
|
||||||
|
}
|
||||||
|
|
||||||
func (conn *Connection) HasWebsocketConnection() bool {
|
func (conn *Connection) HasWebsocketConnection() bool {
|
||||||
return conn.ws != nil
|
return conn.ws != nil
|
||||||
}
|
}
|
||||||
@ -57,7 +70,14 @@ func (conn *Connection) SetWebsocketConnection(ws *websocket.Conn) {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
_, msg, _ := conn.ws.Read(conn.ctx)
|
_, msg, err := conn.ws.Read(conn.ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("while reading from websocket: %w", err)
|
||||||
|
if conn.disconnectCallback != nil {
|
||||||
|
conn.disconnectCallback()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
conn.buffer.Insert(string(msg))
|
conn.buffer.Insert(string(msg))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -32,7 +32,7 @@ func newEmptyLobbyWithPassphrase() *Lobby {
|
|||||||
func (l *Lobby) AddPlayerAndStartGameIfFull(player *chess.Player) {
|
func (l *Lobby) AddPlayerAndStartGameIfFull(player *chess.Player) {
|
||||||
l.Game.AddPlayersToGame(player)
|
l.Game.AddPlayersToGame(player)
|
||||||
if l.IsFull() {
|
if l.IsFull() {
|
||||||
go l.Game.Handle()
|
l.Game.StartHandling()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
main.go
3
main.go
@ -151,6 +151,7 @@ func waitForAndHandlePlayerID(ctx context.Context, conn *websocket.Conn) {
|
|||||||
lobby := lobbies.GetLobbyRegistry().GetLobbyByUUID(*info.LobbyID)
|
lobby := lobbies.GetLobbyRegistry().GetLobbyByUUID(*info.LobbyID)
|
||||||
if lobby == nil {
|
if lobby == nil {
|
||||||
conn.Close(websocket.StatusCode(400), "lobby not found")
|
conn.Close(websocket.StatusCode(400), "lobby not found")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
player, found := lobby.GetPlayerByUUID(*info.PlayerID)
|
player, found := lobby.GetPlayerByUUID(*info.PlayerID)
|
||||||
@ -161,6 +162,6 @@ func waitForAndHandlePlayerID(ctx context.Context, conn *websocket.Conn) {
|
|||||||
if player.Conn.HasWebsocketConnection() {
|
if player.Conn.HasWebsocketConnection() {
|
||||||
player.Conn.Close("closing existing connection")
|
player.Conn.Close("closing existing connection")
|
||||||
}
|
}
|
||||||
player.SetWebsocketConnection(ctx, conn)
|
lobby.Game.SetWebsocketConnectionFor(ctx, player, conn)
|
||||||
log.Println("player after setting connection: ", player)
|
log.Println("player after setting connection: ", player)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user