2020-05-27 22:41:05 +02:00
|
|
|
//
|
|
|
|
// GameCenter.swift
|
|
|
|
// GoldWars
|
|
|
|
//
|
|
|
|
// Created by Niko Jochim on 23.05.20.
|
|
|
|
// Copyright © 2020 SP2. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import Foundation
|
|
|
|
import GameKit
|
|
|
|
import os
|
|
|
|
|
|
|
|
struct RandomNumber: Codable {
|
|
|
|
let number: Int
|
|
|
|
init() {
|
|
|
|
number = Int.random(in: 0...999999)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct State: Codable {
|
|
|
|
// 0 PlayerInit fertig
|
|
|
|
// 1 RemotePlayerInit fertig
|
|
|
|
// 2 Peer hat Map erhalten
|
|
|
|
// 3 Host hat Spiel gestartet
|
2020-06-02 21:51:37 +02:00
|
|
|
// 4 Peer hat verloren
|
|
|
|
// 5 Peer hat gewonnen
|
2020-05-27 22:41:05 +02:00
|
|
|
let state: Int
|
|
|
|
}
|
|
|
|
|
2020-06-02 15:29:53 +02:00
|
|
|
final class GameCenterManager: NSObject, GKMatchmakerViewControllerDelegate, GKGameCenterControllerDelegate ,GKMatchDelegate,GKLocalPlayerListener{
|
2020-05-27 22:41:05 +02:00
|
|
|
|
2020-06-11 21:21:11 +02:00
|
|
|
static var sharedInstance = GameCenterManager()
|
2020-05-27 22:41:05 +02:00
|
|
|
|
|
|
|
let LOG = OSLog.init(subsystem: "GameCenterManager", category: "GameCenterManager")
|
|
|
|
|
|
|
|
var viewController: UIViewController?
|
|
|
|
let localPlayer: GKLocalPlayer = GKLocalPlayer.local
|
|
|
|
var myMatch: GKMatch?
|
|
|
|
var isMatchStarted = false
|
|
|
|
var isServer = false
|
|
|
|
var hostingPlayer: GKPlayer?
|
|
|
|
var peerPlayer: GKPlayer?
|
|
|
|
var menusc: MenuScene?
|
|
|
|
var entityManager = EntityManager.gameEMInstance
|
|
|
|
var localPlayerRandomNumber: RandomNumber?
|
|
|
|
var initIsFinish = false
|
2020-06-07 12:00:12 +02:00
|
|
|
var gameEnded = false
|
2020-06-18 19:39:59 +02:00
|
|
|
var winner: String?
|
2020-05-27 22:41:05 +02:00
|
|
|
var gameScene: GameScene?
|
|
|
|
static var isAuthenticated: Bool {
|
|
|
|
return GKLocalPlayer.local.isAuthenticated
|
|
|
|
}
|
|
|
|
|
|
|
|
override init() {
|
|
|
|
super.init()
|
|
|
|
localPlayer.register(self)
|
|
|
|
authUser();
|
|
|
|
localPlayerRandomNumber = RandomNumber()
|
|
|
|
}
|
|
|
|
|
2020-06-18 19:39:59 +02:00
|
|
|
func reset() {
|
2020-06-11 21:21:11 +02:00
|
|
|
isMatchStarted = false
|
|
|
|
isServer = false
|
|
|
|
localPlayerRandomNumber = RandomNumber()
|
|
|
|
initIsFinish = false
|
|
|
|
gameEnded = false
|
|
|
|
winner = nil
|
|
|
|
gameScene = nil
|
|
|
|
}
|
|
|
|
|
2020-05-27 22:41:05 +02:00
|
|
|
func authUser() -> Void {
|
|
|
|
GKLocalPlayer.local.authenticateHandler = { gcAuthVC, error in
|
|
|
|
NotificationCenter.default
|
|
|
|
.post(name: .authenticationChanged, object: GKLocalPlayer.local.isAuthenticated)
|
|
|
|
if let vc = gcAuthVC {
|
|
|
|
self.viewController?.present(vc, animated: true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func presentMatchmaker() {
|
|
|
|
let request = GKMatchRequest()
|
|
|
|
request.minPlayers = 2
|
|
|
|
request.maxPlayers = 2
|
|
|
|
request.defaultNumberOfPlayers = 2
|
|
|
|
request.inviteMessage = "Willst du GoldWars spielen?"
|
|
|
|
let matchmakerVC = GKMatchmakerViewController.init(matchRequest: request)
|
|
|
|
matchmakerVC!.matchmakerDelegate = self
|
|
|
|
viewController?.present(matchmakerVC!, animated: true, completion: nil)
|
|
|
|
}
|
|
|
|
|
2020-06-02 15:29:53 +02:00
|
|
|
func presentGameCenter() {
|
|
|
|
let gameCenterController: GKGameCenterViewController = GKGameCenterViewController.init()
|
|
|
|
gameCenterController.gameCenterDelegate = self
|
|
|
|
gameCenterController.viewState = .achievements
|
|
|
|
viewController?.present(gameCenterController, animated: true, completion: nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func addAchievementProgress(identifier: String, increasePercentComplete: Double) {
|
|
|
|
GKAchievement.loadAchievements { (achievements: [GKAchievement]?, err: Error?) in
|
|
|
|
var achievementExists: Bool = false
|
|
|
|
achievements?.forEach({ (achievement: GKAchievement) in
|
|
|
|
print(achievement.identifier)
|
|
|
|
if achievement.identifier == identifier {
|
|
|
|
achievementExists = true
|
|
|
|
achievement.percentComplete += increasePercentComplete
|
|
|
|
achievement.showsCompletionBanner = true
|
|
|
|
GKAchievement.report([achievement]) { (error) in
|
2020-06-02 21:51:37 +02:00
|
|
|
print(error?.localizedDescription ?? "")
|
2020-06-02 15:29:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
if !achievementExists {
|
|
|
|
let newAchievement: GKAchievement = GKAchievement.init(identifier: identifier)
|
|
|
|
newAchievement.showsCompletionBanner = true
|
|
|
|
newAchievement.percentComplete = increasePercentComplete
|
|
|
|
GKAchievement.report([newAchievement]) { (error) in
|
2020-06-02 21:51:37 +02:00
|
|
|
print(error?.localizedDescription ?? "")
|
2020-06-02 15:29:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-10 18:32:31 +02:00
|
|
|
|
2020-05-27 22:41:05 +02:00
|
|
|
func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) {
|
|
|
|
if myMatch != match { return }
|
|
|
|
let jsonDecoder = JSONDecoder()
|
|
|
|
if let randomNumberFromPeer = try? jsonDecoder.decode(RandomNumber.self, from: data) {
|
|
|
|
os_log("Random Number des anderen Spielers erhalten", log: LOG, type: .info)
|
|
|
|
if randomNumberFromPeer.number <= localPlayerRandomNumber!.number {
|
|
|
|
isServer = true
|
|
|
|
self.hostingPlayer = GKLocalPlayer.local
|
|
|
|
self.peerPlayer = player
|
|
|
|
os_log("Dieser Spieler wurde zum HostingPlayer gewählt", log: LOG, type: .info)
|
|
|
|
} else {
|
|
|
|
isServer = false
|
|
|
|
self.hostingPlayer = player
|
|
|
|
self.peerPlayer = GKLocalPlayer.local
|
|
|
|
os_log("Dieser Spieler wurde zum PeerPlayer gewählt", log: LOG, type: .info)
|
|
|
|
}
|
|
|
|
os_log("Setzen von Peer und Host abgeschlossen", log: LOG, type: .info)
|
|
|
|
sendStateToPeers(state: State(state: 0))
|
|
|
|
os_log("State 0 wurde an anderen Spieler gesendet", log: LOG, type: .info)
|
|
|
|
}
|
|
|
|
if let state = try? jsonDecoder.decode(State.self, from: data) {
|
|
|
|
switch state.state {
|
2020-06-02 22:18:59 +02:00
|
|
|
case 0:
|
|
|
|
os_log("State 0 erhalten", log: LOG, type: .info)
|
|
|
|
sendStateToPeers(state: State(state: 1))
|
|
|
|
case 1:
|
|
|
|
os_log("State 1 erhalten", log: LOG, type: .info)
|
|
|
|
|
|
|
|
if isServer {
|
|
|
|
os_log("Peer hat Player initialisiert", log: LOG, type: .info)
|
|
|
|
initAndSendMap()
|
|
|
|
}else {
|
|
|
|
os_log("Host hat Player initialisiert", log: LOG, type: .info)
|
|
|
|
}
|
|
|
|
case 2:
|
|
|
|
os_log("State 2 erhalten", log: LOG, type: .info)
|
|
|
|
sendStateToPeers(state: State(state: 3))
|
|
|
|
initIsFinish = true
|
|
|
|
os_log("Spiel startet", log: LOG, type: .info)
|
|
|
|
case 3:
|
|
|
|
os_log("State 3 erhalten", log: LOG, type: .info)
|
|
|
|
initIsFinish = true
|
|
|
|
os_log("Spiel startet", log: LOG, type: .info)
|
|
|
|
case 4:
|
|
|
|
os_log("State 4 erhalten, Peer hat verloren", log: LOG, type: .info)
|
2020-06-07 12:00:12 +02:00
|
|
|
winner = hostingPlayer?.displayName
|
|
|
|
gameEnded = true
|
2020-06-02 22:18:59 +02:00
|
|
|
case 5:
|
|
|
|
os_log("State 5 erhalten, Peer hat gewonnen", log: LOG, type: .info)
|
2020-06-07 12:00:12 +02:00
|
|
|
winner = peerPlayer?.displayName
|
|
|
|
gameEnded = true
|
2020-06-02 22:18:59 +02:00
|
|
|
default:
|
|
|
|
break
|
2020-05-27 22:41:05 +02:00
|
|
|
}
|
|
|
|
}
|
2020-06-01 17:27:13 +02:00
|
|
|
if let roundData = try? jsonDecoder.decode(LocalRoundData.self, from: data) {
|
|
|
|
DataService.sharedInstance.addRemotePlayerMoves(playerName: player.displayName, localRoundData: roundData)
|
2020-05-27 22:41:05 +02:00
|
|
|
}
|
|
|
|
if let snapshotModel = try? jsonDecoder.decode(SnapshotModel.self, from: data) {
|
|
|
|
DataService.sharedInstance.snapshotModel = snapshotModel
|
2020-06-02 20:52:11 +02:00
|
|
|
RoundCalculatorService.sharedInstance.currentRound += 1
|
|
|
|
entityManager.getHUD()?.setCurrentRound(round: RoundCalculatorService.sharedInstance.currentRound)
|
2020-05-27 22:41:05 +02:00
|
|
|
entityManager.updateSnapshotModel(snapshotModel: snapshotModel)
|
2020-05-30 14:46:42 +02:00
|
|
|
entityManager.getHUD()?.startWithDuration()
|
2020-05-27 22:41:05 +02:00
|
|
|
}
|
|
|
|
if let mapModel = try? jsonDecoder.decode(MapGenerationModel.self, from: data) {
|
|
|
|
os_log("Peer hat Map erhalten", log: LOG, type: .info)
|
|
|
|
let scene = GameScene(size: self.menusc!.size)
|
|
|
|
EntityManager.gameEMInstance.setScene(scene: scene)
|
|
|
|
DataService.sharedInstance.setMapModel(model: mapModel)
|
|
|
|
os_log("Map model wurde gesetzt", log: LOG, type: .info)
|
|
|
|
GameCenterManager.sharedInstance.isMatchStarted = true
|
|
|
|
self.gameScene = scene
|
|
|
|
sendStateToPeers(state: State(state: 2))
|
|
|
|
os_log("State 2 wurde an Host gesendet", log: LOG, type: .info)
|
|
|
|
initIsFinish = true
|
|
|
|
os_log("Peer startet Spiel", log: LOG, type: .info)
|
|
|
|
}
|
2020-06-06 18:59:26 +02:00
|
|
|
|
|
|
|
if let notification = try? jsonDecoder.decode(NotificationModel.self, from: data) {
|
|
|
|
os_log("Notification erhalten", log: LOG, type: .info)
|
|
|
|
NotificationCenter.default.post(name: Notification.Name(rawValue: notification.name), object: nil)
|
|
|
|
}
|
2020-06-18 20:10:08 +02:00
|
|
|
|
|
|
|
if let eloData = try? jsonDecoder.decode(EloDataForPeer.self, from: data) {
|
|
|
|
print("Recieved elo data: \(eloData.scoreToReport)")
|
|
|
|
let score = GKScore(leaderboardIdentifier: EloHelper.IDENTIFIER, player: self.localPlayer)
|
|
|
|
score.value = eloData.scoreToReport
|
|
|
|
GKScore.report([score], withCompletionHandler: { error in
|
|
|
|
os_log("New Scores reported to EloSystem", log: self.LOG, type: .info)
|
|
|
|
})
|
|
|
|
}
|
2020-05-27 22:41:05 +02:00
|
|
|
MultiplayerNetwork.sharedInstance.isSending = false
|
|
|
|
}
|
|
|
|
|
|
|
|
func initAndSendMap() -> Void {
|
|
|
|
self.gameScene = GameScene(size: self.menusc!.size)
|
2020-05-29 16:23:56 +02:00
|
|
|
let mapModel = MapFactory(scene: self.gameScene!, entityManager: entityManager).load()
|
2020-05-27 22:41:05 +02:00
|
|
|
os_log("Map wurde erstellt", log: LOG, type: .info)
|
|
|
|
MultiplayerNetwork.sharedInstance.sendMapModelToPlayers(mapModel: mapModel)
|
|
|
|
os_log("Map wurde an Peer gesendet", log: LOG, type: .info)
|
|
|
|
DataService.sharedInstance.setSnapshotModel(snapshotModel: entityManager.getSnapshotModel())
|
|
|
|
os_log("SnapshotModel wurde erstellt", log: LOG, type: .info)
|
|
|
|
}
|
|
|
|
|
|
|
|
func getGKPlayerByUsername(displayName: String) -> GKPlayer? {
|
|
|
|
let nilGK : GKPlayer? = nil
|
|
|
|
|
|
|
|
if GKLocalPlayer.local.displayName == displayName {
|
|
|
|
return GKLocalPlayer.local
|
|
|
|
}
|
|
|
|
|
|
|
|
for player in myMatch!.players {
|
|
|
|
if player.displayName == displayName {
|
|
|
|
return player
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nilGK
|
|
|
|
}
|
|
|
|
func sendStateToPeers(state: State){
|
|
|
|
let encoder = JSONEncoder()
|
|
|
|
let encoded = (try? encoder.encode(state))!
|
|
|
|
MultiplayerNetwork.sharedInstance.sendData(data: encoded)
|
|
|
|
}
|
|
|
|
|
|
|
|
func sendRandomNumberToAllPeers(in match: GKMatch){
|
|
|
|
let encoder = JSONEncoder()
|
|
|
|
let encoded = (try? encoder.encode(localPlayerRandomNumber))!
|
|
|
|
MultiplayerNetwork.sharedInstance.sendData(data: encoded)
|
|
|
|
}
|
|
|
|
|
|
|
|
func player(_ player: GKPlayer, didAccept invite: GKInvite) {
|
|
|
|
os_log("Einladung angenommen", log: LOG, type: .info)
|
|
|
|
let matchmakerVC = GKMatchmakerViewController.init(invite: invite)
|
|
|
|
matchmakerVC!.matchmakerDelegate = self
|
|
|
|
viewController?.present(matchmakerVC!, animated: true, completion: nil)
|
|
|
|
}
|
|
|
|
func matchmakerViewControllerWasCancelled(_ viewController: GKMatchmakerViewController) {
|
|
|
|
viewController.dismiss(animated: true, completion: nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFailWithError error: Error) {
|
|
|
|
viewController.dismiss(animated: true, completion: nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFind match: GKMatch) {
|
|
|
|
viewController.dismiss(animated: true, completion: nil)
|
|
|
|
myMatch = match
|
|
|
|
if !isMatchStarted && match.expectedPlayerCount == 0 {
|
|
|
|
myMatch?.delegate = self
|
|
|
|
sendRandomNumberToAllPeers(in: self.myMatch!)
|
|
|
|
os_log("Random Number wurde an den anderen Spieler gesendet", log: LOG, type: .info)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-02 15:29:53 +02:00
|
|
|
func gameCenterViewControllerDidFinish(_ gameCenterViewController: GKGameCenterViewController) {
|
|
|
|
gameCenterViewController.dismiss(animated: true, completion: nil)
|
|
|
|
}
|
|
|
|
|
2020-05-27 22:41:05 +02:00
|
|
|
func disconnect() {
|
|
|
|
if myMatch != nil {
|
|
|
|
myMatch?.disconnect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension Notification.Name {
|
|
|
|
static let presentGame = Notification.Name(rawValue: "presentGame")
|
|
|
|
static let authenticationChanged = Notification.Name(rawValue: "authenticationChanged")
|
|
|
|
}
|