diff --git a/Better Together/Better Together/GameViews/GameViewController.swift b/Better Together/Better Together/GameViews/GameViewController.swift index a345e5ec46df8078ac0132fc600c3fe878e872cf..777268fb3eef9c5e9cbf9ee93f4420394bbab19c 100644 --- a/Better Together/Better Together/GameViews/GameViewController.swift +++ b/Better Together/Better Together/GameViews/GameViewController.swift @@ -281,7 +281,7 @@ class GameViewController: UIViewController, LocalTeamPlayDelegate { LocalTeamPlayManager.sharedInstance.sendToAll(sessionAction: SessionAction.setup(SetupAction.selectedLevel(selectedLevel)), isReliable: true) // Update the progress Counter spinnerView.currentState = .sendingLevels - progressCounter = LocalTeamPlayManager.sharedInstance.allPlayersPeerIDs!.count * 2 // Two number of messages exchanged in the setup process + progressCounter = LocalTeamPlayManager.sharedInstance.allPlayersPeerIDs!.count * 2 // Is number of messages exchanged in the setup process, if this state is reached. 2 messages exchanged for each player. spinnerView.updateProgress(progressCount: progressCounter) } } @@ -307,7 +307,7 @@ class GameViewController: UIViewController, LocalTeamPlayDelegate { // Upadte the progress view. self.spinnerView.currentState = .sendingPlayerInfo - self.progressCounter = LocalTeamPlayManager.sharedInstance.allPlayersPeerIDs!.count * 4 + self.progressCounter = LocalTeamPlayManager.sharedInstance.allPlayersPeerIDs!.count * 4 // Is number of messages exchanged in the setup process, if this state is reached. 4 messages exchanged for each player. self.spinnerView.updateProgress(progressCount: self.progressCounter) } } diff --git a/Better Together/Better Together/Mutiplayer/LocalTeamPlayManager.swift b/Better Together/Better Together/Mutiplayer/LocalTeamPlayManager.swift index 62d9ea909b6d4a8c2909429b139406ce8d3a1199..eb47d51ceab4081ec8a941dbc61c1af34a885782 100644 --- a/Better Together/Better Together/Mutiplayer/LocalTeamPlayManager.swift +++ b/Better Together/Better Together/Mutiplayer/LocalTeamPlayManager.swift @@ -59,19 +59,19 @@ class LocalTeamPlayManager: NSObject, MCNearbyServiceAdvertiserDelegate, MCBrows let action = try decoder.decode(SessionAction.self, from: data) switch action { case .setup(.selectedLevel(let level)): - DispatchQueue.main.async{ NotificationCenter.default.post(name: .levelSelectedFromHost, object: nil, userInfo: ["level": level]) } + NotificationCenter.default.post(name: .levelSelectedFromHost, object: nil, userInfo: ["level": level]) case .setup(.responseForLevelSetting( _)): - DispatchQueue.main.async{ self.delegate?.receivedLevelConfirmation(for: peerID) } + self.delegate?.receivedLevelConfirmation(for: peerID) case .setup(.syncCharacterIndexForGameScene(let playersInfo)): - DispatchQueue.main.async{ self.delegate?.syncCharacterIndexForGameScene(playersInfo: playersInfo) } + self.delegate?.syncCharacterIndexForGameScene(playersInfo: playersInfo) case .setup(.responseForCharacterInfoSyncDone(let done)): - DispatchQueue.main.async{ self.delegate?.playerSyncDoneReceived(for: peerID, isDone: done) } + self.delegate?.playerSyncDoneReceived(for: peerID, isDone: done) case .setup(.startGame(let start)): - DispatchQueue.main.async{ NotificationCenter.default.post(name: .startGame, object: nil, userInfo: ["playerInfoSync": start]) } + NotificationCenter.default.post(name: .startGame, object: nil, userInfo: ["playerInfoSync": start]) case .setup(.gameOver(_)): NotificationCenter.default.post(name: .gameResultReceived, object: nil, userInfo: ["result": "fail"]) case .setup(.gameSceneLoaded(let isReady)): - DispatchQueue.main.async{ self.delegate?.playersGameSceneLoadStateReceived(for: peerID, isReady: isReady)} + self.delegate?.playersGameSceneLoadStateReceived(for: peerID, isReady: isReady) case .setup(.gameSuccess(_)): NotificationCenter.default.post(name: .gameResultReceived, object: nil, userInfo: ["result": "success"]) case .gamePhysics(let characterActionData): @@ -79,15 +79,11 @@ class LocalTeamPlayManager: NSObject, MCNearbyServiceAdvertiserDelegate, MCBrows case .syncAllCharacters(let syncData): delegate?.allChracterActionsReceived(charactersActions: syncData.data) case .setup(.clientsConfiguration(let config)): - DispatchQueue.main.async{ let index = self.allPlayersPeerIDs!.firstIndex(of: peerID)! CharacterManager.sharedInstance.addNewConfigurationServer(config: config, for: peerID, for: index) self.delegate?.receivedNewCustomization(config: config, for: peerID) - } case .setup(.dismissedInvitation(let value)): - DispatchQueue.main.async { NotificationCenter.default.post(name: .dimissedInvitationBrowserClient , object: nil, userInfo: ["value": value]) - } } } catch { debugPrint("receive - decoding error: \(error)") diff --git a/Better Together/Better Together/UIViews/CharacterManager.swift b/Better Together/Better Together/UIViews/CharacterManager.swift index 8e62aad271a77ed619810176889ba88275e23dc8..4cfb085733dd6b447fa508516be7d7e7f29513ec 100644 --- a/Better Together/Better Together/UIViews/CharacterManager.swift +++ b/Better Together/Better Together/UIViews/CharacterManager.swift @@ -23,9 +23,15 @@ class CharacterManager { private static let nintyDegrees: Float = 1.5708 static let sharedInstance: CharacterManager = CharacterManager() - // Contains the configuration of all other players. - var allPlayersConfiguration = [(MCPeerID, [String], Int)]() // Used on server side (PeerID, Configuration, Index of Config Arrival) - var allOtherConfigurations = [[String]]()// used on client side + // Contains the configuration of all other players, without the servers one. + // Use getConfigurationForServer() to get all players configurations including the servers ones. + // Used on server side (PeerID, Configuration, Index of Config Arrival) + var allPlayersConfiguration = [(MCPeerID, [String], Int)]() + + // used on client side, to save the configuration of all players. + var allOtherConfigurations = [[String]]() + + // the preloaded textures, both client and server use the same array to store textures. var preloadedTextures = [SKTexture]() @@ -58,6 +64,8 @@ class CharacterManager { return [body, arm, hand] } + + /// Return the image index of my configuration images. func getMyConfigAsIndex() -> [Int]? { guard let body = UserDefaults.standard.value(forKey: bodyKey) as? String else { return nil } guard let arm = UserDefaults.standard.value(forKey: armKey) as? String else { return nil } @@ -70,9 +78,13 @@ class CharacterManager { return nil } + private static let numberOfBodyParts = 9 + /// Returns the images for a complete customization (whihc consist of 9 Strings, one image name for each body part) + /// - Parameter customizationKey: The image names of a customization + /// - Returns: The translated images static func getCustomization(from customizationKey: [String]?) -> [UIImage]? { guard customizationKey != nil else { return nil } - guard customizationKey!.count == 9 else { return nil } + guard customizationKey!.count == numberOfBodyParts else { return nil } let _imageName7 = customizationKey![7].replacingOccurrences(of: "BTHandsImages", with: "BTHandsImagesClosed") let _imageName8 = customizationKey![8].replacingOccurrences(of: "BTHandsImages", with: "BTHandsRightImagesClosed") @@ -120,41 +132,45 @@ class CharacterManager { return [Body, LeftUpperArm, LeftLowerArm, LeftHand, RightUpperArm, RightLowerArm, RightHand, LeftHandClosed, RightHandClosed] } + /// Constructs the howl customization of images from a basic configuration, which contains the 3 (body,arm,hands) image names. static func getImages(for config: [String]?) -> [UIImage]? { return getCustomization(from: getCompleteCustomization(for: config)) } + /// Preload the textures for host side. Stored in preloadedTextures. func preloadConfigurationTexturesServer(completion: @escaping () -> Void) { let allConfigs = getConfigurationForServer() - for config in allConfigs { + for config in allConfigs { // Iterate through all characters configurations. guard let allTextureNames = CharacterManager.getCompleteCustomization(for: config) else { return } for i in 0 ..< allTextureNames.count { - var name = allTextureNames[i] + var textureName = allTextureNames[i] // Image name for one bodypart texture. switch i { case 4: - if let index = name.last?.wholeNumberValue, [2,3].contains(index) { - name = CharacterManager.flippedArms[index - 2] + if let index = textureName.last?.wholeNumberValue, [2,3].contains(index) { + textureName = CharacterManager.flippedArms[index - 2] } case 5: - if let index = name.last?.wholeNumberValue, [2,3].contains(index) { - name = CharacterManager.flippedArms[index - 2] + if let index = textureName.last?.wholeNumberValue, [2,3].contains(index) { + textureName = CharacterManager.flippedArms[index - 2] } - case 6: name = name.replacingOccurrences(of: "BTHandsImages", with: "BTHandsRightImages") - case 7: name = name.replacingOccurrences(of: "BTHandsImages", with: "BTHandsImagesClosed") - case 8: name = name.replacingOccurrences(of: "BTHandsImages", with: "BTHandsRightImagesClosed") + case 6: textureName = textureName.replacingOccurrences(of: "BTHandsImages", with: "BTHandsRightImages") + case 7: textureName = textureName.replacingOccurrences(of: "BTHandsImages", with: "BTHandsImagesClosed") + case 8: textureName = textureName.replacingOccurrences(of: "BTHandsImages", with: "BTHandsRightImagesClosed") default: break } + // Flip arms when using the bodybuilding texture. if allTextureNames[2] == CharacterManager.arms[2] && i == 2 { - name = CharacterManager.arms[6] + textureName = CharacterManager.arms[6] } else if allTextureNames[2] == CharacterManager.arms[2] && i == 5 { - name = CharacterManager.flippedArms[2] + textureName = CharacterManager.flippedArms[2] } - preloadedTextures.append(SKTexture(imageNamed: name)) + preloadedTextures.append(SKTexture(imageNamed: textureName)) } } SKTexture.preload(preloadedTextures, withCompletionHandler: completion) } + /// Preload the textures for client side. Stored in preloadedTextures. func preloadConfigurationTextureClient(completion: @escaping () -> Void) { for config in allOtherConfigurations { guard let completeConfiguration = CharacterManager.getCompleteCustomization(for: config) else { return } @@ -185,12 +201,18 @@ class CharacterManager { SKTexture.preload(preloadedTextures, withCompletionHandler: completion) } + + /// Adds a newly received configuration of remote players. + /// - Parameters: + /// - config: the configuration of the remote player + /// - player: the player MCPeerID + /// - index: the index for order arrival in which the player accepted the invitation. func addNewConfigurationServer(config: [String], for player: MCPeerID, for index: Int) { guard config.count == 3 else { return } allPlayersConfiguration.append((player, config, index + 1)) } - // Give server character configurations in correct order. + // Gives server character configurations of remote players in correct order, including his own configuratoin. func getConfigurationForServer() -> [[String]] { var allConfigurations = [(MCPeerID,[String],Int)].init(repeating: (MCPeerID(displayName: "Dummy"),[String](), 0), count: allPlayersConfiguration.count + 1) // +1 because of server himself, which gets added in setp 2.