How to prevent 2 players from joining a match together?

PLEASE HELP. I found a big problem :>(


I just discovered a real big problem with my game logic involving how players are joined together into a match and I am hoping someone can help me resolve it


Requirements for my application

A player can either HOST a match or FIND a match to join.

(Note: The HOST player sets all of the game options such as number of players, number of rounds, number of cards, etc..)

  • Every match created must have only "one" HOST player only
  • All players who request to FIND a match (ie: non-host players) must ONLY join a match which is being hosted and not have a match created between themselves, which does not include a host.


Example:

Player1 is hosting a 2-player match and is actively searching for one more player to join the match. At this time, two separate players (non-host players) each make separate requests to FIND a random match to join. Sometimes, I see a match is created between the two non-host players, while the HOST player keeps spinning looking for a player to join.


Question:

How can I ensure all non-host players only join a match which is being hosted, instead of creating a match between themselves?



My existing application match logic:


1) When a player requests to HOST a match (eg: 2-player match) then the following match request is made, which will result in the GKMatchmakerViewController window being displayed so players can be located to fill the match slots:


let request = GKMatchRequest.init( )

request.minPlayers = 2

request.maxPlayers = 2

request.playerAttributes = 0xFFFF0000 <-- represents HOST player (see note below)

let mmvc = GKMatchmakerViewController.init(matchRequest: request)


Note: The 0xFFFF0000 playerAttribute value ensures multiple HOST players, who are actively searching for players for their match, are not joined together into the same match. Basically, if the match already has a player with attribute 0xFFFF0000, then another player with attirbute 0xFFFF0000 cannot also join the same match.



2) When a player requests to FIND a match (eg: 2-player match) to join then following the match request is made to programmatically find a match:


let matchRequest = GKMatchRequest.init( )

matchRequest.minPlayers = 2

matchRequest.maxPlayers = 2

matchRequest.playerAttributes = 0 <---indicates player is NOT A HOST and can join any match available

GKMatchmaker.shared().findMatch(for: matchRequest, withCompletionHandler: ...)



In my 2-player non-host "Problem" described above, I understand why the two non-host players create a match between themselves. They are both requesting to find a 2-player match while both have player attributes set to "0". Is there a way to make non-host players only join a game with a HOST player?

Accepted Reply

That's what I wrote. Note that the 'host' has 5 F's and 3 0's in my example.

In the example I cited above, for a 4 player game (one host, 3 players), you don't get to the 4 player minimum without also getting an FFFFFFFF:

host - FFFFF000

player1 0000000F

player 2 000000F0

player 3 00000F00



> I believe as long as the number of players is satisified and the attributes do not overlap then the match will start.


I do not know if this is correct or not. If it is, you would need different masks based on the number of players you accept as a minimum. In my example, for a three player game (host and 2 others) you would add one more F to the Host and the system would reject a 'player3' in such an invite.

Replies

Did we discuss this back a few months ago? My answer then was:




PBKFeb 8, 2020 4:29 PM(

in response to uncletr)


I assume that if the player taps on the notification (rather than swipes it up) they want to accept the invite. I have a different issue, I am concerned that in a two player game in which there is a disconnect both players could try to invite the other player. So I may have the mmvc viewController showing that needs to be dismissed. Here's what I do:




  1. - (void)player:(GKPlayer *)player didAcceptInvite:(GKInvite *)invite{
  2. if(!didAcceptInviteVCShowing){
  3. // NSLog(@"didAcceptInviteVCShowing");
  4. [self acceptThisInvite:invite];
  5. }else{
  6. [[self topController] dismissViewControllerAnimated:YES completion:^{
  7. // NSLog(@"we may have problems here");
  8. [self acceptThisInvite:invite];
  9. }];
  10. }
  11. }
  12. -(void)acceptThisInvite:(GKInvite *)invite{
  13. didAcceptInviteVCShowing=YES;
  14. GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc] initWithInvite:invite];
  15. mmvc.matchmakerDelegate = self;
  16. [[self topController] presentViewController:mmvc animated:YES completion:^{
  17. mmvc.view.frame=CGRectMake(0,mmvc.view.safeAreaInsets.top, mmvc.view.bounds.size.width, mmvc.view.bounds.size.height-mmvc.view.safeAreaInsets.top);
  18. }];
  19. }
  20. //didAcceptInviteVCShowing is set and unset in various places throughout the program to indicate if teh VC is showing

no, this is not the same issue. I am clearly not explaining this issue nicely.


My game allows a player to HOST a match or simply FIND an available match.


When a player HOSTS a match then the player sets all of the game options and then requests a match to be created using player attribute 0xFFFF0000 (meaning "HOST") value. Using this player attribute will ensure no other HOST player can join a match which already has a host player included. Only one HOST player is allowed in a match at once.


When other players want to FIND a match to join only, then I want these other players to only be allowed to join a match which has a HOST player in it. I do not want these other non-host players to be able to join matches together (without a host player being present in the match). Is this possible?

Certainly it is possible. It is exactly what is described here:

https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/GameKit_Guide/MatchmakingwithGameCenter/MatchmakingwithGameCenter.html#//apple_ref/doc/uid/TP40008304-CH12-SW2


See the listing in table 6-3. Your host is 0xFFFF0000 like "White". You want to play with someone with a 0x0000FFFF attribute like "Black". Only when you make a full match of 0xFFFFFFFF will a game start.

Post not yet marked as solved Up vote reply of PBK Down vote reply of PBK

Hey PBK,


Yeah I read this earlier and this would most certainly work for a 2-player game. The player who is not a host would simply use a player attribute of 0x0000FFFF like you stated .


However, my issues are the following:


1) How can I get this to work with 3 or 4 player matches where there should be only one HOST player and up to 3 other players who want to simply join a match only (ie: not be the host)? Each player joining the match would have to randomly select a player attribute of either 0x0000000F, 0x000000F0 or 0x00000F00 to be allowed to join a match together, however, randomly selecting one of these attribute values for each player does not seem like the correct approach since if each player selects the same sttribute value them they will not be joined into a match together.


2) Additonally, how do I ensure all players who simply want to join a game do not form a match by themselves, without a host player even existing? For example, if there are 3 players who are all looking for a 3-player game to join, then I see all 3 of these players are joined into a match by Game Center. This match does not have any HOST player included. So I wanted to know whether there was a way to ensure a player can only join a match which currently has the 0xFFFF0000 (Host attribute) existing.


I do not believe there is a way to resolve (1) or (2) issues above. I think I might have to rework my game logic to support matches which do not have a host included. I would have to select one of the players to be the host automatically and then have that selected host player start the game up themselves with proper options, etc... It is just more work, but not impossible

No match will starts unless there is a FFFFFFFF so all matchs will require at least one FFFF0000 host.


This will work: You want 3 players and a host. Have the Host be FFFFF000. Have each player be one of these, randomly selected by the app, 00000F00 000000F0 0000000F. Then no game can start until there are one of each. That means that there might, on ocasion, be an excess of players waiting to start a match because they randommly chose the wrong 'role'. So what. It only means it takes a few seconds longer to form a match.

I "think" 3 non-host players having separate 00000F00, 000000F0 and 0000000F attributes will still form a 3-player game themselves since none of the attributes overlap. I believe as long as the number of players is satisified and the attributes do not overlap then the match will start.


For my case, I think I would need to do the following and then wait for the right mixture of players to exist which could join with the host player (who has attribute 0xFFFF0000)


For a 2-player game, I would need to assign all non-host players the following attribute:


0x0000FFFF


for a 3-player game, I would need to randomly assign all non-host players one of the following attributes:


0x000000FF

0x0000FF00


For a 4-player game, I would need to randomly assign all non-host players one of the following attributes:


0x000000FF

0x00000F00

0x0000F000

That's what I wrote. Note that the 'host' has 5 F's and 3 0's in my example.

In the example I cited above, for a 4 player game (one host, 3 players), you don't get to the 4 player minimum without also getting an FFFFFFFF:

host - FFFFF000

player1 0000000F

player 2 000000F0

player 3 00000F00



> I believe as long as the number of players is satisified and the attributes do not overlap then the match will start.


I do not know if this is correct or not. If it is, you would need different masks based on the number of players you accept as a minimum. In my example, for a three player game (host and 2 others) you would add one more F to the Host and the system would reject a 'player3' in such an invite.

thanks for confirming