Matchmaking

GD-Sync includes a built-in matchmaking system that allows you to automatically find players and place them into a lobby. This removes the need to create your own matchmaking queue or manually search for suitable lobbies.

Matchmaking uses a MatchmakingRequest to determine what kind of match you are looking for. GD-Sync will then search for an existing public lobby or place you in the matchmaking queue, depending on the settings of the request.

You cannot start matchmaking while you are already inside a lobby or when using local multiplayer.

Starting a Request

A matchmaking request can be created using MatchmakingRequest.new(player_limit : int). The player_limit determines the maximum number of players that can be in the resulting lobby.

Once the request has been configured, you can start matchmaking using GDSync.matchmaking_start(request : MatchmakingRequest).

If another matchmaking request is already active, starting a new request will automatically cancel the previous request.

When matchmaking starts successfully, the GDSync.matchmaking_started() signal is emitted. GD-Sync will then search for a suitable lobby or place the player in the matchmaking queue. When a match is found, the GDSync.matchmaking_match_found(lobby_name : String) signal is emitted. GD-Sync automatically joins the lobby for you, so you should not call lobby_join yourself.

Once the lobby has been joined, the regular GDSync.lobby_joined(lobby_name : String) signal is emitted. This is the signal you should use when your game is ready to enter the lobby.

If matchmaking fails, the GDSync.matchmaking_failed(error : int) signal is emitted instead.

Below is a basic example that searches for a match with a maximum of 4 players. Since no minimum player count is specified, the matchmaking queue will wait until 4 players have been found.

GDScript
func _ready():
	GDSync.connected.connect(_on_connected)
	GDSync.matchmaking_match_found.connect(_on_match_found)
	GDSync.lobby_joined.connect(_on_lobby_joined)
	GDSync.start_multiplayer()

func _on_connected():
	GDSync.matchmaking_start(MatchmakingRequest.new(4))

func _on_match_found(lobby_name : String):
	print("Match found: "+lobby_name)

func _on_lobby_joined(lobby_name : String):
	print("Joined lobby: "+lobby_name)

Configuring

The MatchmakingRequest can be configured before it is passed to matchmaking_start.

The minimum number of players can be set using request.set_min_players(count : int). This determines how many players are required before GD-Sync creates the lobby. The value must be between 1 and the player limit, and defaults to the player limit. For example, the following request creates a lobby as soon as 2 players have been found, while still allowing up to 8 players to join:

GDScript
var request := MatchmakingRequest.new(8)
request.set_min_players(2)

GDSync.matchmaking_start(request)

The resulting lobby remains open, allowing additional players to join until the lobby reaches its player limit or is closed.

You can restrict which players are matched together using request.set_required_tags(tags : Dictionary). All tags must match when players are matched through the matchmaking queue. This means that players with different values, or even different keys, will not be matched together. When searching public lobbies, the behaviour is slightly different. A public lobby only needs to contain all of the required tags, so it may contain additional tags.

GDScript
request.set_required_tags({
	"Mode": "PvP",
	"Map": "Desert",
	"Ranked": true,
})

The search mode determines whether public lobbies are searched before using the matchmaking queue. It can be configured using request.set_search_mode(mode : MatchmakingRequest.SearchMode).

The available search modes are:
PUBLIC_ONLY
Only searches for existing public lobbies. If no suitable lobby is found, matchmaking fails.

PUBLIC_THEN_MATCHMAKE
Searches public lobbies first and uses the matchmaking queue if no suitable lobby is found. This is the default.

MATCHMAKE_ONLY
Skips public lobbies and uses the matchmaking queue directly.

Only public, open and passwordless lobbies can be found through public matchmaking. The lobby's player limit must exactly match the request's player limit. Closed or password-protected lobbies are never joined.

You can also configure a timeout using request.set_timeout(seconds : float). If the timeout is reached before a match is found, matchmaking fails. A timeout of 0.0 waits indefinitely and is the default.

When matchmaking creates a new lobby, you can provide initial lobby data using request.set_lobby_data(data : Dictionary). Lobby data is only applied when GD-Sync creates a new lobby. It is not applied when matchmaking joins an existing public lobby.

Skill-based Matching

Matchmaking can optionally take player skill into account. Skill matching is disabled by default and is only used while players are waiting in the matchmaking queue. It does not affect searches for existing public lobbies.

To enable skill matching, first set the player's rating using request.set_skill_rating(rating : float). You can then specify the allowed skill range using request.set_skill_range(initial : float, maximum : float, expansion_per_second : float).The initial value determines the allowed rating difference when the search starts. The range will then increase by expansion_per_second every second until it reaches the maximum value.

For example:

GDScript
request.set_skill_rating(1200.0)
request.set_skill_range(50.0, 400.0, 10.0)

This starts with a range of 50 rating points and increases it by 10 points per second until it reaches 400. Setting the initial and maximum values to the same value creates a fixed range that will not expand. Skill matching can be disabled again using request.clear_skill_matching().

GDScript
request.set_required_tags({
	"Mode": "PvP",
	"Map": "Desert",
	"Ranked": true,
})

The search mode determines whether public lobbies are searched before using the matchmaking queue. It can be configured using request.set_search_mode(mode : MatchmakingRequest.SearchMode).

The available search modes are:
PUBLIC_ONLY
Only searches for existing public lobbies. If no suitable lobby is found, matchmaking fails.

PUBLIC_THEN_MATCHMAKE
Searches public lobbies first and uses the matchmaking queue if no suitable lobby is found. This is the default.

MATCHMAKE_ONLY
Skips public lobbies and uses the matchmaking queue directly.

Only public, open and passwordless lobbies can be found through public matchmaking. The lobby's player limit must exactly match the request's player limit. Closed or password-protected lobbies are never joined.

You can also configure a timeout using request.set_timeout(seconds : float). If the timeout is reached before a match is found, matchmaking fails. A timeout of 0.0 waits indefinitely and is the default.

Matchmaking Status

GD-Sync provides several signals and functions for checking the current matchmaking state.

The GDSync.matchmaking_status_changed(status : int, details : Dictionary) signal is emitted whenever the matchmaking status changes. The status parameter uses the ENUMS.MATCHMAKING_STATUS enum.

The available statuses are:
INACTIVE
No matchmaking request is currently active.

SEARCHING_PUBLIC
GD-Sync is currently searching for a suitable public lobby.

WAITING_FOR_PLAYERS
No suitable public lobby was found and the player is currently waiting in the matchmaking queue.

MATCH_FOUND
A match has been found and the lobby has been reserved.

JOINING
GD-Sync is joining the lobby that was reserved for the match.


The details dictionary currently contains ElapsedSeconds, which contains the amount of time in seconds that the current matchmaking request has been active.

GDScript
func _on_status(status : int, details : Dictionary):
	var elapsed : float = details.get("ElapsedSeconds", 0.0)

	match status:
		ENUMS.MATCHMAKING_STATUS.INACTIVE:
			pass
		ENUMS.MATCHMAKING_STATUS.SEARCHING_PUBLIC:
			print("Searching public lobbies: ", elapsed)
		ENUMS.MATCHMAKING_STATUS.WAITING_FOR_PLAYERS:
			print("Waiting for players: ", elapsed)
		ENUMS.MATCHMAKING_STATUS.MATCH_FOUND:
			print("Match found")
		ENUMS.MATCHMAKING_STATUS.JOINING:
			print("Joining lobby")

The current status can also be retrieved using GDSync.matchmaking_get_status(), while GDSync.matchmaking_get_status_details() returns the current status details.

To check whether a matchmaking request is active, use GDSync.matchmaking_is_active().

Cancelling Matchmaking

An active matchmaking request can be cancelled using GDSync.matchmaking_cancel(). Cancelling an inactive request has no effect.

Once the server has confirmed the cancellation, GD-Sync emits the GDSync.matchmaking_cancelled() signal. This can also be useful when replacing a search with a different request. You do not need to cancel the previous request manually, as starting a new request automatically replaces the previous one.

Errors

If matchmaking cannot be started or completed, GD-Sync emits GDSync.matchmaking_failed(error : int).

The error parameter uses the ENUMS.MATCHMAKING_ERROR enum:
INVALID_REQUEST
The request contains invalid parameters. This can occur when the player limit is invalid, the minimum player count is outside the valid range, the search mode is invalid, the timeout is negative, the tags exceed 2048 bytes, the lobby data exceeds 8192 bytes, or the skill range is invalid.

ALREADY_IN_LOBBY
Matchmaking was started while already inside a lobby.

NO_MATCH
No suitable public lobby was found. This only occurs when using the PUBLIC_ONLY search mode.

TIMEOUT
The matchmaking request exceeded its configured timeout.

UNSUPPORTED_LOCAL
Matchmaking was started while using local multiplayer.

JOIN_FAILED
A match was successfully reserved, but GD-Sync was unable to join the resulting lobby.

INVALID_REQUEST, ALREADY_IN_LOBBY, and UNSUPPORTED_LOCAL can be emitted immediately when GDSync.matchmaking_start() is called. In these cases, GDSync.matchmaking_started will not be emitted.