Matchmaking

The Procedure

The way we set up the matchmaking allows for the platform automatically constructing the right Match, based on the players level. When a Match has been found, the platform will automatically issue the correct Challenge, accept it, and initialize it.


Matchmaking Availability? The Matchmaking feature is no longer available to games created on or after February 19th, 2019, or for games created before February 19th, 2019 that had not yet used the feature. If you require Matchmaking for your game and do not have access under your current plan, please contact us to discuss the Enterprise Pricing Tier.

Creating the Match and Challenge Examples

Before we can continue, we need to create a Match and a Challenge. These will be very simple.

The Match:

The Challenge:

Make sure that the Challenge is turn based.

The Match Event

Make a new Event. This simple Event will take one string that represents the Short Code of the Match it's supposed to make. We'll name this Event findMatch and the Cloud Code will be:

//Get shortCode
var matchshortCode = Spark.getData().matchShortCode;

//If shortCode is equal to 'matchRanked' send a matchmakingRequest for a ranked match
if (matchshortCode === "matchRanked"){
    //Create the request
    var matchRequest = new SparkRequests.MatchmakingRequest();

    //Assign shortCode and skill based on player rank
    matchRequest.matchShortCode = matchshortCode;
    matchRequest.skill = Spark.getPlayer().getScriptData("rank");

    //Send request
    matchRequest.Execute();
}
else if(matchshortCode === "casualMatch"){
    //Create the request
    var matchRequest = new SparkRequests.MatchmakingRequest();

    //Assign shortCode and skill as 0 so all players are matched
    matchRequest.matchShortCode = matchshortCode;
    matchRequest.skill = 0;

    //Send request
    matchRequest.Execute();
}

Now, once the Match is found, we need to allow the platform to automatically create a Challenge and accept the players in. We can do this using the MatchFoundMessage under UserMessages on the Scripts panel in the Cloud Code section.

Match Found Message

We'll edit the MatchFoundMessage to contain this:

//If our match is ranked
if (Spark.getData().matchShortCode === "matchRanked")
{
    //If the first participant
    if(Spark.getPlayer().getPlayerId() === Spark.getData().participants[0].id){

        //Create a challenge request
        var request = new SparkRequests.CreateChallengeRequest();

        //Fill in the details, give a date in the future, the right shortCode,
        //make it a private challenge and invite participant 2
        request.accessType = "PRIVATE";
        request.challengeShortCode = "chalRanked";
        request.endTime = "2020-02-23T13:47Z";
        request.expiryTime = "2020-02-23T12:47Z";
        request.usersToChallenge = [Spark.getData().participants[1].id];

        //Send the request
        request.Send();

    }
}

After the Challenge request is sent, the second participant will receive a Message issued request. We'll automatically accept the Challenge request for that player by editing the ChallengeIssuedMessage under User Messages on the Scripts panel in the Cloud Code section.

Challenge Issued Message

We'll edit the ChallengeIssuedMessage to contain:

//Easy access to data
var chalData = Spark.getData();
//New request to join the challenge automatically
var request = new SparkRequests.AcceptChallengeRequest();

//Retrieve the challenge ID to use it in the AcceptChallenge request
request.challengeInstanceId = chalData.challenge.challengeId;
request.message = "Joining";

//Send the request as the player receiving this message
request.SendAs(chalData.challenge.challenged[0].id);

Challenge Started Global Message

After this, the Challenge would have started and both players would receive the ChallengeStartedMessage. This is the perfect place to initialize the Challenge and set it up for both our players. To avoid duplication, we'll call the logic in the global message instead of the user message. Doing this will also ensure that when our players receive the ChallengeStartedMessage they'll have the Challenge details initialized.

Global Messages not User Messages! Make sure you attach this Cloud Code logic to the ChallengeStartedMessage under the Global Messages section NOT the User Messages section of the Cloud Code>Scripts panel.

//Declare challenge
var chal = Spark.getChallenge(Spark.getData().challenge.challengeId);

//Player IDs
var challengerId = chal.getChallengerId();
var challengedId = chal.getChallengedPlayerIds()[0];

//Construct the play field JSON - Used for the playing field
var playField = {};
playField[challengerId] = {};
playField[challengedId] = {};

//Construct the current hand JSON - Used for the cards in the player's hands
var currentHand = {};
currentHand[challengerId] = {};
currentHand[challengedId] = {};

//Construct player details
var playerStats = {};
playerStats[challengerId] = {"overallMana": 1, "currentMana": 1, "playerHealth": 30, "cardsPulled": 0, "hasPulled": true }
playerStats[challengedId] = {"overallMana": 1, "currentMana": 1, "playerHealth": 30, "cardsPulled": 0, "hasPulled": true }


//Pull three cards for each player
for(var i = 0; i < 3; i++){
    //First Id
    var pId = challengerId;
    require("pullCardModule");
    //second Id
    var pId = challengedId;
    require("pullCardModule");
}


//Save the contructed JSONs against the challenge's scriptData
chal.setScriptData("playField",playField);
chal.setScriptData("currentHand", currentHand);
chal.setScriptData("playerStats", playerStats);

This will construct the game itself with all the details, which contains:

  1. The playField, which will represent the game board where players battle their cards. The playField consists of two objects, one for either player.
  2. The currentHand, which will represent the player's hand. This consists of two objects, one hand for either player.
  3. playerStats, which will house information about mana, health, how many cards pulled, and if the player has pulled a card this round.
  4. Each player will receive 3 cards from their current deck, which will end up in the currentHand object.
  5. A save of all the initialized values against the Challenge's scriptData.

pullCard Module

The pullCardModule used in the ChallengeStartedMessage contains this code:

//Load Game Data Service
var API = Spark.getGameDataService();
//Attempt to retrieve entry
var entryOBJ = API.getItem("playerDeck", pId);

//Check for errors
if(entryOBJ.error()){
    Spark.setScriptData("ERROR", entryOBJ.error());
    Spark.exit();
}

//Get entry
var entry = entryOBJ.document();
//Get data
var data = entry.getData();
//Get current deck
var deck = data.decks[data.currentDeck]

//Length and random number depending on length
var lengthArr = deck.length ;
var randNum = Math.floor(Math.random() * (lengthArr - 1));

var cardOBJ = API.getItem("cardTable", deck[randNum]);

if(cardOBJ.error()){
    Spark.setScriptData("ERROR", cardOBJ.error());
    Spark.exit();
}

//Retrieve random card stats from table entry
var cardDoc = cardOBJ.document();
var cardStats = cardDoc.getData();

//Construct card
var card = {"type" : cardDoc.getId() , "atk" : cardStats.attack, "hp" : cardStats.health, "maxHP": cardStats.health, "spawnCost" : cardStats.spawnCost};

//Retrieve the number of pulled cards so far
var numPulls = playerStats[pId].cardsPulled;

//Add the new card to the player hand and give it a unique name
currentHand[pId]["c" + numPulls.toString()] = card;

//Increment amount of cards pulled for future unique card names
playerStats[pId].cardsPulled = numPulls + 1;

//Return script with card pulled
Spark.setScriptData("result", cardOBJ.document().getId() + " was pulled from deck");

Summary

This concludes the matchmaking part of the tutorial. Now your players will be matched and a Challenge will be started and initialized ready for the game to take part. The next Challenge tutorial will walk you through getting the players to take turns and use their cards.