Post

Replies

Boosts

Views

Activity

Reply to Fragment large size data sent and received using NSKeyedArchiver.archivedData in GameCenter
[quote='796608022, DTS Engineer, /thread/759890?answerId=796608022#796608022'] Finally, how is MCPeerID coming into this? I thought you were using GameKit? [/quote] Actually, I am using both GameKit and MCSession. Trying to play with fragmenting the data, as you prompted. Although it is more or less clear how to send data: func sendData(dictionaryWithData dictionary: Dictionary<String, Any>, toPeer targetPeers: [MCPeerID]) { do { let dataToSend = try NSKeyedArchiver.archivedData(withRootObject: dictionary, requiringSecureCoding: true) let fragments = fragmentsForMessage(dataToSend, messageID: 0xa1a2a3a4, maxMessageBytesInFragment: 50000) for fragment in fragments { try session.send(fragment, toPeers: targetPeers, with: MCSessionSendDataMode.reliable) } } catch { } } ... I am frankly a bit stuck as to how to handle it in func session(_ session: MCSession,didReceive data: Data,fromPeer peerID: MCPeerID) { DispatchQueue.main.async { do { .... Append data to a property and then at some point implement NSDictionary.unsecureUnarchived? How to know when to implement? When reading the data, I am also getting errors Error:Error Domain=NSCocoaErrorDomain Code=4864 "*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0xffffffa1, 0xffffffa2, 0xffffffa3, 0xffffffa4, 0x0, 0x0, 0x0, 0x6)" UserInfo={NSDebugDescription=*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0xffffffa1, 0xffffffa2, 0xffffffa3, 0xffffffa4, 0x0, 0x0, 0x0, 0x6)}
Jul ’24
Reply to Fragment large size data sent and received using NSKeyedArchiver.archivedData in GameCenter
Thank you so much. I also did notice that the size is unreasonably large. For example, an array of 52 elements of a custom object Card with the following init methods takes about 70KB: required init?(coder aDecoder: NSCoder) { self.suit = Suit(rawValue: aDecoder.decodeInteger(forKey: "suit"))! // (custom enum) self.rank = Rank(rawValue: aDecoder.decodeInteger(forKey: "rank"))! // (custom enum) self.positionX = CGFloat (aDecoder.decodeDouble(forKey: "positionX")) self.positionY = CGFloat (aDecoder.decodeDouble(forKey: "positionY")) self.frontTexture = aDecoder.decodeInteger(forKey: "frontTexture") self.backTexture = SKTexture(imageNamed: "card_back") self.faceUp = aDecoder.decodeBool(forKey: "faceUp") self.possession = aDecoder.decodeObject(forKey: "possession") as! String self.possessionPrevious = aDecoder.decodeObject(forKey: "possessionPrevious") as! String self.notDumpable = aDecoder.decodeBool(forKey: "notDumpable") self.intersectsDeck = aDecoder.decodeInteger(forKey: "intersectsDeck") super.init(coder: aDecoder) } override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) aCoder.encode(suit.rawValue, forKey: "suit") aCoder.encode(rank.rawValue, forKey: "rank") aCoder.encode(Double(positionX), forKey: "positionX") aCoder.encode(Double(positionY), forKey: "positionY") aCoder.encode(frontTexture, forKey: "frontTexture") aCoder.encode(faceUp, forKey: "faceUp") aCoder.encode(possession, forKey: "possession") aCoder.encode(possessionPrevious, forKey: "possessionPrevious") aCoder.encode(notDumpable, forKey: "notDumpable") aCoder.encode(intersectsDeck, forKey: "intersectsDeck") } So, I did consider sending data using property list encoding and decoding. However, I read that it is not possible to use it to encode/decode Dictionary [String:Any], which I need to send (e.g., https://stackoverflow.com/questions/53585848/swift-encode-and-decode-a-dictionary-stringany-into-plist). Is this true? Another option may be to use JSONSerialization, but I am not sure whether it is significantly smaller than NSKeyedArchiver.
Jul ’24
Reply to GKVoiceChat not working
I have faced exactly the same problem. Interestingly enough, voice chat works well on my iPhone and iPad Pro running iOS 14, but not on my old iPad running iOS 12.4.9. I get exactly the same errors as in the previous posts. Access to mic is enabled in Settings, voice chat is initiated but no sound. I have another issue with GameCenter voice chat on my son's iPad. But there, initiating voice chat with name after finding a game results in a nil GKVoiceChat object and I do not even see permission to access mic for my application. I wonder if this could be caused by some parental restrictions. Please advise if you have solved the problem. Thanks!
Dec ’20
Reply to Authenticate game Center
Which code? Method authenicatePlayer()? For this, you need to have a separate class that will handle all you GameKit methods. Google "raywenderlich gamecenter tutorials" (a tutorial on building a turn-based game has code in Swift). Or where to call GameCenterHelper.sharedInstance.authenticatePlayer?
Dec ’20
Reply to GKMatchDelegate inviteDelegate?
I tend to receive this error when a player accepts an invitation, this acceptance is passed to the inviting player, however the player who accepted it fails matchmaking with an error. As a result, the inviting player starts a match without the invited player. I followed up with the Apple's technical support and with their help, rewrote the following method: func player(_ player: GKPlayer, didAccept invite: GKInvite)&#9;{ &#9;&#9;&#9;&#9;// Accepting invitation from an already open GKMatchmakerViewController         if matchmakerViewController != nil {             matchmakerViewController!.dismiss(animated: false, completion: nil)             self.matchmakerViewController!.matchmakerDelegate = nil             self.matchmakerViewController = nil         } &#9;&#9;&#9;&#9;// Giving the system time to do a full "clean-up" of matchmakerViewController before starting new task         let delayTime = DispatchTime.now() + .milliseconds(2000) &#9;&#9;&#9;&#9;// Initiating matchmaking VC on the main thread after the delay         DispatchQueue.main.asyncAfter(deadline: delayTime) {             self.matchmakerViewController = GKMatchmakerViewController(invite: invite)             self.matchmakerViewController!.matchmakerDelegate = self             self.delegate?.presentMatchmaking(viewController: self.matchmakerViewController!)         } } I am testing it now and will report if successful. If this helps solve your issues, please let me know. Cheers.
Dec ’20
Reply to Authenticate game Center
You can authenticate by using a method along the following lines (in the GameCenterHelp that will be a singleton): func authenticatePlayer() {         GKLocalPlayer.local.authenticateHandler = { gcAuthVC, error in             &#9;&#9;&#9;&#9;// In your delegate, implement method `didChangeAuthStatus`, for example to enable a Game Center button &#9;&#9;&#9;&#9;self.delegate?.didChangeAuthStatus(isAuthenticated: GKLocalPlayer.local.isAuthenticated) &#9;&#9;&#9;&#9;// This is called if the local player gets authenticated. Nothing happens, GKLocalPlayer gets registered &#9;&#9;&#9;&#9;if GKLocalPlayer.local.isAuthenticated {                 GKLocalPlayer.local.register(self)         }          // This is called, when a player opens your app and he|she is not authenticated. &#9;&#9;&#9;&#9; // It opens a viewController with sign-in info &#9;&#9;&#9;&#9;else if let vc = gcAuthVC {                 self.delegate?.presentGameCenterAuth(viewController: vc)         } &#9;&#9;&#9;&#9;// Handing an error while authenticating &#9;&#9;&#9;&#9;else {                 print(">>>>> Error authenticating the Player! \(error?.localizedDescription ?? "none") <<<<<") &#9;&#9;&#9;&#9;} } So, in your GameScene class you may have something like: override func didMove(to view: SKView) { &#9;&#9; GameCenterHelper.sharedInstance.delegate = self      GameCenterManager.sharedInstance.authenticatePlayer()  } @objc func didChangeAuthStatus(isAuthenticated: Bool) {        ... For example, stop spinning activity indicator      &#9;if indicator != nil {             indicator!.stop()             indicator!.removeFromSuperview()             indicator = nil         }         ... Or enable the *PLAY ON GAMECENTER* button         if GKLocalPlayer.local.isAuthenticated {             btnPlayGameCenter.setButtonLabel(title: btnPlayGameCenterTitle(), font: "Noteworthy-Bold", fontSize: 40) } &#9;&#9; &#9;&#9;/** Present the view controller with the Sign-in info */ &#9;&#9;func presentGameCenterAuth(viewController: UIViewController?) {         guard let vc = viewController else {return}         self.view!.window?.rootViewController?.present(vc, animated: true)  }
Dec ’20
Reply to know that skspritenode has completely moved over another skspritenode
What do you mean by "iterated"? If I understand your subject correctly... This can be used when node 1 is just partially within the boundary of the second node:if node1.intersects(node2) { }If you want to know, whether your first node is entirely within the boundaries of the second node, this should work:// Node 1 intersects HEIGHT of Node2 if ( node1BottomY &lt;= node2TopY &amp;&amp; node1TopY &gt;= node2BottomY ) || ( node1TopY &gt;= node2BottomY &amp;&amp; node1BottomY &lt;= node2TopY ) { intersectsHeight = true } // Node 1 intersects WIDTH of Node 2 if ( node1LeftX &lt;=node2RightX &amp;&amp; node1RightX &gt;= node2LeftX ) || ( node1RightX &gt;= node2LeftX &amp;&amp; node1LeftX &lt;= node2RightX ) { intersectsWidth = true } // If Node1 intersects both height and width of Node 2, it is completely withoin its boundaries: if intersectsHeight == true &amp;&amp; intersectsWidth == true { }This is how you may check if half of the first node intesects the second node:if node2.contains(CGPoint(x: node1.frame.midX, y: node1.frame.midY))
Feb ’20