# Cupid Matchmaker API Documentation ## Overview Cupid Matchmaker is a matchmaking daemon server designed for Unity game matchmaking. It manages player queues, creates game rooms, and spawns game instances when enough players are available. **Version:** v1.0 **Base URL:** `http://localhost:2612` (configurable via `settings.json`) --- ## Authentication All endpoints require authentication via a password query parameter. The password is configured in `settings.json`. **Note:** All requests must include `?password=` in the query string. --- ## Endpoints ### 1. Get Server Settings Retrieve the current server configuration settings. **Endpoint:** `GET /settings` **Query Parameters:** | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `password` | string | Yes | Server password for authentication | **Response (200 OK):** ```json { "minimum_players": 2, "maximum_players": 2, "waiting_time": 60000, "port_range_min": 26000, "port_range_max": 27000, "games": [ { "id": "soccar", "exe": "/home/react/CupidServer/games/soccar/soccar.x86_64" } ] } ``` **Response Fields:** - `minimum_players` (number): Minimum number of players required to start a game - `maximum_players` (number): Maximum number of players allowed in a room - `waiting_time` (number): Room expiration time in milliseconds - `port_range_min` (number): Minimum port number for game instances - `port_range_max` (number): Maximum port number for game instances - `games` (array): List of available game configurations - `id` (string): Game identifier - `exe` (string): Path to game executable **Error Responses:** - `403 Unauthorized`: Invalid password **Example Request:** ```bash curl "http://localhost:2612/settings?password=HelloWorld" ``` --- ### 2. Matchmaking (Join Queue / Get Room) Main endpoint for matchmaking. Players use this endpoint to join the queue or retrieve their current room information. **Endpoint:** `GET /` **Query Parameters:** | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `password` | string | Yes | Server password for authentication | | `username` | string | Yes | Player's username (minimum 2 characters) | | `game_name` | string | Yes | Name/identifier of the game to matchmake for | **Response Scenarios:** #### Scenario 1: Player Already in a Room (200 OK) Returns the room object if the player is already assigned to a room. ```json { "Players": [ { "Name": "player1", "LastSeen": 1234567890 }, { "Name": "player2", "LastSeen": 1234567891 } ], "GameName": "soccar", "Port": 26150, "InitTime": 1234567800 } ``` #### Scenario 2: Room Created (200 OK) Returns a new room when enough players are in the queue and a room is created. ```json { "Players": [ { "Name": "player1", "LastSeen": 1234567890 } ], "GameName": "soccar", "Port": 26150, "InitTime": 1234567890 } ``` #### Scenario 3: Joined Existing Room (200 OK) Returns the room when a player joins an existing room that has available slots. ```json { "Players": [ { "Name": "player1", "LastSeen": 1234567890 }, { "Name": "player2", "LastSeen": 1234567891 } ], "GameName": "soccar", "Port": 26150, "InitTime": 1234567800 } ``` #### Scenario 4: Added to Queue (200 OK) Returns `"0"` when the player is added to the queue or is already in the queue waiting for other players. ``` "0" ``` **Response Fields:** - `Players` (array): List of players in the room - `Name` (string): Player's username - `LastSeen` (number): Unix timestamp of last activity - `GameName` (string): Name of the game - `Port` (number): Port number assigned to the game instance - `InitTime` (number): Unix timestamp when the room was created **Error Responses:** - `403 Unauthorized`: Invalid password - `Bad credentials`: Username is less than 2 characters **Behavior Notes:** - Players must poll this endpoint regularly (within 2 seconds) to maintain their queue position - Rooms expire after `waiting_time` milliseconds - Players are removed from the queue if inactive for more than 2 seconds - When enough players are in the queue (≥ `minimum_players`), a new room is created and a game instance is spawned - Players can join existing rooms if they have available slots and match the `game_name` **Example Request:** ```bash curl "http://localhost:2612/?password=HelloWorld&username=player1&game_name=soccar" ``` --- ### 3. Cancel Queue Entry Remove a player from the matchmaking queue. **Endpoint:** `GET /cancel` **Query Parameters:** | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `password` | string | Yes | Server password for authentication | | `username` | string | Yes | Player's username to remove from queue | **Response (200 OK):** - `"1"`: Successfully removed from queue **Error Responses:** - `403 Unauthorized`: Invalid password - `Bad credentials`: Username is less than 2 characters - `"Couldn't find user in the queue"`: User not found in queue **Example Request:** ```bash curl "http://localhost:2612/cancel?password=HelloWorld&username=player1" ``` --- ## Data Models ### Player ```typescript { Name: string; // Player's username LastSeen: number; // Unix timestamp of last activity } ``` ### Room ```typescript { Players: Player[]; // Array of players in the room GameName: string; // Name/identifier of the game Port: number; // Port number for the game instance InitTime: number; // Unix timestamp when room was created } ``` ### QueueEntry ```typescript { Name: string; // Player's username LastSeen: number; // Unix timestamp of last activity } ``` --- ## Server Configuration The server is configured via `settings.json`: ```json { "port": 2612, "password": "HelloWorld", "minimum_players": 2, "maximum_players": 2, "waiting_time": 60000, "port_range_min": 26000, "port_range_max": 27000, "game_exe": [ { "name": "soccar", "exe": "/home/react/CupidServer/games/soccar/soccar.x86_64" } ], "log_level": 1 } ``` **Configuration Fields:** - `port` (number): Server listening port - `password` (string): Authentication password for API access - `minimum_players` (number): Minimum players required to start a game - `maximum_players` (number): Maximum players allowed per room - `waiting_time` (number): Room expiration time in milliseconds - `port_range_min` (number): Minimum port for game instances - `port_range_max` (number): Maximum port for game instances - `game_exe` (array): Game executable configurations - `name` (string): Game identifier - `exe` (string): Path to game executable - `log_level` (number): Logging verbosity (0 = minimal, 1 = debug, 2 = verbose) --- ## Matchmaking Flow 1. **Player Joins Queue:** - Player calls `GET /` with `username` and `game_name` - If not enough players in queue, player receives `"0"` and is added to queue 2. **Room Creation:** - When queue reaches `minimum_players`, a new room is created - A random port is selected from the configured range - A game instance is spawned with the selected port - First player receives the room object 3. **Room Joining:** - Subsequent players calling `GET /` can join existing rooms with available slots - Players receive the room object with updated player list 4. **Room Expiration:** - Rooms expire after `waiting_time` milliseconds - Expired rooms are automatically cleaned up 5. **Queue Maintenance:** - Players must poll `GET /` at least every 2 seconds to stay in queue - Inactive players are automatically removed from queue --- ## Error Handling All endpoints return appropriate HTTP status codes: - `200 OK`: Successful request - `403 Unauthorized`: Authentication failure - Error messages are returned as plain text in the response body --- ## Best Practices 1. **Polling Frequency:** Poll the matchmaking endpoint (`GET /`) every 1-2 seconds to maintain queue position 2. **Error Handling:** Always check for `403 Unauthorized` responses and handle authentication errors 3. **Username Validation:** Ensure usernames are at least 2 characters long 4. **Room Management:** Once a room is received, connect to the game instance on the provided port 5. **Queue Cancellation:** Use `/cancel` endpoint when a player wants to leave the queue --- ## Example Integration ### JavaScript/TypeScript Example ```typescript const BASE_URL = 'http://localhost:2612'; const PASSWORD = 'HelloWorld'; const USERNAME = 'player1'; const GAME_NAME = 'soccar'; // Join matchmaking queue async function joinMatchmaking() { const url = `${BASE_URL}/?password=${PASSWORD}&username=${USERNAME}&game_name=${GAME_NAME}`; const response = await fetch(url); const data = await response.text(); if (data === '0') { console.log('Added to queue, waiting for players...'); // Poll every 1.5 seconds setTimeout(joinMatchmaking, 1500); } else { const room = JSON.parse(data); console.log('Room found!', room); console.log(`Connect to game on port ${room.Port}`); } } // Cancel queue async function cancelQueue() { const url = `${BASE_URL}/cancel?password=${PASSWORD}&username=${USERNAME}`; const response = await fetch(url); const result = await response.text(); console.log('Cancel result:', result); } ``` --- ## Notes - The server automatically spawns game instances when rooms are created - Game instances are launched with the `-port` argument - Rooms are automatically cleaned up when expired or empty - The queue has a grace period of 2 seconds for player inactivity - All timestamps are Unix timestamps in milliseconds