122 lines
3.2 KiB
Swift
122 lines
3.2 KiB
Swift
import Foundation
|
|
import WebSocketKit
|
|
|
|
protocol Table: AbstractTable {
|
|
|
|
/// The unique id of the table
|
|
var id: TableId { get }
|
|
|
|
/// The name of the table
|
|
var name: TableName { get }
|
|
|
|
/// The table is visible in the list of tables and can be joined by anyone
|
|
var isPublic: Bool { get }
|
|
|
|
/**
|
|
The players sitting at the table.
|
|
|
|
The players are ordered clockwise around the table, with the first player starting the game.
|
|
*/
|
|
var allPlayers: [Player] { get }
|
|
|
|
var indexOfNextActor: Int { get }
|
|
|
|
func perform(action: PlayerAction, forPlayer: PlayerName) -> (result: PlayerActionResult, table: Table?)
|
|
|
|
func play(card: Card, player name: PlayerName) -> (result: PlayerActionResult, table: Table?)
|
|
}
|
|
|
|
extension Table {
|
|
|
|
var playerNames: [String] {
|
|
allPlayers.map { $0.name }
|
|
}
|
|
|
|
|
|
func index(of player: PlayerName) -> Int {
|
|
allPlayers.firstIndex { $0.name == player }!
|
|
}
|
|
|
|
func player(named name: PlayerName) -> Player? {
|
|
allPlayers.first { $0.name == name }
|
|
}
|
|
|
|
func contains(player: PlayerName) -> Bool {
|
|
allPlayers.contains { $0.name == player }
|
|
}
|
|
|
|
// MARK: Connection
|
|
|
|
func sendUpdateToAllPlayers() {
|
|
allPlayers.enumerated().forEach { playerIndex, player in
|
|
guard player.isConnected else {
|
|
return
|
|
}
|
|
let info = self.tableInfo(forPlayerAt: playerIndex)
|
|
player.send(info)
|
|
}
|
|
}
|
|
|
|
func connect(player name: PlayerName, using socket: WebSocket) -> Bool {
|
|
guard let player = player(named: name) else {
|
|
return false
|
|
}
|
|
player.connect(using: socket)
|
|
sendUpdateToAllPlayers()
|
|
return true
|
|
}
|
|
|
|
func disconnect(player name: PlayerName) {
|
|
guard let player = player(named: name) else {
|
|
return
|
|
}
|
|
guard player.disconnect() else {
|
|
return
|
|
}
|
|
sendUpdateToAllPlayers()
|
|
return
|
|
}
|
|
|
|
// MARK: Client info
|
|
|
|
var publicInfo: PublicTableInfo {
|
|
.init(id: id, name: name, players: playerNames)
|
|
}
|
|
|
|
private func player(forIndex index: Int) -> Player? {
|
|
let players = allPlayers
|
|
guard index < players.count else {
|
|
return nil
|
|
}
|
|
return players[index]
|
|
}
|
|
|
|
private func playerInfo(forIndex index: Int) -> PlayerInfo? {
|
|
guard let player = player(forIndex: index) else {
|
|
return nil
|
|
}
|
|
let isNext = indexOfNextActor == index
|
|
return PlayerInfo(player: player, isNextActor: isNext, position: index)
|
|
}
|
|
|
|
func tableInfo(forPlayer player: PlayerName) -> TableInfo {
|
|
let index = index(of: player)
|
|
return tableInfo(forPlayerAt: index)
|
|
}
|
|
|
|
func tableInfo(forPlayerAt index: Int) -> TableInfo {
|
|
let player = player(forIndex: index)!
|
|
let own = playerInfo(forIndex: index)!
|
|
let left = playerInfo(forIndex: (index + 1) % 4)
|
|
let across = playerInfo(forIndex: (index + 2) % 4)
|
|
let right = playerInfo(forIndex: (index + 3) % 4)
|
|
return .init(
|
|
id: id, name: name,
|
|
own: own, left: left,
|
|
across: across, right: right,
|
|
actions: player.actions,
|
|
cards: player.cards)
|
|
}
|
|
|
|
}
|