[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)}
Post
Replies
Boosts
Views
Activity
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.
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!
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?
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)	{
				// Accepting invitation from an already open GKMatchmakerViewController
if matchmakerViewController != nil {
matchmakerViewController!.dismiss(animated: false, completion: nil)
self.matchmakerViewController!.matchmakerDelegate = nil
self.matchmakerViewController = nil
}
				// Giving the system time to do a full "clean-up" of matchmakerViewController before starting new task
let delayTime = DispatchTime.now() + .milliseconds(2000)
				// 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.
No worries. Please feel free to upvote my response if it works. Cheers.
That should work with any kind of app. It is only a matter where you call authenticatePlayer() and assign the delegate: in didMove(view:) or viewDidLoad() or whatever SwiftUI initial method is (I am old school).
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
				// In your delegate, implement method `didChangeAuthStatus`, for example to enable a Game Center button
				self.delegate?.didChangeAuthStatus(isAuthenticated: GKLocalPlayer.local.isAuthenticated)
				// This is called if the local player gets authenticated. Nothing happens, GKLocalPlayer gets registered
				if GKLocalPlayer.local.isAuthenticated {
GKLocalPlayer.local.register(self)
}
// This is called, when a player opens your app and he|she is not authenticated.
				 // It opens a viewController with sign-in info
				else if let vc = gcAuthVC {
self.delegate?.presentGameCenterAuth(viewController: vc)
}
				// Handing an error while authenticating
				else {
print(">>>>> Error authenticating the Player! \(error?.localizedDescription ?? "none") <<<<<")
				}
}
So, in your GameScene class you may have something like:
override func didMove(to view: SKView) {
		 GameCenterHelper.sharedInstance.delegate = self
GameCenterManager.sharedInstance.authenticatePlayer()
}
@objc func didChangeAuthStatus(isAuthenticated: Bool) {
... For example, stop spinning activity indicator
	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)
}
		
		/** Present the view controller with the Sign-in info */
		func presentGameCenterAuth(viewController: UIViewController?) {
guard let vc = viewController else {return}
self.view!.window?.rootViewController?.present(vc, animated: true)
}
Hi. I ran into the same problem. Did you happen to find the solution? Thanks!
Please disregard. I cannot find an option to delete the post.
The problem has not been solved in Xcode 12.1.
Finally, I have figured it out. In Settings -> iTunes&App Stores, the Sandbox Account included my normal email address. This also had to be changed to the Sandbox account.
if !node2.intersects(node1)
Thanks, bg2b. Interesting approach. Is there more information on how to use a custom shader to blur the background that you could recommend?Cheers.
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 <= node2TopY && node1TopY >= node2BottomY ) || ( node1TopY >= node2BottomY && node1BottomY <= node2TopY )
{
intersectsHeight = true
}
// Node 1 intersects WIDTH of Node 2
if ( node1LeftX <=node2RightX && node1RightX >= node2LeftX ) || ( node1RightX >= node2LeftX && node1LeftX <= node2RightX )
{
intersectsWidth = true
}
// If Node1 intersects both height and width of Node 2, it is completely withoin its boundaries:
if intersectsHeight == true && 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))