* create new GameCenterManager

* send RandomNumber to all Peers Method
This commit is contained in:
Niko Jochim 2020-05-27 20:41:05 +00:00 committed by Marcel Schwarz
parent 23707cb1d9
commit 9329978981
14 changed files with 267 additions and 333 deletions

View File

@ -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 = "<group>"; };
3E6785412472CBEC007B9DE4 /* Way.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Way.swift; sourceTree = "<group>"; };
3E6785432472CC27007B9DE4 /* DefaultWayComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultWayComponent.swift; sourceTree = "<group>"; };
3EBD242B245D8044003CECE7 /* GameCenterHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameCenterHelper.swift; sourceTree = "<group>"; };
3EBD242D245D9332003CECE7 /* Team.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Team.swift; sourceTree = "<group>"; };
3F745DEF246F48FC00CE7375 /* PlayerMoveType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerMoveType.swift; sourceTree = "<group>"; };
3FE19DB4246C7A22004827AB /* RoundCalculatorService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundCalculatorService.swift; sourceTree = "<group>"; };
8BB6FF3F2472B8F000162BBD /* SingeClickButtonNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingeClickButtonNode.swift; sourceTree = "<group>"; };
9E04AFAE245E2B73002D5CFC /* AttackActionComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttackActionComponent.swift; sourceTree = "<group>"; };
9E0E459624796262009817A6 /* GameCenterManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameCenterManager.swift; sourceTree = "<group>"; };
9E11FF77245CD81100EED3BE /* Fire.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Fire.sks; sourceTree = "<group>"; };
9E174C81245DD81D00209FF0 /* ButtonNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ButtonNode.swift; sourceTree = "<group>"; };
9E174C83245DD8CE00209FF0 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = "<group>"; };
@ -118,10 +117,9 @@
AB1D759F245DEC0500671525 /* MapFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapFactory.swift; sourceTree = "<group>"; };
AB21D7D4246C748A00B09CBA /* TwoPlayerMapGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoPlayerMapGenerator.swift; sourceTree = "<group>"; };
ABA03D9F244BD54F00A66916 /* Base.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Base.swift; sourceTree = "<group>"; };
ABB8A40D247B195500B901BE /* SliderComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SliderComponent.swift; sourceTree = "<group>"; };
AE151588245F18EF001D363E /* MatchmakingHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatchmakingHelper.swift; sourceTree = "<group>"; };
C04783ED2468583F004961FB /* intro-music.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = "intro-music.mp3"; sourceTree = "<group>"; };
C04783EF24685995004961FB /* SettingsScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScene.swift; sourceTree = "<group>"; };
C05BB9C3247D890C00411249 /* SliderComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SliderComponent.swift; sourceTree = "<group>"; };
C05FAED52468559D0006AF2E /* SoundManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoundManager.swift; sourceTree = "<group>"; };
C064E9A7246C0EA50022B228 /* LabelNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelNode.swift; sourceTree = "<group>"; };
C064E9A9246C114C0022B228 /* LabelComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelComponent.swift; sourceTree = "<group>"; };
@ -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 */,

View File

@ -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)

View File

@ -61,7 +61,7 @@ class TimerComponent: GKComponent {
}
if !RoundCalculatorService.sharedInstance.isCalculating
&& DataService.sharedInstance.didReceiveAllData()
&& MatchmakingHelper.sharedInstance.isServer {
&& GameCenterManager.sharedInstance.isServer {
RoundCalculatorService.sharedInstance.calculateRound()
}
}

View File

@ -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,11 +58,7 @@ class DataService {
}
func didReceiveAllData() -> Bool {
return remotePlayerMoves.count == MatchmakingHelper.sharedInstance.mpMatch?.players.count
}
func setGameHost(host: Host) {
self.gameHost = host
return remotePlayerMoves.count == GameCenterManager.sharedInstance.myMatch?.players.count
}
func setSnapshotModel(snapshotModel: SnapshotModel) {

View File

@ -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)
}

View File

@ -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")
}

View File

@ -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")
}

View File

@ -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
}

View File

@ -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
)

View File

@ -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
)

View File

@ -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()
}
}
}

View File

@ -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))!

View File

@ -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)
}

View File

@ -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!)
}
}
}