363 lines
9.6 KiB
Markdown
363 lines
9.6 KiB
Markdown
# 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=<your_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 <username> 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
|