🎉 🚧 Start working on backend

This commit is contained in:
2025-03-06 10:14:21 +01:00
parent 3217b2c4c3
commit c4b9f9287f
17 changed files with 1591 additions and 0 deletions

142
backend/types/types.go Normal file
View File

@ -0,0 +1,142 @@
package types
import (
"sync"
"github.com/zishang520/socket.io/v2/socket"
"go.mongodb.org/mongo-driver/v2/bson"
)
type WebsocketConnection struct {
IsConnected bool
Socket *socket.Socket
}
type Card interface {
}
type CardDeck interface {
Init(*Room)
SetRoom(*Room)
IsEmpty() bool
DrawCard() Card
CanPlay(Card) bool
PlayCard(Card) bool
GetTopCard() Card
UpdatePlayedCard(interface{}) Card
IsPlayerActive(*Player) bool
}
type Player struct {
PlayerId bson.ObjectID
SessionToken string
Username string
Permissions int
Cards []Card `json:"-"`
Connection WebsocketConnection `bson:"-" json:"-"`
InactivityTimeout int `bson:"-" json:"-"`
}
func (player *Player) ResetInactivity() {
player.InactivityTimeout = 20 * 1000
}
func (player *Player) SetPermissionBit(bit RoomPermission) {
player.Permissions |= (1 << bit)
}
func (player *Player) ClearPermissionBit(bit RoomPermission) {
player.Permissions &= ^(1 << bit)
}
func (player *Player) HasPermissionBit(bit RoomPermission) bool {
return player.Permissions&(1<<bit) > 0
}
type GameState int
const (
StateLobby GameState = iota
StateRunning
StateEnded
)
type RoomPermission int
const (
PermissionHost RoomPermission = 0
)
type GameOptions struct {
}
type Room struct {
RoomId bson.ObjectID `bson:"_id"`
JoinCode string
GameState GameState
GameOptions GameOptions
CardDeckId int
CardDeck CardDeck
Players []*Player
PlayersMutex *sync.Mutex `bson:"-"`
OwnerId bson.ObjectID
MoveTimeout int
Winner *bson.ObjectID
}
func (room *Room) AppendPlayer(player *Player) {
room.PlayersMutex.Lock()
defer room.PlayersMutex.Unlock()
room.Players = append(room.Players, player)
}
func (room *Room) RemovePlayer(target Player) bool {
room.PlayersMutex.Lock()
defer room.PlayersMutex.Unlock()
return room.RemovePlayerUnsafe(target)
}
func (room *Room) FindPlayer(playerId bson.ObjectID) *Player {
room.PlayersMutex.Lock()
defer room.PlayersMutex.Unlock()
for _, player := range room.Players {
if player.PlayerId == playerId {
return player
}
}
return nil
}
func (room *Room) RemovePlayerUnsafe(target Player) bool {
foundHost := false
foundPlayer := false
for i := 0; i < len(room.Players); i++ {
player := room.Players[i]
if player.PlayerId == target.PlayerId {
room.Players = append(room.Players[:i], room.Players[i+1:]...)
foundPlayer = true
i--
continue
}
if player.HasPermissionBit(PermissionHost) {
foundHost = true
}
}
if !foundPlayer {
return false
}
if !foundHost && len(room.Players) > 0 {
room.Players[0].SetPermissionBit(PermissionHost)
}
return true
}
func (room *Room) IsUsernameAvailable(username string) bool {
for _, player := range room.Players {
if player.Username == username {
return false
}
}
return true
}

View File

@ -0,0 +1,113 @@
package types
import (
"go.mongodb.org/mongo-driver/v2/bson"
)
type S2C_Status struct {
IsError bool
StatusCode string
Message string
}
type S2C_PlayerInfo struct {
PlayerId bson.ObjectID
Username string
Permissions int
IsConnected bool
}
type S2C_RoomInfo struct {
RoomId bson.ObjectID `bson:"_id"`
JoinCode string
GameState GameState
GameOptions GameOptions
TopCard Card
CardDeckId int
Winner *bson.ObjectID
Players []S2C_PlayerInfo
}
type S2C_Card struct {
CanPlay bool
Card Card
}
type S2C_OwnCards struct {
Cards []S2C_Card
}
type S2C_PlayerState struct {
PlayerId bson.ObjectID
NumCards int
Active bool
}
type S2C_CardPlayed struct {
Card Card
CardIndex int
PlayedBy bson.ObjectID
}
type S2C_PlayedCardUpdate struct {
UpdatedBy bson.ObjectID
Card Card
}
type C2S_UpdatePlayer struct {
PlayerId bson.ObjectID
Username *string
Permissions *int
}
type C2S_KickPlayer struct {
PlayerId bson.ObjectID
}
type C2S_PlayCard struct {
CardIndex *int
CardData interface{}
}
type C2S_UpdatePlayedCard struct {
CardData interface{}
}
func BuildRoomInfoPacket(room *Room) S2C_RoomInfo {
players := make([]S2C_PlayerInfo, len(room.Players))
for i, player := range room.Players {
players[i] = S2C_PlayerInfo{
PlayerId: player.PlayerId,
Username: player.Username,
Permissions: player.Permissions,
IsConnected: player.Connection.IsConnected,
}
}
roomInfo := S2C_RoomInfo{
RoomId: room.RoomId,
JoinCode: room.JoinCode,
GameState: room.GameState,
CardDeckId: room.CardDeckId,
GameOptions: room.GameOptions,
Winner: room.Winner,
Players: players,
}
if room.CardDeck != nil {
roomInfo.TopCard = room.CardDeck.GetTopCard()
}
return roomInfo
}
func BuildOwnCardsPacket(room *Room, player *Player) S2C_OwnCards {
cards := make([]S2C_Card, len(player.Cards))
for i, card := range player.Cards {
cards[i] = S2C_Card{
Card: card,
CanPlay: room.CardDeck.CanPlay(card),
}
}
return S2C_OwnCards{
Cards: cards,
}
}
func BuildPlayerStatePacket(room *Room, player *Player) S2C_PlayerState {
return S2C_PlayerState{PlayerId: player.PlayerId, NumCards: len(player.Cards), Active: room.CardDeck.IsPlayerActive(player)}
}
func BuildCardPlayedPacket(player *Player, cardIndex int, card Card) S2C_CardPlayed {
return S2C_CardPlayed{Card: card, CardIndex: cardIndex, PlayedBy: player.PlayerId}
}
func BuildPlayedCardUpdatePacket(player *Player, card Card) S2C_PlayedCardUpdate {
return S2C_PlayedCardUpdate{UpdatedBy: player.PlayerId, Card: card}
}