2021-12-09 11:11:17 +01:00
|
|
|
import Foundation
|
|
|
|
import WebSocketKit
|
|
|
|
|
2021-12-22 22:13:09 +01:00
|
|
|
typealias PlayerName = String
|
|
|
|
|
2021-12-18 15:08:43 +01:00
|
|
|
class Player {
|
2021-12-09 11:11:17 +01:00
|
|
|
|
2021-12-18 15:08:43 +01:00
|
|
|
let name: PlayerName
|
2021-12-09 11:11:17 +01:00
|
|
|
|
2022-10-18 11:40:08 +02:00
|
|
|
var totalPoints: Int
|
2021-12-22 22:13:09 +01:00
|
|
|
|
2021-12-18 15:08:43 +01:00
|
|
|
var socket: WebSocket?
|
2021-12-09 11:11:17 +01:00
|
|
|
|
2021-12-18 15:08:43 +01:00
|
|
|
var isNextActor: Bool
|
2021-12-09 11:11:17 +01:00
|
|
|
|
2021-12-22 22:13:09 +01:00
|
|
|
init(name: PlayerName, points: Int, socket: WebSocket? = nil) {
|
2021-12-18 15:08:43 +01:00
|
|
|
self.name = name
|
|
|
|
self.socket = socket
|
|
|
|
self.isNextActor = false
|
2021-12-22 22:13:09 +01:00
|
|
|
self.totalPoints = points
|
2021-12-18 15:08:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
init(player: Player) {
|
|
|
|
self.name = player.name
|
|
|
|
self.socket = player.socket
|
|
|
|
self.isNextActor = false
|
2021-12-22 22:13:09 +01:00
|
|
|
self.totalPoints = player.totalPoints
|
2021-12-18 15:08:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
var actions: [PlayerAction] {
|
|
|
|
[]
|
|
|
|
}
|
|
|
|
|
2021-12-20 20:18:19 +01:00
|
|
|
var states: [PlayerState] {
|
|
|
|
isConnected ? [] : [.isDisconnected]
|
|
|
|
}
|
|
|
|
|
|
|
|
var info: PlayerInfo {
|
|
|
|
var result = PlayerInfo(name: name)
|
2021-12-22 22:13:09 +01:00
|
|
|
result.points = totalPoints
|
2021-12-20 20:18:19 +01:00
|
|
|
result.isConnected = isConnected
|
|
|
|
result.isNextActor = isNextActor
|
|
|
|
result.state = states.map { $0.rawValue }
|
|
|
|
return result
|
|
|
|
}
|
2021-12-18 15:08:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
extension Player: Equatable {
|
|
|
|
|
|
|
|
static func == (lhs: Player, rhs: Player) -> Bool {
|
|
|
|
lhs.name == rhs.name
|
|
|
|
}
|
2021-12-09 11:11:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
extension Player {
|
|
|
|
|
|
|
|
// MARK: Connection
|
|
|
|
|
|
|
|
/// Indicate that the player is connected when at a table
|
|
|
|
var isConnected: Bool {
|
|
|
|
guard let socket = socket else {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
guard !socket.isClosed else {
|
|
|
|
self.socket = nil
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func connect(using socket: WebSocket) {
|
|
|
|
_ = self.socket?.close()
|
|
|
|
self.socket = socket
|
|
|
|
}
|
|
|
|
|
2021-12-18 15:08:43 +01:00
|
|
|
@discardableResult
|
2021-12-09 11:11:17 +01:00
|
|
|
func disconnect() -> Bool {
|
|
|
|
guard let socket = socket else {
|
|
|
|
return false
|
|
|
|
}
|
2021-12-21 14:53:47 +01:00
|
|
|
socket.close().whenFailure { [weak self] error in
|
2023-02-06 22:03:02 +01:00
|
|
|
log("Failed to close socket for player: \(self?.name ?? "<Released>"): \(error)")
|
2021-12-09 11:11:17 +01:00
|
|
|
}
|
|
|
|
self.socket = nil
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-18 15:08:43 +01:00
|
|
|
@discardableResult
|
|
|
|
func send(_ info: TableInfo) -> Bool {
|
|
|
|
guard let socket = socket else {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
do {
|
|
|
|
try socket.send(encodeJSON(info))
|
|
|
|
} catch {
|
2023-02-06 22:03:02 +01:00
|
|
|
log("Failed to send info: \(error)")
|
2021-12-18 15:08:43 +01:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
2021-12-09 11:11:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: Actions
|
|
|
|
|
|
|
|
func canPerform(_ action: PlayerAction) -> Bool {
|
|
|
|
actions.contains(action)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2021-12-18 15:08:43 +01:00
|
|
|
|
|
|
|
extension Player: CustomStringConvertible {
|
|
|
|
|
|
|
|
var description: String {
|
|
|
|
name
|
|
|
|
}
|
|
|
|
}
|