214 lines
3.8 KiB
Markdown
214 lines
3.8 KiB
Markdown
# Spacetris — Supabase Highscore Integration
|
|
## VS Code Copilot AI Agent Prompt
|
|
|
|
You are integrating Supabase highscores into a native C++ SDL3 game called **Spacetris**.
|
|
|
|
This is a REST-only integration using Supabase PostgREST.
|
|
Do NOT use any Supabase JS SDKs.
|
|
|
|
---
|
|
|
|
## 1. Goal
|
|
|
|
Implement a highscore backend using Supabase for these game modes:
|
|
- classic
|
|
- challenge
|
|
- cooperate
|
|
- versus
|
|
|
|
Highscores must be:
|
|
- Submitted asynchronously on game over
|
|
- Fetched asynchronously for leaderboard screens
|
|
- Non-blocking (never stall render loop)
|
|
- Offline-safe (fail silently)
|
|
|
|
---
|
|
|
|
## 2. Supabase Configuration
|
|
|
|
The following constants are provided at build time:
|
|
|
|
```cpp
|
|
const std::string SUPABASE_URL = "https://xzxpmvyamjvtxpwnjpad.supabase.co";
|
|
const std::string SUPABASE_ANON_KEY = "sb_publishable_GqQx844xYDizO9-ytlBXfA_MVT6N7yA";
|
|
````
|
|
|
|
All requests go to:
|
|
|
|
```
|
|
{SUPABASE_URL}/rest/v1/highscores
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Database Schema (Already Exists)
|
|
|
|
The Supabase table `highscores` has the following fields:
|
|
|
|
* score (integer)
|
|
* lines (integer)
|
|
* level (integer)
|
|
* time_sec (integer)
|
|
* name (string)
|
|
* game_type ("classic", "versus", "cooperate", "challenge")
|
|
* timestamp (integer, UNIX epoch seconds)
|
|
|
|
---
|
|
|
|
## 4. Data Model in C++
|
|
|
|
Create a struct matching the database schema:
|
|
|
|
```cpp
|
|
struct HighscoreEntry {
|
|
int score;
|
|
int lines;
|
|
int level;
|
|
int timeSec;
|
|
std::string name;
|
|
std::string gameType;
|
|
int timestamp;
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## 5. HTTP Layer Requirements
|
|
|
|
* Use **libcurl**
|
|
* Use **JSON** (nlohmann::json or equivalent)
|
|
* All network calls must run in a worker thread
|
|
* Never block the SDL main loop
|
|
|
|
Required HTTP headers:
|
|
|
|
```
|
|
apikey: SUPABASE_ANON_KEY
|
|
Authorization: Bearer SUPABASE_ANON_KEY
|
|
Content-Type: application/json
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Submit Highscore (POST)
|
|
|
|
Implement:
|
|
|
|
```cpp
|
|
void SubmitHighscoreAsync(const HighscoreEntry& entry);
|
|
```
|
|
|
|
Behavior:
|
|
|
|
* Convert entry to JSON
|
|
* POST to `/rest/v1/highscores`
|
|
* On failure:
|
|
|
|
* Log error
|
|
* Do NOT crash
|
|
* Optionally store JSON locally for retry
|
|
|
|
Example JSON payload:
|
|
|
|
```json
|
|
{
|
|
"score": 123456,
|
|
"lines": 240,
|
|
"level": 37,
|
|
"time_sec": 1820,
|
|
"name": "P1 & P2",
|
|
"game_type": "cooperate",
|
|
"timestamp": 1710000000
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Fetch Leaderboard (GET)
|
|
|
|
Implement:
|
|
|
|
```cpp
|
|
std::vector<HighscoreEntry> FetchHighscores(
|
|
const std::string& gameType,
|
|
int limit
|
|
);
|
|
```
|
|
|
|
REST query examples:
|
|
|
|
Classic:
|
|
|
|
```
|
|
?game_type=eq.classic&order=score.desc&limit=20
|
|
```
|
|
|
|
Challenge:
|
|
|
|
```
|
|
?game_type=eq.challenge&order=level.desc,time_sec.asc&limit=20
|
|
```
|
|
|
|
Cooperate:
|
|
|
|
```
|
|
?game_type=eq.cooperate&order=score.desc&limit=20
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Threading Model
|
|
|
|
* Use `std::thread` or a simple job queue
|
|
* Network calls must not run on the render thread
|
|
* Use mutex or lock-free queue to pass results back to UI
|
|
|
|
---
|
|
|
|
## 9. Error Handling Rules
|
|
|
|
* If Supabase is unreachable:
|
|
|
|
* Game continues normally
|
|
* Leaderboard screen shows "Offline"
|
|
* Never block gameplay
|
|
* Never show raw network errors to player
|
|
|
|
---
|
|
|
|
## 10. Security Constraints
|
|
|
|
* API key is public (acceptable for highscores)
|
|
* Obfuscate key in binary if possible
|
|
* Do NOT trust client-side data (future server validation planned)
|
|
|
|
---
|
|
|
|
## 11. File Structure Suggestion
|
|
|
|
```
|
|
/network
|
|
supabase_client.h
|
|
supabase_client.cpp
|
|
|
|
/highscores
|
|
highscore_submit.cpp
|
|
highscore_fetch.cpp
|
|
```
|
|
|
|
---
|
|
|
|
## 12. Acceptance Criteria
|
|
|
|
* Highscores are submitted after game over
|
|
* Leaderboards load without blocking gameplay
|
|
* Works for all four game types
|
|
* Offline mode does not crash or freeze
|
|
* Code is clean, modular, and SDL3-safe
|
|
|
|
---
|
|
|
|
## 13. Summary for the Agent
|
|
|
|
Integrate Supabase highscores into Spacetris using REST calls from C++ with libcurl. Use async submission and fetching. Support classic, challenge, cooperate, and versus modes. Ensure non-blocking behavior and graceful offline handling.
|