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 userxx
and click thePLAY GAME
button to create a lobby as the owner (code callfindOrCreateLobby
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 callFindLobby
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 is5
greater than the owner settings level, which is3
). Useryy
leave the lobby and join it again, we can see the user fails to join the previous lobby with aJOIN_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 idprofileId
- 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 inrating
- the candidate's skill ratingstep
- the user's current step/stage/iteration in matchmakingmaxSteps
- the maximum number of steps to wait when searching. Steps occur approximately every 2 seconds.algo
- the rating step algorithm to usefilter
- the custom filter criteriaready
- boolean to indicate whether the participant should be set to ready when added to the lobbyextraJson
- 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 matchmakingcompound
- a special form of strategy that supports nested algorithms. See example.
alignment
- determines how the range is aligned with the user's ratingranges - 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 |
| 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. |
| 75 | 95 | Subtracks 50% of the range for the min, and adds 150% of the range to the max. |
| 70 | 90 | Centers the range around the candidiate's rating. |
| 65 | 85 | Subtracts 150% of the range for the min, and adds 50% of the range to the max. |
| 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. |
β
β
β