imprvd
This commit is contained in:
@@ -0,0 +1,362 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user