Team Matchmaking

Introduction

In this guide we’ll be using the GameSparks matchmaking system to search for matches that can accommodate parties of a specific size on one of two teams in a match. A typical example of this type of Team or Party Matchmaking is where you want Matches to be found only for a 2v2 four-player Match.

Creating the Match Configuration

Let’s create our Match configuration for testing this scenario. Here's the configuration settings we're going to use:

For Thresholds we’ll use the following settings:

For the Custom Script we’ll be using the following snippet. Please review the code comments included here to understand how the script operates to adjust the Pending Match as players leave or join and achieves the desired Team Match goal:

// Obtain player and match data from the pending match and set up default team values
var players = pendingMatch.getPlayersDetails();
var existingMatchData = pendingMatch.getMatchData();
if(!existingMatchData.TeamA) existingMatchData.TeamA = [];
if(!existingMatchData.TeamB) existingMatchData.TeamB = [];

// Build an array of playerIds covering all players currently in the match
var allPlayers = [];
for(var i = 0, l=players.length; i<l; ++i){
    allPlayers.push(players[i].getPlayerId());
}

// Build an array of playerIds covering all players already assigned to a team.
currentTeamPlayers = existingMatchData.TeamA.concat(existingMatchData.TeamB);

// if the number of players currently in the match is less than the number of players assigned to teams it would mean that this script has been triggered
// in response to a player or players leaving the match. In this case we need to identify which team they were part of and remove them from it.
if(allPlayers.length < currentTeamPlayers.length){
    // Identify the player or players that are present in a team, but no longer in a match
    var extraPlayer = currentTeamPlayers.filter(function(el){if(this.indexOf(el) == -1)return el}, allPlayers);
    // Figure out which team each of these players is in and remove them from it
    for(var i in extraPlayer){
        var index = existingMatchData.TeamA.indexOf(extraPlayer[i]);
        if(index >= 0){
            existingMatchData.TeamA.splice(index, 1);
        }
        else{
            index = existingMatchData.TeamB.indexOf(extraPlayer[i]);
            if(index >= 0){
                existingMatchData.TeamB.splice(index, 1);  
            }
        }
    }
}
// If there are more players in the match than are assigned to teams it means the script was triggered in response to a player or players joining a match. Here we want to
// decide which match they should be added to, and add them
else if(allPlayers.length > currentTeamPlayers.length){
    //If TeamA is empty, add all match players which aren't already in TeamB to TeamA
    if(existingMatchData.TeamA.length===0){
        existingMatchData.TeamA = allPlayers.filter(function(el){if(this.indexOf(el) == -1)return el}, existingMatchData.TeamB);
    }
    //If TeamB is empty, add all match players which aren't already in TeamA to TeamB
    else if(existingMatchData.TeamB.length===0 && allPlayers.length > existingMatchData.TeamA.length){
        existingMatchData.TeamB = allPlayers.filter(function(el){if(this.indexOf(el) == -1)return el}, existingMatchData.TeamA);
    }
    // Identify which players are new (that is, which players haven't yet been assigned to a team), then add them to the smaller team
    else{
        var newPlayers = allPlayers.filter(function(el){if(this.indexOf(el) == -1)return el}, currentTeamPlayers);
        if(existingMatchData.TeamA.length <= existingMatchData.TeamB.length && existingMatchData.maxTeamSize >= existingMatchData.TeamA.length+newPlayers.length){
            existingMatchData.TeamA = existingMatchData.TeamA.concat(newPlayers);
        }
        else if(existingMatchData.maxTeamSize >= existingMatchData.TeamB.length+newPlayers.length){
            existingMatchData.TeamB = existingMatchData.TeamB.concat(newPlayers);
        }
    }
}

// Determine the maximum party size that this match will allow to be added (represents the number of player slots left on the smaller of the two teams)
if(existingMatchData.TeamA.length <= existingMatchData.TeamB.length){    
    existingMatchData.maxPartySize = existingMatchData.maxTeamSize-existingMatchData.TeamA.length;
}
else  {                                                                  
    existingMatchData.maxPartySize = existingMatchData.maxTeamSize-existingMatchData.TeamB.length;
}

// Apply the updated data to the pending match.
pendingMatch.setMatchData(existingMatchData);

NOTE: This custom script covers a two-team match scenario. It can be adapted to handle more teams where required.

Setting up a Matchmaking Event

Next, let’s configure an Event that will handle the matchmaking for our party of players. This Event will let you specify the Ids of the players you would like to include in your party or team.

1. In the portal, navigate to Configurator>Events and click to Add a new Event. We’ll use the following settings:

2. For Attributes, click to Add an Attribute and set it up as follows:

3. Navigate to the Configurator>Cloud Code tab in the portal and open the script for this Event. We’ll add our custom code here:


//grab the array we will be passing in through the request
var partyMembers = Spark.getData().userIds

//create an array and set the current sparkplayer object to it by default
var partyMemberPlayerObject = [Spark.getPlayer()];

//get the sparkplayer objects from the passed in ids and push them to the array
for (i = 0; i < partyMembers.length; i++) {
  partyMemberPlayerObject.push(Spark.loadPlayer(partyMembers[i]));
}

//start the matchmaking process for the party
var partyMatch = Spark.getConfig().getMatchConfig("partyMatch").createPendingMatchWithCustomQuery("partyTest", 2, {"matchData.maxPartySize":{"$gte": partyMemberPlayerObject.length}}, {"maxTeamSize":2}, partyMemberPlayerObject)

Testing the Setup

To test our set up lets open 4 test harness windows.

In the first window we’ll register p1:


{
  "@class": ".RegistrationRequest",
  "displayName": "p1",
  "password": "",
  "userName": "p1"
}

In the second window we’ll register p2:


{
  "@class": ".RegistrationRequest",
  "displayName": "p2",
  "password": "",
  "userName": "p2"
}

In the third window we’ll register p3:


{
  "@class": ".RegistrationRequest",
  "displayName": "p3",
  "password": "",
  "userName": "p3"
}

In the fourth window we’ll register p4:


{
  "@class": ".RegistrationRequest",
  "displayName": "p4",
  "password": "",
  "userName": "p4"
}

We now have 4 players created and authenticated. We are ready to proceed with our tests.

Test 1 - Team Match is Achieved

1. Back in window one, we can send the MatchmakingRequest for p1 as follows to create the pendingMatch:


{
  "@class": ".MatchmakingRequest",
  "matchData": {
    "maxTeamSize": 2
  },
  "matchGroup": "partyTest",
  "matchShortCode": "partyMatch",
  "skill": 2
}

At this point:

2. In window two, we can send the custom partyMatch LogEventRequest as p2. We are passing in the id of p3 so these players (p1, p2, and p3) will be matched together as far as player skill level is concerned - all have skill level of 2:


{
  "@class": ".LogEventRequest",
  "eventKey": "partyMatch",
  "userIds": ["5a5df7417eebc060c16bab0a"]
}

At this point:

3. Now let’s send the MatchmakingRequest as p4 and see what happens:


{
  "@class": ".MatchmakingRequest",
  "matchGroup": "partyTest",
  "matchShortCode": "partyMatch",
  "skill": 2
}

At this point:

Test 2 - Team Match is Not Achieved

To re-test this flow in a scenario where the party containing p2 & p3 won’t be able to join a match you can perform the following steps:

1. Send the MatchmakingRequest as p1.

2. Send the MatchmakingRequest as p4.

At this point:

3. Now send the partyMatch LogEventRequest as p3:

{
  "@class": ".LogEventRequest",
  "eventKey": "partyMatch",
  "userIds": ["5a5df7417eebc060c16bab0a"]
}

Because there isn’t a match available that can accommodate the team containing players p3 & p2, these users will receive a MatchNotFoundMessage.


NOTE: The above example uses the ids of 4 unrelated players that we have registered. To apply it to your friends, you can simply get the current players friends with the SparkPlayer getFriendIds call or by sending the ListGameFriendsRequest.

Cancelling a MatchMakingRequest

To cancel matchmaking for all players (for additional testing) simply send the MatchmakingRequest with the “action” parameter set to “cancel” for each of our players:


{
  "@class": ".MatchmakingRequest",
  "action": "cancel”
  "matchGroup": "partyTest",
  "matchShortCode": "partyMatch",
  "skill": 2
}

Did this page help you? Please enter your feedback below. For questions about using this part of the platform, please contact support here