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

198 lines
6.4 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
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
2020-05-13 14:59:20 +02:00
*/
2020-05-13 14:59:20 +02:00
func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) {
if mpMatch != match { return }
2020-05-13 14:59:20 +02:00
let jsonDecoder = JSONDecoder()
2020-05-13 21:15:44 +02:00
if let playerMoves = try? jsonDecoder.decode([PlayerMove].self, from: data) {
DataService.sharedInstance.addRemotePlayerMoves(playerID: player.gamePlayerID, playerMoves: playerMoves)
}
2020-05-13 20:22:23 +02:00
if let message = try? jsonDecoder.decode(Host.self, from: data) {
if !self.isServer {
DataService.sharedInstance.gameHost = message
print("LocalID: \(GKLocalPlayer.local.gamePlayerID)")
print("ServerID: \(message.playerID)")
}
}
2020-05-13 14:59:20 +02:00
}
/*
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-13 14:59:20 +02:00
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-13 20:22:48 +02:00
DataService.sharedInstance.setGameHost(host: Host(playerID: player!.gamePlayerID))
2020-05-04 20:34:58 +02:00
} else {
self.isServer = false
}
2020-05-05 11:44:33 +02:00
self.delegate?.matchStarted()
2020-05-05 00:35:27 +02:00
self.menusc!.loadScene(scene: GameScene(size: self.menusc!.size))
2020-05-13 20:22:23 +02:00
MultiplayerNetwork.sharedInstance.sendHostIdentifier()
2020-05-04 20:34:58 +02:00
})
}
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
}
}