The matchmaking cycle works as follows:
- Clients should first retrieve a list of all the available queues from the server using list.
- Clients should then queue for one or more of these queues by sending an array of the queue ids in a queue request.
- The server can send periodic updates about the status of the search as a queueUpdate event.
- When a match is found, the server should send a found event along with the id of the queue of the found match.
- Clients can then ready up by sending a ready request. The number of readied players should be sent to clients via the foundUpdate event.
- To cancel queueing, or to decline a found match, clients should send a cancel request. After a successful
cancel
response, the server will also send a cancelled event. - If a client fails to ready up for a found match, the server should send a lost event, and the queueing phase should resume.
- Once all players are ready, the server should send a autohost/battleStart request to a suitable autohost client. If the autohost doesn't respond quickly, or if it sends a failed response, the server should repeat this step.
- Once the autohost has successfully started the battle, the server should then send battle/battleStart requests to the users.
The server may send matchmaking/cancelled event at any point after the client sent a queue request with a reason. This means the client has been booted out the matchmaking system. It can happen for example when a party member leaves, or in case of a server error that needs to reset the matchmaking state. This event is also sent after a successful cancel request.
matchmaking/cancelled can have the following reasons:
intentional
: the player left matchmakingserver_error
: something bad happended and the server couldn't maintain state so it booted the player out. Retrying may fix the issue.party_user_left
: a member of the player's party left matchmaking, thus forcing the entire party to withdrawready_timeout
: The player failed to accept a match within the given time window and is thus removed from the matchmaking system.
Cancel queueing for matchmaking.
- Endpoint Type: Request -> Response
- Source: User
- Target: Server
- Required Scopes:
tachyon.lobby
JSONSchema
{
"title": "MatchmakingCancelRequest",
"tachyon": {
"source": "user",
"target": "server",
"scopes": ["tachyon.lobby"]
},
"type": "object",
"properties": {
"type": { "const": "request" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/cancel" }
},
"required": ["type", "messageId", "commandId"]
}
Example
{
"type": "request",
"messageId": "magna commodo",
"commandId": "matchmaking/cancel"
}
export interface MatchmakingCancelRequest {
type: "request";
messageId: string;
commandId: "matchmaking/cancel";
}
JSONSchema
{
"title": "MatchmakingCancelResponse",
"tachyon": {
"source": "server",
"target": "user",
"scopes": ["tachyon.lobby"]
},
"anyOf": [
{
"title": "MatchmakingCancelOkResponse",
"type": "object",
"properties": {
"type": { "const": "response" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/cancel" },
"status": { "const": "success" }
},
"required": ["type", "messageId", "commandId", "status"]
},
{
"title": "MatchmakingCancelFailResponse",
"type": "object",
"properties": {
"type": { "const": "response" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/cancel" },
"status": { "const": "failed" },
"reason": {
"enum": [
"not_queued",
"internal_error",
"unauthorized",
"invalid_request",
"command_unimplemented"
]
},
"details": { "type": "string" }
},
"required": ["type", "messageId", "commandId", "status", "reason"]
}
]
}
Example
{
"type": "response",
"messageId": "id ea",
"commandId": "matchmaking/cancel",
"status": "success"
}
export interface MatchmakingCancelOkResponse {
type: "response";
messageId: string;
commandId: "matchmaking/cancel";
status: "success";
}
Possible Failed Reasons: not_queued
, internal_error
, unauthorized
, invalid_request
, command_unimplemented
Server may send this event at any point when the user is queuing to indicate that the user has been booted out the matchmaking system.
- Endpoint Type: Event
- Source: Server
- Target: User
- Required Scopes:
tachyon.lobby
JSONSchema
{
"title": "MatchmakingCancelledEvent",
"tachyon": {
"source": "server",
"target": "user",
"scopes": ["tachyon.lobby"]
},
"type": "object",
"properties": {
"type": { "const": "event" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/cancelled" },
"data": {
"title": "MatchmakingCancelledEventData",
"type": "object",
"properties": {
"reason": {
"enum": [
"intentional",
"server_error",
"party_user_left",
"ready_timeout"
]
}
},
"required": ["reason"]
}
},
"required": ["type", "messageId", "commandId", "data"]
}
Example
{
"type": "event",
"messageId": "voluptate ullamco",
"commandId": "matchmaking/cancelled",
"data": {
"reason": "server_error"
}
}
export interface MatchmakingCancelledEvent {
type: "event";
messageId: string;
commandId: "matchmaking/cancelled";
data: MatchmakingCancelledEventData;
}
export interface MatchmakingCancelledEventData {
reason: "intentional" | "server_error" | "party_user_left" | "ready_timeout";
}
Server should send this when there are enough queued players to form a valid battle that meets their criteria. Clients should then send ready.
- Endpoint Type: Event
- Source: Server
- Target: User
- Required Scopes:
tachyon.lobby
JSONSchema
{
"title": "MatchmakingFoundEvent",
"tachyon": {
"source": "server",
"target": "user",
"scopes": ["tachyon.lobby"]
},
"type": "object",
"properties": {
"type": { "const": "event" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/found" },
"data": {
"title": "MatchmakingFoundEventData",
"type": "object",
"properties": {
"queueId": { "type": "string" },
"timeoutMs": { "type": "integer" }
},
"required": ["queueId", "timeoutMs"]
}
},
"required": ["type", "messageId", "commandId", "data"]
}
Example
{
"type": "event",
"messageId": "in exercitation",
"commandId": "matchmaking/found",
"data": {
"queueId": "in exercitation",
"timeoutMs": -48000000
}
}
export interface MatchmakingFoundEvent {
type: "event";
messageId: string;
commandId: "matchmaking/found";
data: MatchmakingFoundEventData;
}
export interface MatchmakingFoundEventData {
queueId: string;
timeoutMs: number;
}
Server should send this when players ready up using ready.
- Endpoint Type: Event
- Source: Server
- Target: User
- Required Scopes:
tachyon.lobby
JSONSchema
{
"title": "MatchmakingFoundUpdateEvent",
"tachyon": {
"source": "server",
"target": "user",
"scopes": ["tachyon.lobby"]
},
"type": "object",
"properties": {
"type": { "const": "event" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/foundUpdate" },
"data": {
"title": "MatchmakingFoundUpdateEventData",
"type": "object",
"properties": { "readyCount": { "type": "integer" } },
"required": ["readyCount"]
}
},
"required": ["type", "messageId", "commandId", "data"]
}
Example
{
"type": "event",
"messageId": "in nostrud",
"commandId": "matchmaking/foundUpdate",
"data": {
"readyCount": -46000000
}
}
export interface MatchmakingFoundUpdateEvent {
type: "event";
messageId: string;
commandId: "matchmaking/foundUpdate";
data: MatchmakingFoundUpdateEventData;
}
export interface MatchmakingFoundUpdateEventData {
readyCount: number;
}
Returns all available matchmaking playlists.
- Endpoint Type: Request -> Response
- Source: User
- Target: Server
- Required Scopes:
tachyon.lobby
JSONSchema
{
"title": "MatchmakingListRequest",
"tachyon": {
"source": "user",
"target": "server",
"scopes": ["tachyon.lobby"]
},
"type": "object",
"properties": {
"type": { "const": "request" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/list" }
},
"required": ["type", "messageId", "commandId"]
}
Example
{
"type": "request",
"messageId": "consequat quis",
"commandId": "matchmaking/list"
}
export interface MatchmakingListRequest {
type: "request";
messageId: string;
commandId: "matchmaking/list";
}
JSONSchema
{
"title": "MatchmakingListResponse",
"tachyon": {
"source": "server",
"target": "user",
"scopes": ["tachyon.lobby"]
},
"anyOf": [
{
"title": "MatchmakingListOkResponse",
"type": "object",
"properties": {
"type": { "const": "response" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/list" },
"status": { "const": "success" },
"data": {
"title": "MatchmakingListOkResponseData",
"type": "object",
"properties": {
"playlists": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"numOfTeams": { "type": "integer" },
"teamSize": { "type": "integer" },
"ranked": { "type": "boolean" }
},
"required": [
"id",
"name",
"numOfTeams",
"teamSize",
"ranked"
]
}
}
},
"required": ["playlists"],
"examples": [
{
"playlists": [
{
"id": "1v1",
"name": "Duel",
"numOfTeams": 2,
"teamSize": 1,
"ranked": true
},
{
"id": "1v1v1",
"name": "3 Way FFA",
"numOfTeams": 3,
"teamSize": 1,
"ranked": true
}
]
}
]
}
},
"required": ["type", "messageId", "commandId", "status", "data"]
},
{
"title": "MatchmakingListFailResponse",
"type": "object",
"properties": {
"type": { "const": "response" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/list" },
"status": { "const": "failed" },
"reason": {
"enum": [
"internal_error",
"unauthorized",
"invalid_request",
"command_unimplemented"
]
},
"details": { "type": "string" }
},
"required": ["type", "messageId", "commandId", "status", "reason"]
}
]
}
Example
{
"type": "response",
"messageId": "commodo laborum",
"commandId": "matchmaking/list",
"status": "success",
"data": {
"playlists": [
{
"id": "1v1",
"name": "Duel",
"numOfTeams": 2,
"teamSize": 1,
"ranked": true
},
{
"id": "1v1v1",
"name": "3 Way FFA",
"numOfTeams": 3,
"teamSize": 1,
"ranked": true
}
]
}
}
export interface MatchmakingListOkResponse {
type: "response";
messageId: string;
commandId: "matchmaking/list";
status: "success";
data: MatchmakingListOkResponseData;
}
export interface MatchmakingListOkResponseData {
playlists: {
id: string;
name: string;
numOfTeams: number;
teamSize: number;
ranked: boolean;
}[];
}
Possible Failed Reasons: internal_error
, unauthorized
, invalid_request
, command_unimplemented
Sent when a found match gets disbanded because a client failed to ready up.
- Endpoint Type: Event
- Source: Server
- Target: User
- Required Scopes:
tachyon.lobby
JSONSchema
{
"title": "MatchmakingLostEvent",
"tachyon": {
"source": "server",
"target": "user",
"scopes": ["tachyon.lobby"]
},
"type": "object",
"properties": {
"type": { "const": "event" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/lost" }
},
"required": ["type", "messageId", "commandId"]
}
Example
{
"type": "event",
"messageId": "nisi deserunt",
"commandId": "matchmaking/lost"
}
export interface MatchmakingLostEvent {
type: "event";
messageId: string;
commandId: "matchmaking/lost";
}
Queue up for matchmaking. Should cancel the previous queue if already in one.
- Endpoint Type: Request -> Response
- Source: User
- Target: Server
- Required Scopes:
tachyon.lobby
JSONSchema
{
"title": "MatchmakingQueueRequest",
"tachyon": {
"source": "user",
"target": "server",
"scopes": ["tachyon.lobby"]
},
"type": "object",
"properties": {
"type": { "const": "request" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/queue" },
"data": {
"title": "MatchmakingQueueRequestData",
"type": "object",
"properties": {
"queues": {
"type": "array",
"items": { "type": "string" },
"minItems": 1
}
},
"required": ["queues"]
}
},
"required": ["type", "messageId", "commandId", "data"]
}
Example
{
"type": "request",
"messageId": "nisi qui",
"commandId": "matchmaking/queue",
"data": {
"queues": [
"nisi qui",
"nisi qui"
]
}
}
export interface MatchmakingQueueRequest {
type: "request";
messageId: string;
commandId: "matchmaking/queue";
data: MatchmakingQueueRequestData;
}
export interface MatchmakingQueueRequestData {
queues: [string, ...string[]];
}
JSONSchema
{
"title": "MatchmakingQueueResponse",
"tachyon": {
"source": "server",
"target": "user",
"scopes": ["tachyon.lobby"]
},
"anyOf": [
{
"title": "MatchmakingQueueOkResponse",
"type": "object",
"properties": {
"type": { "const": "response" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/queue" },
"status": { "const": "success" }
},
"required": ["type", "messageId", "commandId", "status"]
},
{
"title": "MatchmakingQueueFailResponse",
"type": "object",
"properties": {
"type": { "const": "response" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/queue" },
"status": { "const": "failed" },
"reason": {
"enum": [
"invalid_queue_specified",
"already_queued",
"already_inbattle",
"internal_error",
"unauthorized",
"invalid_request",
"command_unimplemented"
]
},
"details": { "type": "string" }
},
"required": ["type", "messageId", "commandId", "status", "reason"]
}
]
}
Example
{
"type": "response",
"messageId": "laboris non",
"commandId": "matchmaking/queue",
"status": "success"
}
export interface MatchmakingQueueOkResponse {
type: "response";
messageId: string;
commandId: "matchmaking/queue";
status: "success";
}
Possible Failed Reasons: invalid_queue_specified
, already_queued
, already_inbattle
, internal_error
, unauthorized
, invalid_request
, command_unimplemented
Contains some info about the state of the current queue.
- Endpoint Type: Event
- Source: Server
- Target: User
- Required Scopes:
tachyon.lobby
JSONSchema
{
"title": "MatchmakingQueueUpdateEvent",
"tachyon": {
"source": "server",
"target": "user",
"scopes": ["tachyon.lobby"]
},
"type": "object",
"properties": {
"type": { "const": "event" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/queueUpdate" },
"data": {
"title": "MatchmakingQueueUpdateEventData",
"type": "object",
"properties": { "playersQueued": { "type": "string" } },
"required": ["playersQueued"]
}
},
"required": ["type", "messageId", "commandId", "data"]
}
Example
{
"type": "event",
"messageId": "ullamco occaecat",
"commandId": "matchmaking/queueUpdate",
"data": {
"playersQueued": "ullamco occaecat"
}
}
export interface MatchmakingQueueUpdateEvent {
type: "event";
messageId: string;
commandId: "matchmaking/queueUpdate";
data: MatchmakingQueueUpdateEventData;
}
export interface MatchmakingQueueUpdateEventData {
playersQueued: string;
}
Clients should send this when they are ready to proceed with the found match. If not sent within 10s of the found response then queue should be cancelled.
- Endpoint Type: Request -> Response
- Source: User
- Target: Server
- Required Scopes:
tachyon.lobby
JSONSchema
{
"title": "MatchmakingReadyRequest",
"tachyon": {
"source": "user",
"target": "server",
"scopes": ["tachyon.lobby"]
},
"type": "object",
"properties": {
"type": { "const": "request" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/ready" }
},
"required": ["type", "messageId", "commandId"]
}
Example
{
"type": "request",
"messageId": "reprehenderit Lorem",
"commandId": "matchmaking/ready"
}
export interface MatchmakingReadyRequest {
type: "request";
messageId: string;
commandId: "matchmaking/ready";
}
JSONSchema
{
"title": "MatchmakingReadyResponse",
"tachyon": {
"source": "server",
"target": "user",
"scopes": ["tachyon.lobby"]
},
"anyOf": [
{
"title": "MatchmakingReadyOkResponse",
"type": "object",
"properties": {
"type": { "const": "response" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/ready" },
"status": { "const": "success" }
},
"required": ["type", "messageId", "commandId", "status"]
},
{
"title": "MatchmakingReadyFailResponse",
"type": "object",
"properties": {
"type": { "const": "response" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/ready" },
"status": { "const": "failed" },
"reason": {
"enum": [
"no_match",
"internal_error",
"unauthorized",
"invalid_request",
"command_unimplemented"
]
},
"details": { "type": "string" }
},
"required": ["type", "messageId", "commandId", "status", "reason"]
}
]
}
Example
{
"type": "response",
"messageId": "dolor Lorem",
"commandId": "matchmaking/ready",
"status": "success"
}
export interface MatchmakingReadyOkResponse {
type: "response";
messageId: string;
commandId: "matchmaking/ready";
status: "success";
}
Possible Failed Reasons: no_match
, internal_error
, unauthorized
, invalid_request
, command_unimplemented