From 9329978981178a01e6b61175773707f20f7bfa91 Mon Sep 17 00:00:00 2001 From: Niko Jochim <82joni1bif@hft-stuttgart.de> Date: Wed, 27 May 2020 20:41:05 +0000 Subject: [PATCH] * create new GameCenterManager * send RandomNumber to all Peers Method --- GoldWars/GoldWars.xcodeproj/project.pbxproj | 20 +- .../Components/PlayerInfoComponent.swift | 9 +- .../GoldWars/Components/TimerComponent.swift | 2 +- GoldWars/GoldWars/DataService.swift | 13 +- .../GoldWars/Entities/EntityManager.swift | 2 +- GoldWars/GoldWars/GameCenterHelper.swift | 45 ---- GoldWars/GoldWars/GameCenterManager.swift | 219 ++++++++++++++++++ GoldWars/GoldWars/GameViewController.swift | 6 +- .../Map/TwoPlayerDefaultTestMap.swift | 4 +- .../GoldWars/Map/TwoPlayerMapGenerator.swift | 4 +- GoldWars/GoldWars/MatchmakingHelper.swift | 216 ----------------- GoldWars/GoldWars/MultiplayerNetwork.swift | 33 +-- GoldWars/GoldWars/Scenes/GameScene.swift | 11 +- GoldWars/GoldWars/Scenes/MenuScene.swift | 16 +- 14 files changed, 267 insertions(+), 333 deletions(-) delete mode 100644 GoldWars/GoldWars/GameCenterHelper.swift create mode 100644 GoldWars/GoldWars/GameCenterManager.swift delete mode 100644 GoldWars/GoldWars/MatchmakingHelper.swift diff --git a/GoldWars/GoldWars.xcodeproj/project.pbxproj b/GoldWars/GoldWars.xcodeproj/project.pbxproj index b1e5e03..86d5540 100644 --- a/GoldWars/GoldWars.xcodeproj/project.pbxproj +++ b/GoldWars/GoldWars.xcodeproj/project.pbxproj @@ -20,12 +20,12 @@ 3E67854024728368007B9DE4 /* CElements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E67853F24728368007B9DE4 /* CElements.swift */; }; 3E6785422472CBEC007B9DE4 /* Way.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E6785412472CBEC007B9DE4 /* Way.swift */; }; 3E6785442472CC27007B9DE4 /* DefaultWayComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E6785432472CC27007B9DE4 /* DefaultWayComponent.swift */; }; - 3EBD242C245D8044003CECE7 /* GameCenterHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EBD242B245D8044003CECE7 /* GameCenterHelper.swift */; }; 3EBD242E245D9332003CECE7 /* Team.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EBD242D245D9332003CECE7 /* Team.swift */; }; 3F745DF0246F48FC00CE7375 /* PlayerMoveType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F745DEF246F48FC00CE7375 /* PlayerMoveType.swift */; }; 3FE19DB5246C7A22004827AB /* RoundCalculatorService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FE19DB4246C7A22004827AB /* RoundCalculatorService.swift */; }; 8BB6FF402472B8F000162BBD /* SingeClickButtonNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB6FF3F2472B8F000162BBD /* SingeClickButtonNode.swift */; }; 9E04AFAF245E2B73002D5CFC /* AttackActionComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E04AFAE245E2B73002D5CFC /* AttackActionComponent.swift */; }; + 9E0E459724796262009817A6 /* GameCenterManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E0E459624796262009817A6 /* GameCenterManager.swift */; }; 9E11FF79245CD81100EED3BE /* Fire.sks in Resources */ = {isa = PBXBuildFile; fileRef = 9E11FF77245CD81100EED3BE /* Fire.sks */; }; 9E174C82245DD81D00209FF0 /* ButtonNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E174C81245DD81D00209FF0 /* ButtonNode.swift */; }; 9E174C84245DD8CE00209FF0 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E174C83245DD8CE00209FF0 /* Button.swift */; }; @@ -49,10 +49,9 @@ AB1D75A0245DEC0500671525 /* MapFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB1D759F245DEC0500671525 /* MapFactory.swift */; }; AB21D7D5246C748A00B09CBA /* TwoPlayerMapGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB21D7D4246C748A00B09CBA /* TwoPlayerMapGenerator.swift */; }; ABA03DA0244BD54F00A66916 /* Base.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABA03D9F244BD54F00A66916 /* Base.swift */; }; - ABB8A40E247B195500B901BE /* SliderComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABB8A40D247B195500B901BE /* SliderComponent.swift */; }; - AE151589245F18EF001D363E /* MatchmakingHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE151588245F18EF001D363E /* MatchmakingHelper.swift */; }; C04783EE2468583F004961FB /* intro-music.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C04783ED2468583F004961FB /* intro-music.mp3 */; }; C04783F024685995004961FB /* SettingsScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04783EF24685995004961FB /* SettingsScene.swift */; }; + C05BB9C4247D890C00411249 /* SliderComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C05BB9C3247D890C00411249 /* SliderComponent.swift */; }; C05FAED62468559D0006AF2E /* SoundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C05FAED52468559D0006AF2E /* SoundManager.swift */; }; C064E9A8246C0EA50022B228 /* LabelNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = C064E9A7246C0EA50022B228 /* LabelNode.swift */; }; C064E9AA246C114C0022B228 /* LabelComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C064E9A9246C114C0022B228 /* LabelComponent.swift */; }; @@ -88,12 +87,12 @@ 3E67853F24728368007B9DE4 /* CElements.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CElements.swift; sourceTree = ""; }; 3E6785412472CBEC007B9DE4 /* Way.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Way.swift; sourceTree = ""; }; 3E6785432472CC27007B9DE4 /* DefaultWayComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultWayComponent.swift; sourceTree = ""; }; - 3EBD242B245D8044003CECE7 /* GameCenterHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameCenterHelper.swift; sourceTree = ""; }; 3EBD242D245D9332003CECE7 /* Team.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Team.swift; sourceTree = ""; }; 3F745DEF246F48FC00CE7375 /* PlayerMoveType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerMoveType.swift; sourceTree = ""; }; 3FE19DB4246C7A22004827AB /* RoundCalculatorService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundCalculatorService.swift; sourceTree = ""; }; 8BB6FF3F2472B8F000162BBD /* SingeClickButtonNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingeClickButtonNode.swift; sourceTree = ""; }; 9E04AFAE245E2B73002D5CFC /* AttackActionComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttackActionComponent.swift; sourceTree = ""; }; + 9E0E459624796262009817A6 /* GameCenterManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameCenterManager.swift; sourceTree = ""; }; 9E11FF77245CD81100EED3BE /* Fire.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Fire.sks; sourceTree = ""; }; 9E174C81245DD81D00209FF0 /* ButtonNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ButtonNode.swift; sourceTree = ""; }; 9E174C83245DD8CE00209FF0 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; @@ -118,10 +117,9 @@ AB1D759F245DEC0500671525 /* MapFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapFactory.swift; sourceTree = ""; }; AB21D7D4246C748A00B09CBA /* TwoPlayerMapGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoPlayerMapGenerator.swift; sourceTree = ""; }; ABA03D9F244BD54F00A66916 /* Base.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Base.swift; sourceTree = ""; }; - ABB8A40D247B195500B901BE /* SliderComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SliderComponent.swift; sourceTree = ""; }; - AE151588245F18EF001D363E /* MatchmakingHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatchmakingHelper.swift; sourceTree = ""; }; C04783ED2468583F004961FB /* intro-music.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = "intro-music.mp3"; sourceTree = ""; }; C04783EF24685995004961FB /* SettingsScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScene.swift; sourceTree = ""; }; + C05BB9C3247D890C00411249 /* SliderComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SliderComponent.swift; sourceTree = ""; }; C05FAED52468559D0006AF2E /* SoundManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoundManager.swift; sourceTree = ""; }; C064E9A7246C0EA50022B228 /* LabelNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelNode.swift; sourceTree = ""; }; C064E9A9246C114C0022B228 /* LabelComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelComponent.swift; sourceTree = ""; }; @@ -186,9 +184,8 @@ 9EC239E0246878A900952F74 /* MultiplayerNetwork.swift */, C099579B246C5E5C0016AA22 /* DataService.swift */, 110360E4244B101B008610AF /* Info.plist */, - AE151588245F18EF001D363E /* MatchmakingHelper.swift */, 3FE19DB4246C7A22004827AB /* RoundCalculatorService.swift */, - 3EBD242B245D8044003CECE7 /* GameCenterHelper.swift */, + 9E0E459624796262009817A6 /* GameCenterManager.swift */, C04783EF24685995004961FB /* SettingsScene.swift */, ); path = GoldWars; @@ -206,6 +203,7 @@ 116060F4245C56EA004E5A36 /* Components */ = { isa = PBXGroup; children = ( + C05BB9C3247D890C00411249 /* SliderComponent.swift */, C064E9A7246C0EA50022B228 /* LabelNode.swift */, 9E174C81245DD81D00209FF0 /* ButtonNode.swift */, 8BB6FF3F2472B8F000162BBD /* SingeClickButtonNode.swift */, @@ -220,7 +218,6 @@ 9E174C87245DF1FF00209FF0 /* BackgroundComponent.swift */, 9E04AFAE245E2B73002D5CFC /* AttackActionComponent.swift */, 2086465B2461B66200817C23 /* TimerComponent.swift */, - ABB8A40D247B195500B901BE /* SliderComponent.swift */, 3E6785432472CC27007B9DE4 /* DefaultWayComponent.swift */, 9EC2FBA62476B1EC00ABF11F /* PlayerInfoComponent.swift */, ); @@ -402,6 +399,7 @@ buildActionMask = 2147483647; files = ( 9E78ACB8245CB75B00526FF7 /* TeamComponent.swift in Sources */, + 9E0E459724796262009817A6 /* GameCenterManager.swift in Sources */, 3FE19DB5246C7A22004827AB /* RoundCalculatorService.swift in Sources */, 9EC86BA6245C8AD000796EF3 /* ModalType.swift in Sources */, 9EC239E1246878A900952F74 /* MultiplayerNetwork.swift in Sources */, @@ -418,8 +416,6 @@ 9EC2FBA72476B1EC00ABF11F /* PlayerInfoComponent.swift in Sources */, 9EEDE02D246FCD770096C735 /* SpinningLogoEntity.swift in Sources */, 9E174C86245DD91500209FF0 /* ButtonComponent.swift in Sources */, - AE151589245F18EF001D363E /* MatchmakingHelper.swift in Sources */, - ABB8A40E247B195500B901BE /* SliderComponent.swift in Sources */, 11036113244B3E30008610AF /* MenuScene.swift in Sources */, C099579C246C5E5C0016AA22 /* DataService.swift in Sources */, AB21D7D5246C748A00B09CBA /* TwoPlayerMapGenerator.swift in Sources */, @@ -428,7 +424,6 @@ 8BB6FF402472B8F000162BBD /* SingeClickButtonNode.swift in Sources */, AB0B88F6247AD89200C8DF66 /* SkillComponent.swift in Sources */, C064E9A8246C0EA50022B228 /* LabelNode.swift in Sources */, - 3EBD242C245D8044003CECE7 /* GameCenterHelper.swift in Sources */, 3F745DF0246F48FC00CE7375 /* PlayerMoveType.swift in Sources */, AB1D75A0245DEC0500671525 /* MapFactory.swift in Sources */, AB1D759D245DD18100671525 /* TwoPlayerDefaultTestMap.swift in Sources */, @@ -442,6 +437,7 @@ 110360DB244B101A008610AF /* GameViewController.swift in Sources */, 3E6785442472CC27007B9DE4 /* DefaultWayComponent.swift in Sources */, 2086465C2461B66200817C23 /* TimerComponent.swift in Sources */, + C05BB9C4247D890C00411249 /* SliderComponent.swift in Sources */, 110360D3244B101A008610AF /* AppDelegate.swift in Sources */, 9EC86B9F245C88A300796EF3 /* Modal.swift in Sources */, C05FAED62468559D0006AF2E /* SoundManager.swift in Sources */, diff --git a/GoldWars/GoldWars/Components/PlayerInfoComponent.swift b/GoldWars/GoldWars/Components/PlayerInfoComponent.swift index 26d1b1d..5db9c9e 100644 --- a/GoldWars/GoldWars/Components/PlayerInfoComponent.swift +++ b/GoldWars/GoldWars/Components/PlayerInfoComponent.swift @@ -23,13 +23,8 @@ class PlayerInfoComponent: GKComponent { var peer: GKPlayer? init(size: CGSize) { - if MatchmakingHelper.sharedInstance.isServer { - host = GKLocalPlayer.local - peer = MatchmakingHelper.sharedInstance.mpMatch?.players[0] - } else { - host = MatchmakingHelper.sharedInstance.mpMatch?.players[0] - peer = GKLocalPlayer.local - } + host = GameCenterManager.sharedInstance.hostingPlayer + peer = GameCenterManager.sharedInstance.peerPlayer hostLabel = SKLabelNode(text: host?.displayName) hostUnitsLabel = SKLabelNode(text: "500" ) peerLabel = SKLabelNode(text: peer?.displayName) diff --git a/GoldWars/GoldWars/Components/TimerComponent.swift b/GoldWars/GoldWars/Components/TimerComponent.swift index 41461b2..fc6df85 100644 --- a/GoldWars/GoldWars/Components/TimerComponent.swift +++ b/GoldWars/GoldWars/Components/TimerComponent.swift @@ -61,7 +61,7 @@ class TimerComponent: GKComponent { } if !RoundCalculatorService.sharedInstance.isCalculating && DataService.sharedInstance.didReceiveAllData() - && MatchmakingHelper.sharedInstance.isServer { + && GameCenterManager.sharedInstance.isServer { RoundCalculatorService.sharedInstance.calculateRound() } } diff --git a/GoldWars/GoldWars/DataService.swift b/GoldWars/GoldWars/DataService.swift index f12623f..5ae7da0 100644 --- a/GoldWars/GoldWars/DataService.swift +++ b/GoldWars/GoldWars/DataService.swift @@ -12,10 +12,6 @@ struct PlayerMove: Codable{ var unitCount: Int } -struct Host: Codable { - let playerName: String -} - class SnapshotModel: Codable { var baseEntites: [BaseEntityModel] @@ -41,7 +37,8 @@ class DataService { var localPlayerMoves: [PlayerMove] = [] var remotePlayerMoves: [String: [PlayerMove]] = [:] var snapshotModel: SnapshotModel? - var gameHost: Host? + var hostingPlayer = GameCenterManager.sharedInstance.hostingPlayer + var mapModel: MapGenerationModel? var entityManager = EntityManager.gameEMInstance @@ -61,13 +58,9 @@ class DataService { } func didReceiveAllData() -> Bool { - return remotePlayerMoves.count == MatchmakingHelper.sharedInstance.mpMatch?.players.count + return remotePlayerMoves.count == GameCenterManager.sharedInstance.myMatch?.players.count } - func setGameHost(host: Host) { - self.gameHost = host - } - func setSnapshotModel(snapshotModel: SnapshotModel) { self.snapshotModel = snapshotModel } diff --git a/GoldWars/GoldWars/Entities/EntityManager.swift b/GoldWars/GoldWars/Entities/EntityManager.swift index 9301d1e..19aab8b 100644 --- a/GoldWars/GoldWars/Entities/EntityManager.swift +++ b/GoldWars/GoldWars/Entities/EntityManager.swift @@ -137,7 +137,7 @@ class EntityManager { base.unitCount = snapBase.unitCount if snapBase.ownership != nil { - getOwnerBySnapBase = MatchmakingHelper.sharedInstance.getGKPlayerByUsername(displayName: snapBase.ownership!) + getOwnerBySnapBase = GameCenterManager.sharedInstance.getGKPlayerByUsername(displayName: snapBase.ownership!) } else { entity.removeComponent(ofType: TeamComponent.self) } diff --git a/GoldWars/GoldWars/GameCenterHelper.swift b/GoldWars/GoldWars/GameCenterHelper.swift deleted file mode 100644 index abf9578..0000000 --- a/GoldWars/GoldWars/GameCenterHelper.swift +++ /dev/null @@ -1,45 +0,0 @@ -// -// GameCenterHelper.swift -// GoldWars -// -// Created by Jakob Haag on 02.05.20. -// Copyright © 2020 SP2. All rights reserved. -// - -import GameKit - -final class GameCenterHelper: NSObject { - typealias CompletionBlock = (Error?) -> Void - - static let helper = GameCenterHelper() - - var viewController: UIViewController? - - static var isAuthenticated: Bool { - return GKLocalPlayer.local.isAuthenticated - } - - override init() { - super.init() - - GKLocalPlayer.local.authenticateHandler = { gcAuthVC, error in - NotificationCenter.default - .post(name: .authenticationChanged, object: GKLocalPlayer.local.isAuthenticated) - - if GKLocalPlayer.local.isAuthenticated { - print("Authenticated to Game Center!") - } else if let vc = gcAuthVC { - self.viewController?.present(vc, animated: true) - } - else { - print("Error authentication to GameCenter: " + - "\(error?.localizedDescription ?? "none")") - } - } - } -} - -extension Notification.Name { - static let presentGame = Notification.Name(rawValue: "presentGame") - static let authenticationChanged = Notification.Name(rawValue: "authenticationChanged") -} diff --git a/GoldWars/GoldWars/GameCenterManager.swift b/GoldWars/GoldWars/GameCenterManager.swift new file mode 100644 index 0000000..ba0ce93 --- /dev/null +++ b/GoldWars/GoldWars/GameCenterManager.swift @@ -0,0 +1,219 @@ +// +// 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 + let state: Int +} + +final class GameCenterManager: NSObject, GKMatchmakerViewControllerDelegate ,GKMatchDelegate,GKLocalPlayerListener{ + + static let sharedInstance = GameCenterManager() + + 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 + var gameScene: GameScene? + static var isAuthenticated: Bool { + return GKLocalPlayer.local.isAuthenticated + } + + override init() { + super.init() + localPlayer.register(self) + authUser(); + localPlayerRandomNumber = RandomNumber() + } + + 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) + } + + 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 { + 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) + default: + break + } + } + if let playerMoves = try? jsonDecoder.decode([PlayerMove].self, from: data) { + DataService.sharedInstance.addRemotePlayerMoves(playerName: player.displayName, playerMoves: playerMoves) + } + 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) { + 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) + } + MultiplayerNetwork.sharedInstance.isSending = false + } + + func initAndSendMap() -> Void { + self.gameScene = GameScene(size: self.menusc!.size) + let mapModel = MapFactory(scene: self.gameScene!, entityManager: entityManager).loadMap() + 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) + } + } + + func disconnect() { + if myMatch != nil { + myMatch?.disconnect() + } + } +} + +extension Notification.Name { + static let presentGame = Notification.Name(rawValue: "presentGame") + static let authenticationChanged = Notification.Name(rawValue: "authenticationChanged") +} diff --git a/GoldWars/GoldWars/GameViewController.swift b/GoldWars/GoldWars/GameViewController.swift index 604a530..a3b45f5 100644 --- a/GoldWars/GoldWars/GameViewController.swift +++ b/GoldWars/GoldWars/GameViewController.swift @@ -23,11 +23,11 @@ class GameViewController: UIViewController { //TODO: create dev profile or remove on delivery view.showsFPS = true view.showsNodeCount = true - GameCenterHelper.helper.viewController = self - MatchmakingHelper.sharedInstance.viewController = self } + GameCenterManager.sharedInstance.viewController = self + + } - override var shouldAutorotate: Bool { return true } diff --git a/GoldWars/GoldWars/Map/TwoPlayerDefaultTestMap.swift b/GoldWars/GoldWars/Map/TwoPlayerDefaultTestMap.swift index 5f67cd7..84e4a48 100644 --- a/GoldWars/GoldWars/Map/TwoPlayerDefaultTestMap.swift +++ b/GoldWars/GoldWars/Map/TwoPlayerDefaultTestMap.swift @@ -25,7 +25,7 @@ class TwoPlayerDefaultTestMap: MapProtocol { // Create Bases let basePlayerOne = Base( position: CGPoint(x: self.size.width * 0.1, y: self.size.height / 2), - player: (MatchmakingHelper.sharedInstance.isServer) ? GKLocalPlayer.local : MatchmakingHelper.sharedInstance.mpMatch?.players[0], + player: (GameCenterManager.sharedInstance.isServer) ? GKLocalPlayer.local : GameCenterManager.sharedInstance.myMatch?.players[0], team: .team1 ) @@ -48,7 +48,7 @@ class TwoPlayerDefaultTestMap: MapProtocol { let basePlayerTwo = Base( position: CGPoint(x: self.size.width * 0.9, y: self.size.height / 2), - player: (!MatchmakingHelper.sharedInstance.isServer) ? GKLocalPlayer.local : MatchmakingHelper.sharedInstance.mpMatch?.players[0], + player: (!GameCenterManager.sharedInstance.isServer) ? GKLocalPlayer.local : GameCenterManager.sharedInstance.myMatch?.players[0], team: .team2 ) diff --git a/GoldWars/GoldWars/Map/TwoPlayerMapGenerator.swift b/GoldWars/GoldWars/Map/TwoPlayerMapGenerator.swift index 918bdf2..52e303d 100644 --- a/GoldWars/GoldWars/Map/TwoPlayerMapGenerator.swift +++ b/GoldWars/GoldWars/Map/TwoPlayerMapGenerator.swift @@ -56,7 +56,7 @@ class TwoPlayerMapGenerator: MapProtocol { os_log("Get player one base", log: LOG, type: .info) let basePlayerOne = Base( position: CGPoint(x: self.size.width * 0.07, y: self.size.height / 2), - player: (MatchmakingHelper.sharedInstance.isServer) ? GKLocalPlayer.local : MatchmakingHelper.sharedInstance.mpMatch?.players[0], + player: (GameCenterManager.sharedInstance.isServer) ? GKLocalPlayer.local : GameCenterManager.sharedInstance.myMatch?.players[0], team: .team1 ) @@ -128,7 +128,7 @@ class TwoPlayerMapGenerator: MapProtocol { os_log("Get player two base", log: LOG, type: .info) let basePlayerTwo = Base( position: CGPoint(x: self.size.width * 0.93, y: self.size.height / 2), - player: (!MatchmakingHelper.sharedInstance.isServer) ? GKLocalPlayer.local : MatchmakingHelper.sharedInstance.mpMatch?.players[0], + player: (!GameCenterManager.sharedInstance.isServer) ? GKLocalPlayer.local : GameCenterManager.sharedInstance.myMatch?.players[0], team: .team2 ) diff --git a/GoldWars/GoldWars/MatchmakingHelper.swift b/GoldWars/GoldWars/MatchmakingHelper.swift deleted file mode 100644 index ec5477a..0000000 --- a/GoldWars/GoldWars/MatchmakingHelper.swift +++ /dev/null @@ -1,216 +0,0 @@ -// -// MatchmakingHelper.swift -// GoldWars -// -// Created by Chauntalle Schüle, Ömer Özel, Eray Kör on 03.05.20. -// Copyright © 2020 SP2. All rights reserved. -// - -import GameKit - -protocol GameKitHelperDelegate { - func matchStarted() - func matchEnded() - func matchReceivedData(match: GKMatch, data: NSData, - fromPlayer player: String) - -} -/* - 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 - */ -class MatchmakingHelper: NSObject, GKMatchmakerViewControllerDelegate, GKMatchDelegate { - - var delegate: GameKitHelperDelegate? - var mpMatch: GKMatch? - var viewController: UIViewController? - var mpMatchStarted: Bool - var isServer: Bool - var spieler1: GKPlayer? - var nameSpieler1 = "" - var menusc: MenuScene? - let localPlayer: GKLocalPlayer = GKLocalPlayer.local - var entityManager = EntityManager.gameEMInstance - - static let sharedInstance = MatchmakingHelper() - - - static var isAuthenticated: Bool{ - return GKLocalPlayer.local.isAuthenticated - } - - override init() { - mpMatchStarted = false - isServer = false - 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. - */ - func presentMatchmaker(scene: MenuScene) { - menusc = scene - 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) - } - - /* - Der User hat die Verbindung mit "Abbrechen" unterbrochen. GameCenter MatchMaking wird beendet. - */ - func matchmakerViewControllerWasCancelled(_ viewController: GKMatchmakerViewController) { - viewController.dismiss(animated: true, completion: nil) - delegate?.matchEnded() - } - - /* - Wenn GameCenter kein match erstellen kann, wird der viewcontroller dismissed. - */ - func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFailWithError error: Error) { - viewController.dismiss(animated: true, completion: nil) - print("Error finding match", error.localizedDescription) - delegate?.matchEnded() - } - - /* - 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 - */ - func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFind match: GKMatch) { - viewController.dismiss(animated: true, completion: nil) - mpMatch = match - match.delegate = self - if !mpMatchStarted && match.expectedPlayerCount == 0 { - startMatch() - } - } - - /* - Vom match erhaltene Spielerdaten - */ - func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) { - if mpMatch != match { return } - - let jsonDecoder = JSONDecoder() - - if let playerMoves = try? jsonDecoder.decode([PlayerMove].self, from: data) { - DataService.sharedInstance.addRemotePlayerMoves(playerName: player.displayName, playerMoves: playerMoves) - } - - if let message = try? jsonDecoder.decode(Host.self, from: data) { - DataService.sharedInstance.gameHost = message - } - - 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 - } - - /* - Verbindung/Matchmaking ist fehlgeschlagen - */ - private func match(match: GKMatch!, didFailWithError error: NSError!) { - if mpMatch != match { - return - } - mpMatchStarted = false - delegate?.matchEnded() - } - - /* - Wird beim ändern des States/Zustands des Spielers aufgerufen udn gibt dessen Zustand zurück. - */ - func match(_ match: GKMatch, player: GKPlayer, didChange state: GKPlayerConnectionState) { - if mpMatch != match { - return - } - - switch (state) { - case GKPlayerConnectionState.connected: - if (!mpMatchStarted && match.expectedPlayerCount == 0) { - startMatch() - } - case GKPlayerConnectionState.disconnected: - mpMatchStarted = false - delegate?.matchEnded() - default: - delegate?.matchEnded() - } - } - - /* - Ein Spieler wird als Host für das Match gewählt. Dieser ist Spieler 1. Im Anschluss wird die GameScene geladen. - */ - func startMatch() { - - mpMatch!.chooseBestHostingPlayer(completionHandler: { - (player) in - - self.mpMatchStarted = true - - if player == GKLocalPlayer.local { - self.isServer = true - self.spieler1 = player - self.nameSpieler1 = self.spieler1!.displayName - DataService.sharedInstance.setGameHost(host: Host(playerName: player!.displayName)) - } else { - self.isServer = false - } - - self.delegate?.matchStarted() - let scene = GameScene(size: self.menusc!.size) - self.entityManager.setScene(scene: scene) - self.menusc!.loadScene(scene: scene) - MultiplayerNetwork.sharedInstance.sendHostIdentifier() - }) - } - - 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 - } - - /* - Trennt die Verbindung vom Match - */ - func disconnect() { - if mpMatch != nil { - mpMatch?.disconnect() - } - } -} diff --git a/GoldWars/GoldWars/MultiplayerNetwork.swift b/GoldWars/GoldWars/MultiplayerNetwork.swift index 9535514..89b1479 100644 --- a/GoldWars/GoldWars/MultiplayerNetwork.swift +++ b/GoldWars/GoldWars/MultiplayerNetwork.swift @@ -15,24 +15,21 @@ class MultiplayerNetwork{ var isSending = false - func sendData(data: Data) { - let mmHelper = MatchmakingHelper.sharedInstance - if let multiplayerMatch = mmHelper.mpMatch { - do { - try multiplayerMatch.sendData(toAllPlayers: data, with: .reliable) - } catch { - //TODO: Add logging - } - } - } + func sendData(data: Data) { + let mmHelper = GameCenterManager.sharedInstance + if let multiplayerMatch = mmHelper.myMatch { + do { + try multiplayerMatch.sendData(toAllPlayers: data, with: .reliable) + } catch { + } + } + } func sendDataToHost(data: Data) { - let mmHelper = MatchmakingHelper.sharedInstance - let hostGKPlayer = MatchmakingHelper.sharedInstance.mpMatch?.players.filter{ $0.displayName == DataService.sharedInstance.gameHost!.playerName}[0] - if let multiplayerMatch = mmHelper.mpMatch{ + if let multiplayerMatch = GameCenterManager.sharedInstance.myMatch{ do { - try multiplayerMatch.send(data, to: [hostGKPlayer!], dataMode: .reliable) + try multiplayerMatch.send(data, to: [GameCenterManager.sharedInstance.hostingPlayer!], dataMode: .reliable) } catch { //TODO: Add logging } @@ -40,7 +37,7 @@ class MultiplayerNetwork{ } func sendPlayerMoves(playerMoves: [PlayerMove]) { - if MatchmakingHelper.sharedInstance.isServer == false { + if GameCenterManager.sharedInstance.isServer == false { self.isSending = true let encoder = JSONEncoder() let encoded = (try? encoder.encode(playerMoves))! @@ -49,12 +46,6 @@ class MultiplayerNetwork{ } } - func sendHostIdentifier() { - let encoder = JSONEncoder() - let encoded = (try? encoder.encode(DataService.sharedInstance.gameHost))! - sendData(data: encoded) - } - func sendSnapshotModelToPlayers() { let encoder = JSONEncoder() let encoded = (try? encoder.encode(DataService.sharedInstance.snapshotModel))! diff --git a/GoldWars/GoldWars/Scenes/GameScene.swift b/GoldWars/GoldWars/Scenes/GameScene.swift index 4b0fe8b..0dc2a6d 100644 --- a/GoldWars/GoldWars/Scenes/GameScene.swift +++ b/GoldWars/GoldWars/Scenes/GameScene.swift @@ -23,17 +23,9 @@ class GameScene: SKScene{ entityManager.setScene(scene: self) entityManager.add(HUD(size: self.size)) entityManager.add(Background(size: self.size)) - initMap() - } - - func initMap() { - if (DataService.sharedInstance.gameHost?.playerName == GKLocalPlayer.local.displayName) { - let mapModel = MapFactory(scene: self, entityManager: entityManager).loadMap() - MultiplayerNetwork.sharedInstance.sendMapModelToPlayers(mapModel: mapModel) - DataService.sharedInstance.setSnapshotModel(snapshotModel: entityManager.getSnapshotModel()) - } if CommandLine.arguments.contains("--no-matchmaking") { _ = MapFactory(scene: self, entityManager: entityManager).loadMap() + return } } @@ -57,7 +49,6 @@ class GameScene: SKScene{ else { for entity in entityManager.entities { let spriteNode = entity.component(ofType: DefaultBaseComponent.self)?.spriteNode - //FIXME: this is confusing addBaseDetails(touchLocation: touchLocation, spriteNode: spriteNode, touches: touches, event: event, entity: entity) } diff --git a/GoldWars/GoldWars/Scenes/MenuScene.swift b/GoldWars/GoldWars/Scenes/MenuScene.swift index 22152a1..6281713 100644 --- a/GoldWars/GoldWars/Scenes/MenuScene.swift +++ b/GoldWars/GoldWars/Scenes/MenuScene.swift @@ -13,7 +13,7 @@ class MenuScene: SKScene { var entityManager = EntityManager.menuEMInstance override func sceneDidLoad() { - + GameCenterManager.sharedInstance.menusc = self entityManager.setScene(scene: self) let midX = self.size.width / 2 let midY = self.size.height / 2 @@ -26,7 +26,12 @@ class MenuScene: SKScene { self.loadScene(scene: GameScene(size: self.size)) SoundManager.sharedInstance.stopMenuMusic() } else { - MatchmakingHelper.sharedInstance.presentMatchmaker(scene: self) + + if GameCenterManager.isAuthenticated { + GameCenterManager.sharedInstance.presentMatchmaker() + }else { + GameCenterManager.sharedInstance.authUser() + } } })) entityManager.add(Button(name: "settingsButton", @@ -54,7 +59,12 @@ class MenuScene: SKScene { override func update(_ currentTime: TimeInterval) { if entityManager.entities.count != 0 { entityManager.getBackground()!.update(deltaTime: currentTime) - entityManager.getButtonByName(buttonName: "startGameButton").component(ofType: ButtonComponent.self)?.buttonNode.isEnabled = GameCenterHelper.isAuthenticated + entityManager.getButtonByName(buttonName: "startGameButton").component(ofType: ButtonComponent.self)?.buttonNode.isEnabled = GameCenterManager.isAuthenticated } + + if GameCenterManager.sharedInstance.initIsFinish { + self.loadScene(scene: GameCenterManager.sharedInstance.gameScene!) + } + } }