Skip to content

Latest commit

 

History

History
1009 lines (885 loc) · 24.5 KB

matchmaking.md

File metadata and controls

1009 lines (885 loc) · 24.5 KB

Matchmaking

The matchmaking cycle works as follows:

  1. Clients should first retrieve a list of all the available queues from the server using list.
  2. Clients should then queue for one or more of these queues by sending an array of the queue ids in a queue request.
  3. The server can send periodic updates about the status of the search as a queueUpdate event.
  4. When a match is found, the server should send a found event along with the id of the queue of the found match.
  5. Clients can then ready up by sending a ready request. The number of readied players should be sent to clients via the foundUpdate event.
  6. 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.
  7. If a client fails to ready up for a found match, the server should send a lost event, and the queueing phase should resume.
  8. 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.
  9. 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 matchmaking
  • server_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 withdraw
  • ready_timeout: The player failed to accept a match within the given time window and is thus removed from the matchmaking system.


Cancel

Cancel queueing for matchmaking.

  • Endpoint Type: Request -> Response
  • Source: User
  • Target: Server
  • Required Scopes: tachyon.lobby

Request

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"
}

TypeScript Definition

export interface MatchmakingCancelRequest {
    type: "request";
    messageId: string;
    commandId: "matchmaking/cancel";
}

Response

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"
}

TypeScript Definition

export interface MatchmakingCancelOkResponse {
    type: "response";
    messageId: string;
    commandId: "matchmaking/cancel";
    status: "success";
}

Possible Failed Reasons: not_queued, internal_error, unauthorized, invalid_request, command_unimplemented


Cancelled

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

Event

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"
    }
}

TypeScript Definition

export interface MatchmakingCancelledEvent {
    type: "event";
    messageId: string;
    commandId: "matchmaking/cancelled";
    data: MatchmakingCancelledEventData;
}
export interface MatchmakingCancelledEventData {
    reason: "intentional" | "server_error" | "party_user_left" | "ready_timeout";
}

Found

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

Event

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
    }
}

TypeScript Definition

export interface MatchmakingFoundEvent {
    type: "event";
    messageId: string;
    commandId: "matchmaking/found";
    data: MatchmakingFoundEventData;
}
export interface MatchmakingFoundEventData {
    queueId: string;
    timeoutMs: number;
}

FoundUpdate

Server should send this when players ready up using ready.

  • Endpoint Type: Event
  • Source: Server
  • Target: User
  • Required Scopes: tachyon.lobby

Event

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
    }
}

TypeScript Definition

export interface MatchmakingFoundUpdateEvent {
    type: "event";
    messageId: string;
    commandId: "matchmaking/foundUpdate";
    data: MatchmakingFoundUpdateEventData;
}
export interface MatchmakingFoundUpdateEventData {
    readyCount: number;
}

List

Returns all available matchmaking playlists.

  • Endpoint Type: Request -> Response
  • Source: User
  • Target: Server
  • Required Scopes: tachyon.lobby

Request

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"
}

TypeScript Definition

export interface MatchmakingListRequest {
    type: "request";
    messageId: string;
    commandId: "matchmaking/list";
}

Response

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
            }
        ]
    }
}

TypeScript Definition

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


Lost

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

Event

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"
}

TypeScript Definition

export interface MatchmakingLostEvent {
    type: "event";
    messageId: string;
    commandId: "matchmaking/lost";
}

Queue

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

Request

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"
        ]
    }
}

TypeScript Definition

export interface MatchmakingQueueRequest {
    type: "request";
    messageId: string;
    commandId: "matchmaking/queue";
    data: MatchmakingQueueRequestData;
}
export interface MatchmakingQueueRequestData {
    queues: [string, ...string[]];
}

Response

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"
}

TypeScript Definition

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


QueueUpdate

Contains some info about the state of the current queue.

  • Endpoint Type: Event
  • Source: Server
  • Target: User
  • Required Scopes: tachyon.lobby

Event

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"
    }
}

TypeScript Definition

export interface MatchmakingQueueUpdateEvent {
    type: "event";
    messageId: string;
    commandId: "matchmaking/queueUpdate";
    data: MatchmakingQueueUpdateEventData;
}
export interface MatchmakingQueueUpdateEventData {
    playersQueued: string;
}

Ready

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

Request

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"
}

TypeScript Definition

export interface MatchmakingReadyRequest {
    type: "request";
    messageId: string;
    commandId: "matchmaking/ready";
}

Response

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"
}

TypeScript Definition

export interface MatchmakingReadyOkResponse {
    type: "response";
    messageId: string;
    commandId: "matchmaking/ready";
    status: "success";
}

Possible Failed Reasons: no_match, internal_error, unauthorized, invalid_request, command_unimplemented