brainCloud Online Matchmaking is a process of finding (or creating) an appropriate lobby for the user. During matchmaking, potential participants are put into a waiting/entry queue. As the last filtering resort, if the developer has specified a filter script, the candidate lobbies will be passed to it for final approval before sending it to the client app. See the following flowchart, the filter script is checked as the last step before the user can join a lobby.

The filter criteria of the lobby filter script can be customized as you needed, but basically, just comparing the filter JSON data when calling FindLobby with the candidate lobbies' configurations, which can be the lobbies' metadata or the owner customized data, see the following data that can be accessed by the lobby filter script.

{
"step": 1,
"filter": {
"groupName": "group1",
"cheater": false,
"level": 5
},
"matchCandidate": {
"id": "13229:CursorPartyV2:29",
"lobbyType": "CursorPartyV2",
"state": "early",
"rating": 10,
"lobbyTypeDef": {
"roomConfig": {
"roomConfig_key3": false,
"roomConfig_key2": 99,
"roomConfig_key1": "customValue"
},
"lobbyTypeId": "CursorPartyV2",
"teams": {
"all": {
"minUsers": 1,
"maxUsers": 8,
"autoAssign": true,
"code": "all"
}
},
"rules": {
"allowEarlyStartWithoutMax": true,
"forceOnTimeStartWithoutReady": true,
"allowJoinInProgress": true,
"onTimeStartSecs": 300,
"disbandOnStart": false,
"everyReadyMinPercent": 0,
"everyReadyMinNum": 1,
"earliestStartSecs": 1,
"tooLateSecs": 300
},
"desc": "relay protocol version 2"
},
"settings": {
"groupName": "group1",
"cheater": false,
"level": 3
},
"version": 1,
"connectData": {},
"timetable": {
"createdAt": 1650419947323,
"early": 1650419948323,
"onTime": 1650420247323,
"tooLate": 1650420247323
},
"cRegions": [],
"round": 1,
"isRoomReady": false,
"ownerCxId": "13229:35620730-e2f0-468f-bc1d-700942de0b87:pggquikoeiqkj20kepu42175lr",
"legacyLobbyOwnerEnabled": false,
"numMembers": 1,
"members": [
{
"profileId": "35620730-e2f0-468f-bc1d-700942de0b87",
"name": "xx",
"pic": "",
"rating": 10,
"team": "all",
"isReady": false,
"extra": {
"colorIndex": 4
},
"cxId": "13229:35620730-e2f0-468f-bc1d-700942de0b87:pggquikoeiqkj20kepu42175lr"
}
]
},
"pingData": {}
}

The following simple lobby filter script example shows you how to use the custom filter criteria to filter the lobbies with state and the owner customized settings data when lobbies get created.

"use strict";

function main() {
var response = {};
var is_accept = false;
bridge.logInfoJson("lobby filter data...", data);
var matchCandidate = data.matchCandidate;
var lobbyState = matchCandidate.state;
var lobbyRating = matchCandidate.rating;

// check state, will not joining if the lobby is starting already
if (lobbyState != "starting")
{
var lobbySettings = matchCandidate.settings;
var filter = data.filter;

// check if user passed filter data meet owner's settings data
if (filter.groupName == lobbySettings.groupName &&
filter.level >= lobbySettings.level &&
filter.cheater == lobbySettings.cheater )
{
is_accept = true;
}
}

// the return object must contain keyword 'accept' with boolean value, lobby service will check this name with code: `boolean isAccept = (Boolean) response.get("accept");`
response.accept = is_accept;
return response;
}

main();

Now, let's test this filter script with our RelayTestApp example, which can be found in most types of brainCloud client libs from GitHub, we'll use node.js one.

  • After creating the above script from the script editor, go to Configure Lobbies page, open a lobby type and link the lobby filter script to this lobby type from the Filter Script dropdown.

  • Modify the RelayTestApp example app to link to your app, build and run it on your local device, then login to the app with a user xx and click the PLAY GAME button to create a lobby as the owner (code call findOrCreateLobby method, since no other running lobby instances running on your local build, so the first user who calls this method will create a lobby).

    (Note that if no lobby candidates are found, the filter script will not be triggered.)

  • The passed arguments are as follows for findOrCreateLobby call.

// Find or create a lobby
this.bc.lobby.findOrCreateLobby(lobbyType, 10, 3, { strategy: "ranged-absolute", alignment: "center", ranges: [1000] }, {}, null, {"groupName":"group1", "cheater":false, "level":3}, false, {colorIndex:this.state.user.colorIndex}, "all", result =>
{
if (result.status !== 200)
{
this.dieWithMessage("Failed to find lobby")
}
})
  • Run the same localhost from another browser log in to the app with another user and click PLAY GAME WITH FILTER SETTINGS button, it will call FindLobby with filter JSON meeting the validation of the lobby filter script.

  • The passed arguments are as follows for findLobby call.

// Find the martched lobby
this.bc.lobby.findLobby(lobbyType, 10, 3, { strategy: "ranged-absolute", alignment: "center", ranges: [1000] }, {"groupName":"group1", "cheater":false, "level":5}, null, false, {colorIndex:this.state.user.colorIndex}, "all", result =>
{
if (result.status !== 200)
{
this.dieWithMessage("Failed to find lobby")
}
})
  • We can see the user yy member joined the lobby successfully, and we can know that the lobby filter script was triggered by checking app log info from the monitoring page.

  • Now, let's change the filter script's one of the conditions to false, set filter.level <= lobbySettings.level (since the user passed filter data JSON level is 5 greater than the owner settings level, which is 3). User yy leave the lobby and join it again, we can see the user fails to join the previous lobby with a JOIN_FAIL message -- No lobbies found matching criteria.

PS. Online Matchmaking (OMM)

Overview

Online Matchmaking is the process of finding (or creating) an appropriate lobby for the user.

During matchmaking, potential participants are put into a waiting/entry queue.

The system then periodically runs through all members of the queue, from oldest (highest step #) to lowest, looking for suitable lobbies, and creating a new lobby for that user if required.

If the developer has specified a filter script, candidate lobbies will be passed to it for final approval before sending it to the client app.

The lobbyQueue process should:

  • run every <x> seconds

  • exit immediately if there are no participants in the queue

Data

The following information is also stored about the candidate in the queue:

  • cx - the user's connection id

  • profileId - the user's profile id (separated out for each-of-use in the matchmaking filter)

  • lobbyType - the type of the queue the user is waiting in

  • rating - the candidate's skill rating

  • step - the user's current step/stage/iteration in matchmaking

  • maxSteps - the maximum number of steps to wait when searching. Steps occur approximately every 2 seconds.

  • algo - the rating step algorithm to use

  • filter - the custom filter criteria

  • ready - boolean to indicate whether the participant should be set to ready when added to the lobby

  • extraJson - extra data about the participant (to use when adding the participant to the lobby)

  • team - the team to add the player to. Maybe"".

  • create - create a lobby if we reach maxSteps?

  • settings - if create == true, then these settings will be used as the owner settings for the lobby...

Step algorithms

The matchmaking system can be "programmed" by filling out an algorithm structure for stepping. The structure looks like this. Note - if maxSteps > than the included ranges, then the last specified range is used.

{
"strategy": "ranged-percent",
"alignment": "center",
"ranges": [ 5, 5, 7.5, 7.5, 10, 10, 12.5, 12.5, 15, 15 ]
}

The following algorithm values are currently supported:

  • strategy - used to select the overall rating-step algorithm. The following variations are supported:

    • ranged-percent - the ranges provided are interpreted as percentages to be applied to the user's rating for matchmaking.

    • ranged-absolute - the ranges provided are interpreted as absolute values to add/subtract from the user's rating when calculating the range for matchmaking

    • compound - a special form of strategy that supports nested algorithms. See example.

  • alignment - determines how the range is aligned with the user's rating

  • ranges - an array of ranges values to apply to the algorithm. Note - if the current step is greater than the value supplied in the range, the last value of the range is used.

Example using the compound algorithm - select lobby based on ping then rating

{
"strategy": "compound",
"algos" [
{ "criteria": "ping", "strategy": "ranged-percent", "alignment": "center" },
{ "criteria": "rating", "strategy": "ranged-percent", "alignment": "center" }
],
"compound-ranges": [
[ 30, [ 5, 7.5 ]],
[ 60, [ 5, 5, 7.5, 7.5, 10, 10 ]],
[ 130, [ 5, 7.5, 10, 12.5, 15]]
]
}

The following alignment options are available, and show how they would affect a range of +/- 10 for a ranking of 80.

alignment

min

max

description

high

80

100

Ensures that lobbies must have skill rating >= to the candidate. Leaves the min equal to player rating, and adds 200% of the range to the max.

mid-high

75

95

Subtracks 50% of the range for the min, and adds 150% of the range to the max.

center

70

90

Centers the range around the candidiate's rating.

mid-low

65

85

Subtracts 150% of the range for the min, and adds 50% of the range to the max.

low

60

80

Ensures that lobbies will have skill rating <= to the candidate. Subtracts 200% of the range from the rating to calculate min, and leaves max as the player rating.




Did this answer your question?