From d5a4ff4eb2927b082941c12ad03a8c794cf80b77 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Sep 2025 13:21:43 +0000 Subject: [PATCH 1/5] Initial plan From 1ec154e97aa95fe8f0b79bf64d868a4b6c903998 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Sep 2025 13:27:11 +0000 Subject: [PATCH 2/5] Create comprehensive README documentation Co-authored-by: ExilProductions <206137164+ExilProductions@users.noreply.github.com> --- README.md | 354 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 353 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 76deaad..e488dee 100644 --- a/README.md +++ b/README.md @@ -1 +1,353 @@ -# PurrLobby \ No newline at end of file +# PurrLobby 🐱 + +A lightweight, fast, and reliable lobby service for multiplayer games. PurrLobby provides an alternative to Steam Lobby Service and Unity Lobby Service, offering real-time lobby management with WebSocket communication. + +## 🌟 Features + +- **Multi-Game Support**: Scope lobbies per game using unique Game IDs +- **Real-time Updates**: WebSocket-based live lobby updates and member status changes +- **Player Management**: Join/leave lobbies, ready status, custom display names +- **Custom Properties**: Store arbitrary key-value data on lobbies +- **Search & Discovery**: Find available lobbies with filtering +- **Rate Limiting**: Built-in protection against abuse (300 requests/minute per IP) +- **Statistics**: Global and per-game player/lobby statistics +- **Production Ready**: Includes compression, HTTPS, security headers, and proxy support +- **Web Interface**: Built-in dashboard for monitoring and testing +- **OpenAPI/Swagger**: Full API documentation with interactive testing + +## 🚀 Quick Start + +### Prerequisites + +- [.NET 8.0 SDK](https://dotnet.microsoft.com/download/dotnet/8.0) +- Windows, macOS, or Linux + +### Installation & Running + +1. Clone the repository: +```bash +git clone https://github.com/ExilProductions/PurrLobby.git +cd PurrLobby +``` + +2. Build the project: +```bash +dotnet build +``` + +3. Run the service: +```bash +cd PurrLobby +dotnet run +``` + +4. Access the web interface: [https://localhost:7225](https://localhost:7225) +5. View API documentation: [https://localhost:7225/swagger](https://localhost:7225/swagger) + +## 🔧 Configuration + +### Environment Variables + +Configure the service using `appsettings.json` or environment variables: + +- `ASPNETCORE_ENVIRONMENT`: Set to `Production` for production deployment +- `ASPNETCORE_URLS`: Configure listening URLs (default: `https://localhost:7225;http://localhost:5123`) + +### Domain Configuration + +For production deployment, update the cookie domain in `Program.cs`: +```csharp +Domain = "your-domain.com" // Line 134 +``` + +### Rate Limiting + +Default rate limits (configurable in `Program.cs`): +- **300 requests per minute** per IP address +- **100 queued requests** per IP +- Returns `429 Too Many Requests` when exceeded + +## 📚 API Usage + +### 1. Set Game Context + +Before using lobby endpoints, set your game's GUID: + +```bash +curl -X POST "https://your-domain.com/session/game" \ + -H "Content-Type: application/json" \ + -d '{"gameId": "your-game-guid-here"}' +``` + +This sets a secure cookie that scopes all subsequent requests to your game. + +### 2. Create a Lobby + +```bash +curl -X POST "https://your-domain.com/lobbies" \ + -H "Content-Type: application/json" \ + -H "Cookie: gameId=your-game-guid" \ + -d '{ + "ownerUserId": "player123", + "ownerDisplayName": "PlayerName", + "maxPlayers": 4, + "properties": { + "gameMode": "competitive", + "map": "dust2" + } + }' +``` + +### 3. Search Lobbies + +```bash +curl "https://your-domain.com/lobbies/search?maxRoomsToFind=10" \ + -H "Cookie: gameId=your-game-guid" +``` + +### 4. Join a Lobby + +```bash +curl -X POST "https://your-domain.com/lobbies/{lobbyId}/join" \ + -H "Content-Type: application/json" \ + -H "Cookie: gameId=your-game-guid" \ + -d '{ + "userId": "player456", + "displayName": "AnotherPlayer" + }' +``` + +### 5. WebSocket Connection for Real-time Updates + +Connect to lobby-specific WebSocket for live updates: + +```javascript +const ws = new WebSocket(`wss://your-domain.com/ws/lobbies/${lobbyId}?userId=${userId}`); + +ws.onmessage = function(event) { + const data = JSON.parse(event.data); + console.log('Lobby update:', data); + // Handle events: member_joined, member_left, member_ready, lobby_data, etc. +}; +``` + +## 🌐 Web Interface + +The service includes a web dashboard at the root URL featuring: + +- **Global Statistics**: Total players and lobbies across all games +- **Game-Specific Stats**: Players and lobbies for your specific game +- **Game ID Management**: Easy way to set and track your game +- **Direct API Access**: Links to Swagger documentation + +## 📊 Monitoring & Statistics + +### Global Statistics +- `GET /stats/global/players` - Total players across all games +- `GET /stats/global/lobbies` - Total lobbies across all games + +### Game-Specific Statistics +- `GET /stats/{gameId}/players` - Active players for a specific game +- `GET /stats/{gameId}/lobbies` - Lobby count for a specific game + +### Health Check +- `GET /health` - Service health status + +## 🏗️ Architecture + +### Components + +- **Program.cs**: Main application configuration and API endpoints +- **LobbyService**: Core business logic for lobby management +- **LobbyEventHub**: WebSocket connection management and real-time events +- **Lobby Models**: Data structures for lobbies and users + +### Key Features Implementation + +- **Cookie-based Game Scoping**: Uses secure HTTP-only cookies for game context +- **In-Memory Storage**: Fast performance with concurrent collections +- **Event-Driven Updates**: Real-time WebSocket notifications for all lobby changes +- **Production Security**: Rate limiting, HTTPS enforcement, proxy header trust +- **Comprehensive Logging**: HTTP request logging and structured application logs + +## 🚢 Deployment + +### Docker (Recommended) + +Create a `Dockerfile`: +```dockerfile +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["PurrLobby/PurrLobby.csproj", "PurrLobby/"] +RUN dotnet restore "PurrLobby/PurrLobby.csproj" +COPY . . +WORKDIR "/src/PurrLobby" +RUN dotnet build "PurrLobby.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "PurrLobby.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "PurrLobby.dll"] +``` + +### Reverse Proxy Configuration + +For production deployment behind a reverse proxy (nginx, Apache, etc.), ensure proper header forwarding for rate limiting and security: + +```nginx +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Forwarded-Proto $scheme; +proxy_set_header X-Forwarded-Host $host; +``` + +## 🔌 Client Integration Examples + +### Unity C# +```csharp +public async Task CreateLobby(string gameId, string userId, string displayName) +{ + var client = new HttpClient(); + + // Set game context + await client.PostAsync($"{baseUrl}/session/game", + new StringContent($"{{\"gameId\": \"{gameId}\"}}", Encoding.UTF8, "application/json")); + + // Create lobby + var lobbyData = new { + ownerUserId = userId, + ownerDisplayName = displayName, + maxPlayers = 4, + properties = new { gameMode = "casual" } + }; + + var response = await client.PostAsync($"{baseUrl}/lobbies", + new StringContent(JsonUtility.ToJson(lobbyData), Encoding.UTF8, "application/json")); + + return response.IsSuccessStatusCode; +} +``` + +### JavaScript/Web +```javascript +class PurrLobbyClient { + constructor(baseUrl, gameId) { + this.baseUrl = baseUrl; + this.gameId = gameId; + } + + async setGameContext() { + await fetch(`${this.baseUrl}/session/game`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + credentials: 'include', + body: JSON.stringify({ gameId: this.gameId }) + }); + } + + async createLobby(userId, displayName, maxPlayers = 4) { + const response = await fetch(`${this.baseUrl}/lobbies`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + credentials: 'include', + body: JSON.stringify({ + ownerUserId: userId, + ownerDisplayName: displayName, + maxPlayers: maxPlayers, + properties: {} + }) + }); + return response.json(); + } +} +``` + +## 🛠️ Development + +### Building from Source +```bash +# Clone repository +git clone https://github.com/ExilProductions/PurrLobby.git +cd PurrLobby + +# Restore dependencies and build +dotnet restore +dotnet build + +# Run with hot reload for development +cd PurrLobby +dotnet watch run +``` + +### Running Tests +```bash +dotnet test +``` + +### Code Analysis +The project includes code analysis rules. Fix any warnings before deploying: +```bash +dotnet build --verbosity normal +``` + +## 📝 API Reference + +Full API documentation is available via Swagger UI when the service is running: +- **Local**: [https://localhost:7225/swagger](https://localhost:7225/swagger) +- **Production**: `https://your-domain.com/swagger` + +### Authentication +Most endpoints require a `gameId` cookie set via `POST /session/game`. The cookie: +- Is HTTP-only and secure +- Expires after 7 days +- Scopes all requests to your specific game + +### WebSocket Events +The lobby WebSocket (`/ws/lobbies/{lobbyId}`) broadcasts these events: +- `member_joined` - New player joined +- `member_left` - Player left lobby +- `member_ready` - Player readiness changed +- `lobby_data` - Custom lobby property updated +- `lobby_deleted` - Lobby was deleted + +## 🤝 Contributing + +This is an independent project by ExilProductions, not affiliated with PurrNet. + +### Issues & Support +- For bugs or feature requests, open an issue on GitHub +- For direct support, contact: **exil_s** on Discord +- Please don't contact PurrNet developers about this service + +### Development Guidelines +1. Fork the repository +2. Create a feature branch +3. Make your changes with appropriate tests +4. Ensure code analysis passes +5. Submit a pull request + +## ⚠️ Disclaimer + +This service is independent and runs on personal infrastructure. It may experience downtime or instability. It's provided as-is for development and testing purposes. For production use, consider self-hosting or implementing additional redundancy. + +## 📄 License + +This project is open source. Check the repository for license details. + +## 🔗 Links + +- **Live Instance**: [https://purrlobby.exil.dev](https://purrlobby.exil.dev) +- **API Documentation**: [https://purrlobby.exil.dev/swagger](https://purrlobby.exil.dev/swagger) +- **GitHub Repository**: [https://github.com/ExilProductions/PurrLobby](https://github.com/ExilProductions/PurrLobby) + +--- + +Made with 💜 by ExilProductions \ No newline at end of file From 926bd0e139a493f7f088034e21f00a2ed578d8c9 Mon Sep 17 00:00:00 2001 From: Exil Productions Date: Fri, 12 Sep 2025 16:49:57 +0200 Subject: [PATCH 3/5] Made readmebetter the copilot one sucked so i reworte it --- README.md | 340 ++++++------------------------------------------------ 1 file changed, 37 insertions(+), 303 deletions(-) diff --git a/README.md b/README.md index e488dee..019022e 100644 --- a/README.md +++ b/README.md @@ -1,206 +1,75 @@ -# PurrLobby 🐱 +# PurrLobby -A lightweight, fast, and reliable lobby service for multiplayer games. PurrLobby provides an alternative to Steam Lobby Service and Unity Lobby Service, offering real-time lobby management with WebSocket communication. +Lightweight, fast lobby service for [PurrNet](https://github.com/PurrNet/PurrNet) multiplayer games. Alternative to Steam or Unity lobby lobby services. -## 🌟 Features +## Implementation Overview -- **Multi-Game Support**: Scope lobbies per game using unique Game IDs -- **Real-time Updates**: WebSocket-based live lobby updates and member status changes -- **Player Management**: Join/leave lobbies, ready status, custom display names -- **Custom Properties**: Store arbitrary key-value data on lobbies -- **Search & Discovery**: Find available lobbies with filtering -- **Rate Limiting**: Built-in protection against abuse (300 requests/minute per IP) -- **Statistics**: Global and per-game player/lobby statistics -- **Production Ready**: Includes compression, HTTPS, security headers, and proxy support -- **Web Interface**: Built-in dashboard for monitoring and testing -- **OpenAPI/Swagger**: Full API documentation with interactive testing +* **Multi-game scoping**: Each game has isolated lobbies via Game ID +* **Real-time WebSocket events**: member join/leave, ready status, lobby data updates +* **Custom lobby properties**: Store arbitrary key-value data per lobby +* **Built-in stats**: Global & per-game player/lobby counts +* **Rate limiting**: Protects against abuse by default +* **Web dashboard + Swagger**: Monitor lobbies and test API -## 🚀 Quick Start +## Quick Start -### Prerequisites - -- [.NET 8.0 SDK](https://dotnet.microsoft.com/download/dotnet/8.0) -- Windows, macOS, or Linux - -### Installation & Running - -1. Clone the repository: ```bash git clone https://github.com/ExilProductions/PurrLobby.git cd PurrLobby -``` - -2. Build the project: -```bash dotnet build -``` - -3. Run the service: -```bash -cd PurrLobby dotnet run ``` -4. Access the web interface: [https://localhost:7225](https://localhost:7225) -5. View API documentation: [https://localhost:7225/swagger](https://localhost:7225/swagger) +Dashboard: [https://purrlobby.exil.dev](https://purrlobby.exil.dev) +API docs: [https://purrlobby.exil.dev/swagger](https://purrlobby.exil.dev/swagger) -## 🔧 Configuration +## Configuration -### Environment Variables +* `ASPNETCORE_ENVIRONMENT=Production` +* `ASPNETCORE_URLS=https://localhost:7225;http://localhost:5123` +* Cookie domain (production): `Program.cs → Domain = "your-domain.com"` -Configure the service using `appsettings.json` or environment variables: +## API Essentials -- `ASPNETCORE_ENVIRONMENT`: Set to `Production` for production deployment -- `ASPNETCORE_URLS`: Configure listening URLs (default: `https://localhost:7225;http://localhost:5123`) - -### Domain Configuration - -For production deployment, update the cookie domain in `Program.cs`: -```csharp -Domain = "your-domain.com" // Line 134 -``` - -### Rate Limiting - -Default rate limits (configurable in `Program.cs`): -- **300 requests per minute** per IP address -- **100 queued requests** per IP -- Returns `429 Too Many Requests` when exceeded - -## 📚 API Usage - -### 1. Set Game Context - -Before using lobby endpoints, set your game's GUID: +Set game context (required): ```bash curl -X POST "https://your-domain.com/session/game" \ - -H "Content-Type: application/json" \ - -d '{"gameId": "your-game-guid-here"}' +-H "Content-Type: application/json" \ +-d '{"gameId":"your-game-guid"}' ``` -This sets a secure cookie that scopes all subsequent requests to your game. - -### 2. Create a Lobby +Create a lobby: ```bash curl -X POST "https://your-domain.com/lobbies" \ - -H "Content-Type: application/json" \ - -H "Cookie: gameId=your-game-guid" \ - -d '{ - "ownerUserId": "player123", - "ownerDisplayName": "PlayerName", - "maxPlayers": 4, - "properties": { - "gameMode": "competitive", - "map": "dust2" - } - }' +-H "Content-Type: application/json" \ +-H "Cookie: gameId=your-game-guid" \ +-d '{"ownerUserId":"player1","ownerDisplayName":"Player","maxPlayers":4,"properties":{"mode":"casual"}}' ``` -### 3. Search Lobbies +Join/search lobbies using `/lobbies/{id}/join` and `/lobbies/search`. -```bash -curl "https://your-domain.com/lobbies/search?maxRoomsToFind=10" \ - -H "Cookie: gameId=your-game-guid" -``` - -### 4. Join a Lobby - -```bash -curl -X POST "https://your-domain.com/lobbies/{lobbyId}/join" \ - -H "Content-Type: application/json" \ - -H "Cookie: gameId=your-game-guid" \ - -d '{ - "userId": "player456", - "displayName": "AnotherPlayer" - }' -``` - -### 5. WebSocket Connection for Real-time Updates - -Connect to lobby-specific WebSocket for live updates: +**WebSocket** (live updates): ```javascript const ws = new WebSocket(`wss://your-domain.com/ws/lobbies/${lobbyId}?userId=${userId}`); - -ws.onmessage = function(event) { - const data = JSON.parse(event.data); - console.log('Lobby update:', data); - // Handle events: member_joined, member_left, member_ready, lobby_data, etc. -}; +ws.onmessage = e => console.log(JSON.parse(e.data)); ``` -## 🌐 Web Interface +## Deployment -The service includes a web dashboard at the root URL featuring: +**Docker** -- **Global Statistics**: Total players and lobbies across all games -- **Game-Specific Stats**: Players and lobbies for your specific game -- **Game ID Management**: Easy way to set and track your game -- **Direct API Access**: Links to Swagger documentation - -## 📊 Monitoring & Statistics - -### Global Statistics -- `GET /stats/global/players` - Total players across all games -- `GET /stats/global/lobbies` - Total lobbies across all games - -### Game-Specific Statistics -- `GET /stats/{gameId}/players` - Active players for a specific game -- `GET /stats/{gameId}/lobbies` - Lobby count for a specific game - -### Health Check -- `GET /health` - Service health status - -## 🏗️ Architecture - -### Components - -- **Program.cs**: Main application configuration and API endpoints -- **LobbyService**: Core business logic for lobby management -- **LobbyEventHub**: WebSocket connection management and real-time events -- **Lobby Models**: Data structures for lobbies and users - -### Key Features Implementation - -- **Cookie-based Game Scoping**: Uses secure HTTP-only cookies for game context -- **In-Memory Storage**: Fast performance with concurrent collections -- **Event-Driven Updates**: Real-time WebSocket notifications for all lobby changes -- **Production Security**: Rate limiting, HTTPS enforcement, proxy header trust -- **Comprehensive Logging**: HTTP request logging and structured application logs - -## 🚢 Deployment - -### Docker (Recommended) - -Create a `Dockerfile`: ```dockerfile -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:8.0 WORKDIR /app -EXPOSE 80 -EXPOSE 443 - -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build -WORKDIR /src -COPY ["PurrLobby/PurrLobby.csproj", "PurrLobby/"] -RUN dotnet restore "PurrLobby/PurrLobby.csproj" +EXPOSE 80 443 COPY . . -WORKDIR "/src/PurrLobby" -RUN dotnet build "PurrLobby.csproj" -c Release -o /app/build - -FROM build AS publish -RUN dotnet publish "PurrLobby.csproj" -c Release -o /app/publish - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "PurrLobby.dll"] +ENTRYPOINT ["dotnet","PurrLobby.dll"] ``` -### Reverse Proxy Configuration - -For production deployment behind a reverse proxy (nginx, Apache, etc.), ensure proper header forwarding for rate limiting and security: +**Reverse Proxy (nginx)** ```nginx proxy_set_header X-Real-IP $remote_addr; @@ -209,145 +78,10 @@ proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; ``` -## 🔌 Client Integration Examples +## Contributing -### Unity C# -```csharp -public async Task CreateLobby(string gameId, string userId, string displayName) -{ - var client = new HttpClient(); - - // Set game context - await client.PostAsync($"{baseUrl}/session/game", - new StringContent($"{{\"gameId\": \"{gameId}\"}}", Encoding.UTF8, "application/json")); - - // Create lobby - var lobbyData = new { - ownerUserId = userId, - ownerDisplayName = displayName, - maxPlayers = 4, - properties = new { gameMode = "casual" } - }; - - var response = await client.PostAsync($"{baseUrl}/lobbies", - new StringContent(JsonUtility.ToJson(lobbyData), Encoding.UTF8, "application/json")); - - return response.IsSuccessStatusCode; -} -``` +Fork → branch → PR. Use tests & pass code analysis. Report issues on GitHub. -### JavaScript/Web -```javascript -class PurrLobbyClient { - constructor(baseUrl, gameId) { - this.baseUrl = baseUrl; - this.gameId = gameId; - } - - async setGameContext() { - await fetch(`${this.baseUrl}/session/game`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - credentials: 'include', - body: JSON.stringify({ gameId: this.gameId }) - }); - } - - async createLobby(userId, displayName, maxPlayers = 4) { - const response = await fetch(`${this.baseUrl}/lobbies`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - credentials: 'include', - body: JSON.stringify({ - ownerUserId: userId, - ownerDisplayName: displayName, - maxPlayers: maxPlayers, - properties: {} - }) - }); - return response.json(); - } -} -``` +## License -## 🛠️ Development - -### Building from Source -```bash -# Clone repository -git clone https://github.com/ExilProductions/PurrLobby.git -cd PurrLobby - -# Restore dependencies and build -dotnet restore -dotnet build - -# Run with hot reload for development -cd PurrLobby -dotnet watch run -``` - -### Running Tests -```bash -dotnet test -``` - -### Code Analysis -The project includes code analysis rules. Fix any warnings before deploying: -```bash -dotnet build --verbosity normal -``` - -## 📝 API Reference - -Full API documentation is available via Swagger UI when the service is running: -- **Local**: [https://localhost:7225/swagger](https://localhost:7225/swagger) -- **Production**: `https://your-domain.com/swagger` - -### Authentication -Most endpoints require a `gameId` cookie set via `POST /session/game`. The cookie: -- Is HTTP-only and secure -- Expires after 7 days -- Scopes all requests to your specific game - -### WebSocket Events -The lobby WebSocket (`/ws/lobbies/{lobbyId}`) broadcasts these events: -- `member_joined` - New player joined -- `member_left` - Player left lobby -- `member_ready` - Player readiness changed -- `lobby_data` - Custom lobby property updated -- `lobby_deleted` - Lobby was deleted - -## 🤝 Contributing - -This is an independent project by ExilProductions, not affiliated with PurrNet. - -### Issues & Support -- For bugs or feature requests, open an issue on GitHub -- For direct support, contact: **exil_s** on Discord -- Please don't contact PurrNet developers about this service - -### Development Guidelines -1. Fork the repository -2. Create a feature branch -3. Make your changes with appropriate tests -4. Ensure code analysis passes -5. Submit a pull request - -## ⚠️ Disclaimer - -This service is independent and runs on personal infrastructure. It may experience downtime or instability. It's provided as-is for development and testing purposes. For production use, consider self-hosting or implementing additional redundancy. - -## 📄 License - -This project is open source. Check the repository for license details. - -## 🔗 Links - -- **Live Instance**: [https://purrlobby.exil.dev](https://purrlobby.exil.dev) -- **API Documentation**: [https://purrlobby.exil.dev/swagger](https://purrlobby.exil.dev/swagger) -- **GitHub Repository**: [https://github.com/ExilProductions/PurrLobby](https://github.com/ExilProductions/PurrLobby) - ---- - -Made with 💜 by ExilProductions \ No newline at end of file +MIT From ee20301c571ee0cfad1a423154d5ad7ee4dc462d Mon Sep 17 00:00:00 2001 From: Exil Productions Date: Fri, 12 Sep 2025 16:50:47 +0200 Subject: [PATCH 4/5] i did a upsie --- PurrLobby/appsettings.Production.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PurrLobby/appsettings.Production.json b/PurrLobby/appsettings.Production.json index ee659bf..ef912cb 100644 --- a/PurrLobby/appsettings.Production.json +++ b/PurrLobby/appsettings.Production.json @@ -4,11 +4,11 @@ "Https": { "Url": "https://0.0.0.0:443", "Certificate": { - "Path": "C:\\certs\\purrlobby.pem", - "KeyPath": "C:\\certs\\purrlobby.key" + "Path": "pemfile", + "KeyPath": "keyfile" } } } }, - "AllowedHosts": "purrlobby.exil.dev" + "AllowedHosts": "your.domain.com" } From dab152fa35076c6f53f44a96ac33ca88e1a8042c Mon Sep 17 00:00:00 2001 From: Exil Productions Date: Fri, 12 Sep 2025 16:51:31 +0200 Subject: [PATCH 5/5] Remove duplicate dashboard and API links --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 019022e..a8b7d9a 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ Lightweight, fast lobby service for [PurrNet](https://github.com/PurrNet/PurrNet) multiplayer games. Alternative to Steam or Unity lobby lobby services. +Dashboard: [https://purrlobby.exil.dev](https://purrlobby.exil.dev) +API docs: [https://purrlobby.exil.dev/swagger](https://purrlobby.exil.dev/swagger) + ## Implementation Overview * **Multi-game scoping**: Each game has isolated lobbies via Game ID @@ -20,9 +23,6 @@ dotnet build dotnet run ``` -Dashboard: [https://purrlobby.exil.dev](https://purrlobby.exil.dev) -API docs: [https://purrlobby.exil.dev/swagger](https://purrlobby.exil.dev/swagger) - ## Configuration * `ASPNETCORE_ENVIRONMENT=Production`