2021-12-09 11:11:17 +01:00
|
|
|
import Foundation
|
2021-12-18 15:08:43 +01:00
|
|
|
import WebSocketKit
|
2021-12-09 11:11:17 +01:00
|
|
|
|
2021-12-22 14:53:53 +01:00
|
|
|
|
|
|
|
let numberOfCardsPerPlayer = 8
|
|
|
|
|
2021-12-18 15:08:43 +01:00
|
|
|
class AbstractTable<TablePlayer> where TablePlayer: Player {
|
2021-12-09 11:11:17 +01:00
|
|
|
|
|
|
|
/// The unique id of the table
|
2021-12-22 22:13:09 +01:00
|
|
|
let id: UUID
|
2021-12-09 11:11:17 +01:00
|
|
|
|
|
|
|
/// The name of the table
|
|
|
|
let name: TableName
|
|
|
|
|
|
|
|
/// Indicates that the table is visible to all players, and can be joined by anyone
|
|
|
|
let isPublic: Bool
|
|
|
|
|
2021-12-21 09:53:20 +01:00
|
|
|
let language: SupportedLanguage = .german
|
|
|
|
|
2021-12-18 15:08:43 +01:00
|
|
|
/**
|
|
|
|
The players sitting at the table.
|
|
|
|
|
|
|
|
The players are ordered clockwise around the table, with the first player starting the game.
|
|
|
|
*/
|
|
|
|
var players: [TablePlayer]
|
|
|
|
|
|
|
|
var playedGame: GameType? {
|
|
|
|
nil
|
|
|
|
}
|
|
|
|
|
2021-12-22 22:13:09 +01:00
|
|
|
var leavePenalty: Int {
|
|
|
|
5
|
|
|
|
}
|
|
|
|
|
2021-12-18 15:08:43 +01:00
|
|
|
init(table: ManageableTable, players: [TablePlayer]) {
|
2021-12-09 11:11:17 +01:00
|
|
|
self.id = table.id
|
|
|
|
self.name = table.name
|
|
|
|
self.isPublic = table.isPublic
|
2021-12-18 15:08:43 +01:00
|
|
|
self.players = players
|
2021-12-09 11:11:17 +01:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:13:09 +01:00
|
|
|
init(id: UUID, name: TableName, isPublic: Bool, players: [TablePlayer]) {
|
2021-12-09 11:11:17 +01:00
|
|
|
self.id = id
|
|
|
|
self.name = name
|
|
|
|
self.isPublic = isPublic
|
2021-12-18 15:08:43 +01:00
|
|
|
self.players = players
|
|
|
|
}
|
|
|
|
|
|
|
|
func perform(action: PlayerAction, forPlayer name: PlayerName) -> (result: PlayerActionResult, table: ManageableTable?) {
|
|
|
|
(.tableStateInvalid, nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func play(card: Card, player name: PlayerName) -> (result: PlayerActionResult, table: ManageableTable?) {
|
|
|
|
(.tableStateInvalid, nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func cardStackPosition(ofPlayerAt index: Int) -> Int {
|
|
|
|
index
|
|
|
|
}
|
|
|
|
|
2021-12-20 20:18:19 +01:00
|
|
|
func cards(forPlayerAt index: Int) -> [PlayableCard] {
|
|
|
|
[]
|
|
|
|
}
|
|
|
|
|
|
|
|
func games(forPlayerAt index: Int) -> [GameConvertible] {
|
|
|
|
[]
|
|
|
|
}
|
|
|
|
|
|
|
|
func gameIsSelected(byPlayerAt index: Int) -> Bool {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
|
|
|
func tableInfo(forPlayerAt index: Int) -> TableInfo {
|
2021-12-22 22:13:09 +01:00
|
|
|
var info = TableInfo(id: id.uuidString, name: name)
|
2021-12-20 20:18:19 +01:00
|
|
|
info.player = playerInfo(forIndex: index)!
|
|
|
|
info.playerLeft = playerInfo(forIndex: (index + 1) % 4)
|
|
|
|
info.playerAcross = playerInfo(forIndex: (index + 2) % 4)
|
|
|
|
info.playerRight = playerInfo(forIndex: (index + 3) % 4)
|
|
|
|
info.playableGames = games(forPlayerAt: index).map { $0.id }
|
|
|
|
info.actions = players[index].actions.map { $0.id }
|
|
|
|
info.cards = cards(forPlayerAt: index).map { $0.cardInfo }
|
|
|
|
info.playerSelectsGame = gameIsSelected(byPlayerAt: index)
|
|
|
|
info.game = playedGame?.id
|
|
|
|
return info
|
|
|
|
}
|
|
|
|
|
2021-12-09 11:11:17 +01:00
|
|
|
}
|
2021-12-18 15:08:43 +01:00
|
|
|
|
|
|
|
extension AbstractTable: ManageableTable {
|
|
|
|
|
|
|
|
var publicInfo: PublicTableInfo {
|
2021-12-22 22:13:09 +01:00
|
|
|
.init(id: id.uuidString, name: name, players: playerNames)
|
2021-12-18 15:08:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
var playerNames: [PlayerName] {
|
|
|
|
players.map { $0.name }
|
|
|
|
}
|
|
|
|
|
|
|
|
var allPlayers: [Player] {
|
|
|
|
players
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: Connection
|
|
|
|
|
|
|
|
func connect(player name: PlayerName, using socket: WebSocket) -> Bool {
|
|
|
|
guard let player = players.player(named: name) else {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
player.connect(using: socket)
|
|
|
|
sendUpdateToAllPlayers()
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func disconnect(player name: PlayerName) {
|
|
|
|
guard let player = players.player(named: name) else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
guard player.disconnect() else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
sendUpdateToAllPlayers()
|
|
|
|
return
|
|
|
|
}
|
2022-01-24 17:15:11 +01:00
|
|
|
|
|
|
|
func disconnectAllPlayers() {
|
|
|
|
players.forEach { $0.disconnect() }
|
|
|
|
}
|
2021-12-18 15:08:43 +01:00
|
|
|
|
|
|
|
func sendUpdateToAllPlayers() {
|
|
|
|
players.enumerated().forEach { playerIndex, player in
|
|
|
|
guard player.isConnected else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
let info = self.tableInfo(forPlayerAt: playerIndex)
|
|
|
|
player.send(info)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: Client info
|
|
|
|
|
|
|
|
func playerInfo(forIndex index: Int) -> PlayerInfo? {
|
|
|
|
guard let player = players.at(index) else {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
let height = cardStackPosition(ofPlayerAt: index)
|
2021-12-20 20:18:19 +01:00
|
|
|
var info = player.info
|
|
|
|
info.positionInTrick = height
|
|
|
|
return info
|
2021-12-18 15:08:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func tableInfo(forPlayer player: PlayerName) -> TableInfo {
|
|
|
|
let index = players.index(of: player)
|
|
|
|
return tableInfo(forPlayerAt: index)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|