software-projekt-2-gold-wars/GoldWars/GoldWars/MatchmakingHelper.swift

217 lines
7.3 KiB
Swift
Raw Normal View History

2020-05-04 15:13:04 +02:00
//
// MatchmakingHelper.swift
// GoldWars
//
2020-05-04 21:44:50 +02:00
// Created by Chauntalle Schüle, Ömer Özel, Eray Kör on 03.05.20.
2020-05-04 15:13:04 +02:00
// Copyright © 2020 SP2. All rights reserved.
//
import GameKit
protocol GameKitHelperDelegate {
func matchStarted()
func matchEnded()
func matchReceivedData(match: GKMatch, data: NSData,
fromPlayer player: String)
2020-05-04 15:13:04 +02:00
}
/*
Diese Klasse wird für das Matchmaking über das Gamecenter gebraucht
@param: delegate: erhält alle Multiplayerevents
@param: mpMatch: repräsentiert das Netzwerk, alle Mitspieler besitzen ein gemeinsames Spiel
@param: viewController: ist nicht der ViewController des Gamecenters, sondern des Spiels
@param: mpMatchStarted: gibt an, ob ein Match schon gestartet wurde
@param: isServer: gibt an, ob der local player, als der Server fungiert
@param: spieler1: ist immer der Spieler, der der Server ist
@param: spieler2: ist immer der Spieler, der der Client ist
@param: sharedInstance: ist eine geteilte Instanz für alle Spieler
*/
2020-05-04 15:13:04 +02:00
class MatchmakingHelper: NSObject, GKMatchmakerViewControllerDelegate, GKMatchDelegate {
var delegate: GameKitHelperDelegate?
var mpMatch: GKMatch?
2020-05-04 15:13:04 +02:00
var viewController: UIViewController?
var mpMatchStarted: Bool
2020-05-04 20:34:58 +02:00
var isServer: Bool
var spieler1: GKPlayer?
var nameSpieler1 = ""
2020-05-04 23:44:23 +02:00
var menusc: MenuScene?
2020-05-04 15:13:04 +02:00
let localPlayer: GKLocalPlayer = GKLocalPlayer.local
var entityManager = EntityManager.gameEMInstance
2020-05-04 15:13:04 +02:00
static let sharedInstance = MatchmakingHelper()
static var isAuthenticated: Bool{
return GKLocalPlayer.local.isAuthenticated
}
override init() {
mpMatchStarted = false
2020-05-04 20:34:58 +02:00
isServer = false
2020-05-04 15:13:04 +02:00
super.init()
}
/*
Diese Methode wechselt von der MenuScene zum GameCenter ViewController. Die Spieler werden hier gesucht und gematcht. Mit minplayers/maxplayers kann bestimmt werden, wie viele Spieler insgesamt zusammen miteinander spielen.
*/
2020-05-05 00:35:27 +02:00
func presentMatchmaker(scene: MenuScene) {
menusc = scene
2020-05-04 20:34:58 +02:00
guard GKLocalPlayer.local.isAuthenticated else {
return
}
let request = GKMatchRequest()
request.minPlayers = 2
request.maxPlayers = 2
request.inviteMessage = "Willst du GoldWars spielen?"
let matchmakerVC = GKMatchmakerViewController.init(matchRequest: request)
matchmakerVC!.matchmakerDelegate = self
viewController?.present(matchmakerVC!, animated: true, completion: nil)
2020-05-04 15:13:04 +02:00
}
/*
Der User hat die Verbindung mit "Abbrechen" unterbrochen. GameCenter MatchMaking wird beendet.
*/
2020-05-04 15:13:04 +02:00
func matchmakerViewControllerWasCancelled(_ viewController: GKMatchmakerViewController) {
viewController.dismiss(animated: true, completion: nil)
2020-05-05 11:44:33 +02:00
delegate?.matchEnded()
2020-05-04 15:13:04 +02:00
}
/*
Wenn GameCenter kein match erstellen kann, wird der viewcontroller dismissed.
*/
2020-05-04 15:13:04 +02:00
func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFailWithError error: Error) {
viewController.dismiss(animated: true, completion: nil)
print("Error finding match", error.localizedDescription)
2020-05-05 11:44:33 +02:00
delegate?.matchEnded()
2020-05-04 15:13:04 +02:00
}
/*
Gamecenter hat erfolgreich ein Match gefunden, das Spiel kann gestartet werden.
expectedPlayerCount: Die verbleibende Anzahl von Spielern, die sich noch nicht mit dem Spiel verbunden haben
z.B 0 gibt an, dass keine weiteren Spieler benötigt werden um das Match zu starten
*/
2020-05-04 15:13:04 +02:00
func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFind match: GKMatch) {
viewController.dismiss(animated: true, completion: nil)
mpMatch = match
match.delegate = self
if !mpMatchStarted && match.expectedPlayerCount == 0 {
2020-05-04 20:34:58 +02:00
startMatch()
2020-05-04 15:13:04 +02:00
}
}
/*
Vom match erhaltene Spielerdaten
*/
func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) {
if mpMatch != match { return }
let jsonDecoder = JSONDecoder()
2020-05-13 21:15:44 +02:00
if let playerMoves = try? jsonDecoder.decode([PlayerMove].self, from: data) {
2020-05-18 00:27:53 +02:00
DataService.sharedInstance.addRemotePlayerMoves(playerName: player.displayName, playerMoves: playerMoves)
}
2020-05-13 20:22:23 +02:00
if let message = try? jsonDecoder.decode(Host.self, from: data) {
DataService.sharedInstance.gameHost = message
2020-05-13 20:22:23 +02:00
}
if let snapshotModel = try? jsonDecoder.decode(SnapshotModel.self, from: data) {
DataService.sharedInstance.snapshotModel = snapshotModel
entityManager.updateSnapshotModel(snapshotModel: snapshotModel)
entityManager.getTimer().startWithDuration(duration: 31)
}
if let mapModel = try? jsonDecoder.decode(MapGenerationModel.self, from: data) {
DataService.sharedInstance.setMapModel(model: mapModel)
}
MultiplayerNetwork.sharedInstance.isSending = false
}
/*
2020-05-05 11:44:33 +02:00
Verbindung/Matchmaking ist fehlgeschlagen
*/
2020-05-04 15:13:04 +02:00
private func match(match: GKMatch!, didFailWithError error: NSError!) {
if mpMatch != match {
return
}
mpMatchStarted = false
2020-05-05 11:44:33 +02:00
delegate?.matchEnded()
2020-05-04 15:13:04 +02:00
}
/*
Wird beim ändern des States/Zustands des Spielers aufgerufen udn gibt dessen Zustand zurück.
*/
2020-05-04 20:34:58 +02:00
func match(_ match: GKMatch, player: GKPlayer, didChange state: GKPlayerConnectionState) {
if mpMatch != match {
return
}
2020-05-04 20:34:58 +02:00
switch (state) {
case GKPlayerConnectionState.connected:
if (!mpMatchStarted && match.expectedPlayerCount == 0) {
startMatch()
}
2020-05-04 20:34:58 +02:00
case GKPlayerConnectionState.disconnected:
mpMatchStarted = false
2020-05-05 11:44:33 +02:00
delegate?.matchEnded()
2020-05-04 20:34:58 +02:00
default:
2020-05-05 11:44:33 +02:00
delegate?.matchEnded()
2020-05-04 20:34:58 +02:00
}
}
/*
Ein Spieler wird als Host für das Match gewählt. Dieser ist Spieler 1. Im Anschluss wird die GameScene geladen.
*/
2020-05-04 20:34:58 +02:00
func startMatch() {
2020-05-04 20:34:58 +02:00
mpMatch!.chooseBestHostingPlayer(completionHandler: {
(player) in
2020-05-04 20:34:58 +02:00
self.mpMatchStarted = true
2020-05-04 20:34:58 +02:00
if player == GKLocalPlayer.local {
self.isServer = true
self.spieler1 = player
self.nameSpieler1 = self.spieler1!.displayName
2020-05-18 00:27:53 +02:00
DataService.sharedInstance.setGameHost(host: Host(playerName: player!.displayName))
2020-05-04 20:34:58 +02:00
} else {
self.isServer = false
}
2020-05-05 11:44:33 +02:00
self.delegate?.matchStarted()
let scene = GameScene(size: self.menusc!.size)
self.entityManager.setScene(scene: scene)
self.menusc!.loadScene(scene: scene)
2020-05-15 19:40:13 +02:00
MultiplayerNetwork.sharedInstance.sendHostIdentifier()
2020-05-04 20:34:58 +02:00
})
}
2020-05-18 00:27:53 +02:00
func getGKPlayerByUsername(displayName: String) -> GKPlayer? {
let nilGK : GKPlayer? = nil
if GKLocalPlayer.local.displayName == displayName {
return GKLocalPlayer.local
}
for player in mpMatch!.players {
if player.displayName == displayName {
return player
}
}
return nilGK
}
2020-05-04 20:34:58 +02:00
/*
Trennt die Verbindung vom Match
*/
2020-05-04 20:34:58 +02:00
func disconnect() {
if mpMatch != nil {
mpMatch?.disconnect()
}
2020-05-04 15:13:04 +02:00
}
}