feat(sprint1-step3b): backend save system + anti-cheat + données rattrapées
- game_saves table + migration 002 (JSON state, anti-cheat metadata) - saveControllers.js : load/save avec validation delta ressources (750k/s × 1.1) - GameSaveManager : upsert MySQL ON DUPLICATE KEY UPDATE - useSaveSync hook : auto-save 30s + keepalive beforeunload + guest fallback - save-validation.test.ts : 8 tests anti-cheat - economy.ts : arbre d'évolution 5 nœuds + prestige ADN (rattrapage step 2) - economy.test.ts : +40 tests (évolution tree, multipliers, start bonus) - GDD + SPRINT1.md : docs sprint complètes - Rethème data : shop.json, Achievements.json, Cookie, Legal (rattrapage step 1)
This commit is contained in:
192
docs/GDD.md
192
docs/GDD.md
@@ -1,76 +1,188 @@
|
||||
# Clickerz — GDD Minimal
|
||||
# Clickerz — GDD (Game Design Document)
|
||||
|
||||
> Sprint 1 — Step 1 output
|
||||
> Date : 2026-03-17
|
||||
> Tetard Universe — Clicker/idle hybride
|
||||
> Dernière mise à jour : 2026-03-20
|
||||
> Repo : git.tetardtek.com/Tetardtek/clickerz
|
||||
> URL : https://clickerz.tetardtek.com/
|
||||
|
||||
---
|
||||
|
||||
## Identité
|
||||
|
||||
**Clickerz** — Clicker/idle hybride dans le Tetard Universe.
|
||||
Un marais mystérieux où des têtards naissent, évoluent, mutent et bâtissent un écosystème.
|
||||
Chaque prestige = une nouvelle "génération" de têtards, plus forte, plus étrange.
|
||||
|
||||
**Archétype :** hybride — clicker au départ (onboarding immédiat), idle dominant en mid-game (rétention), couche stratégique en late-game (prestige + arbre permanent).
|
||||
|
||||
---
|
||||
|
||||
## Univers — Tetard Universe
|
||||
|
||||
Le joueur est le **Gardien du Marais**. Les têtards sont la ressource vivante — ils naissent, travaillent, évoluent. Le marais grandit, se diversifie, attire de nouvelles espèces.
|
||||
|
||||
Cross-promo naturelle avec TetaRdPG (même univers, assets partageables à terme).
|
||||
|
||||
### Vocabulaire in-game
|
||||
|
||||
| Concept mécanique | Nom in-game | Icône |
|
||||
|-------------------|-------------|-------|
|
||||
| Ressource principale | **Têtards** | 🥚 |
|
||||
| Click | **Ponte** | tap/click |
|
||||
| Générateurs tier 1 | **Nid** | 🪹 |
|
||||
| Générateurs tier 2 | **Mare** | 🌊 |
|
||||
| Générateurs tier 3 | **Marécage** | 🏞️ |
|
||||
| Générateurs tier 4 | **Étang Ancien** | 🏛️ |
|
||||
| Générateurs tier 5 | **Lac Mystique** | ✨ |
|
||||
| Prestige currency | **ADN Ancestral** | 🧬 |
|
||||
| Prestige reset | **Nouvelle Génération** | 🔄🐸 |
|
||||
| Arbre permanent | **Arbre d'Évolution** | 🌳 |
|
||||
| Milestones | **Mutations** | 🧪 |
|
||||
|
||||
---
|
||||
|
||||
## Stack technique
|
||||
|
||||
**React + TypeScript + Vite** — vanilla, sans moteur de jeu
|
||||
|
||||
Justification : prototype existant déjà en React/Vite (Xmass Clicker), shop.json et Achievements.json validés, backend Node.js en place. Phaser/PixiJS = overhead injustifié pour un clicker — la logique est dans les chiffres, pas dans le rendu.
|
||||
| Couche | Techno | Justification |
|
||||
|--------|--------|---------------|
|
||||
| Frontend | React 18 + TypeScript + Vite | Existant validé, lazy calc pattern |
|
||||
| State | Zustand | Game loop adapté, léger |
|
||||
| Style | Tailwind CSS (migration SCSS → Tailwind) | Productivité, cohérence |
|
||||
| Backend | Express + MySQL | Existant avec SuperOAuth câblé |
|
||||
| Auth | SuperOAuth (clickerz.tetardtek.com) | SSO Tetardtek ecosystem |
|
||||
| Tests | Vitest | 13 tests existants sur economy.ts |
|
||||
|
||||
---
|
||||
|
||||
## Mécaniques core
|
||||
|
||||
**Ressource principale** : Cookies (ou ressource thématique à nommer)
|
||||
### Ressource principale : Têtards
|
||||
|
||||
**Sources de production** :
|
||||
- Clic manuel : +1 ressource/clic (multiplicateur upgradable)
|
||||
- Générateurs idle : 5 tiers, coût `base × 1.15^n`, production `/s` cumulative
|
||||
**Sources de production :**
|
||||
- Ponte (clic manuel) : +1 × clickMultiplier × prestigeMultiplier
|
||||
- Générateurs idle : 5 tiers, coût `base × 1.15^owned`, production/s cumulative
|
||||
|
||||
**Tiers upgrades** (structure shop.json existante — x10 de coût par tier validé) :
|
||||
| Tier | Coût base | Production/s |
|
||||
|------|-----------|-------------|
|
||||
| 1 | 10 | 0.1 |
|
||||
| 2 | 100 | 0.5 |
|
||||
| 3 | 1 000 | 3 |
|
||||
| 4 | 10 000 | 20 |
|
||||
| 5 | 100 000 | 150 |
|
||||
### Générateurs — progression tier
|
||||
|
||||
| Tier | Nom | Coût base | Production/s | Ratio scaling |
|
||||
|------|-----|-----------|-------------|---------------|
|
||||
| 1 | Nid | 10 | 0.1 | 1.15 |
|
||||
| 2 | Mare | 100 | 0.5 | 1.15 |
|
||||
| 3 | Marécage | 1 000 | 3 | 1.15 |
|
||||
| 4 | Étang Ancien | 10 000 | 20 | 1.15 |
|
||||
| 5 | Lac Mystique | 100 000 | 150 | 1.15 |
|
||||
|
||||
**Formule coût :** `coût = base_cost × 1.15^owned`
|
||||
**Formule production :** `output = base_prod × owned × multipliers`
|
||||
|
||||
> Ratio 1.15 = standard éprouvé. Assez steep pour forcer la diversification, assez doux pour que chaque achat ait un impact.
|
||||
|
||||
---
|
||||
|
||||
## Boucle de progression
|
||||
## Boucle de progression — 3 couches
|
||||
|
||||
**Prestige / Reset**
|
||||
- Seuil déclencheur : 1 000 000 ressources (ajustable à l'équilibrage)
|
||||
- Récompense : +0.1× multiplicateur permanent par reset (stackable)
|
||||
- Reset : ressources + générateurs à 0, upgrades prestige conservés
|
||||
- Courbe : reset 1 = ×1.1, reset 10 = ×2.0, reset 50 = ×6.0
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ BOUCLE 1 — La Run (secondes → minutes) │
|
||||
│ │
|
||||
│ Ponte (click) → +têtards │
|
||||
│ Acheter Nid → +têtards/sec (idle) │
|
||||
│ Upgrades Nid → multiplicateur │
|
||||
│ Débloquer Mare → nouveau tier, plus cher, │
|
||||
│ plus rentable │
|
||||
│ ...jusqu'à atteindre un plateau │
|
||||
└──────────────────────┬──────────────────────────┘
|
||||
│ plateau atteint
|
||||
▼
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ BOUCLE 2 — Nouvelle Génération (heures → jours) │
|
||||
│ │
|
||||
│ Prestige → reset générateurs + têtards │
|
||||
│ Gain : ADN Ancestral (formule sur total têtards) │
|
||||
│ ADN → Arbre d'Évolution (permanent) │
|
||||
│ → +% production globale │
|
||||
│ → débloquer nouvelles mutations │
|
||||
│ → débloquer nouveaux types de générateurs │
|
||||
│ Nouvelle run = plus rapide, va plus loin │
|
||||
└──────────────────────┬──────────────────────────┘
|
||||
│ arbre mature
|
||||
▼
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ BOUCLE 3 — Méta (semaines) [Sprint 3+] │
|
||||
│ │
|
||||
│ Espèces rares, événements saisonniers, │
|
||||
│ leaderboard, objectifs communautaires │
|
||||
│ (hors scope Sprint 1) │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Milestones visibles** : barre de progression vers prestige, compteur resets, multiplicateur actuel affiché
|
||||
---
|
||||
|
||||
## Prestige — Nouvelle Génération
|
||||
|
||||
**Seuil :** 1 000 000 têtards produits (total lifetime de la run)
|
||||
**Formule ADN :** `adn = floor(150 × sqrt(lifetime_tadpoles / 1e9))`
|
||||
|
||||
**Ce qui reset :** têtards, générateurs, upgrades de run
|
||||
**Ce qui persiste :** ADN Ancestral, Arbre d'Évolution, achievements, stats
|
||||
|
||||
**Prestige actuel (hérité) :** `+0.1× multiplicateur permanent par reset`
|
||||
**Cible Sprint 1 :** migrer vers ADN Ancestral + Arbre d'Évolution
|
||||
|
||||
---
|
||||
|
||||
## Arbre d'Évolution (permanent — jamais reset)
|
||||
|
||||
Sprint 1 — linéaire (5 nœuds). Sprint 2+ → branches.
|
||||
|
||||
| Nœud | Coût ADN | Effet |
|
||||
|------|----------|-------|
|
||||
| Ponte Améliorée | 1 | +100% click power |
|
||||
| Instinct Grégaire | 3 | +50% production tous générateurs |
|
||||
| Mémoire Génétique | 10 | Commence chaque run avec 100 têtards |
|
||||
| Mutation Alpha | 25 | Débloquer tier 5 dès le début de la run |
|
||||
| Symbiose | 50 | +1% production par achievement débloqué |
|
||||
|
||||
---
|
||||
|
||||
## Sauvegarde & Anti-triche
|
||||
|
||||
- Save côté serveur uniquement (backend Express + MySQL)
|
||||
- Pas de localStorage pour les données de jeu (cache UI uniquement)
|
||||
- Auto-save toutes les 30 secondes via API
|
||||
- Validation snapshot : `elapsed_time × max_possible_production × 1.1 >= claimed_resources`
|
||||
- Client considéré hostile — toute donnée validée côté serveur
|
||||
|
||||
---
|
||||
|
||||
## Monétisation
|
||||
|
||||
**Cosmétiques only** — pas de pay-to-win
|
||||
|
||||
- Thèmes visuels (couleurs, icônes)
|
||||
- Titres / badges de prestige
|
||||
- Effets de clic (particules)
|
||||
- Thèmes visuels (couleurs, icônes marais)
|
||||
- Titres / badges de génération
|
||||
- Effets de ponte (particules)
|
||||
- Raison : 0 compliance fiscale, 0 déséquilibre économie, communauté saine
|
||||
|
||||
---
|
||||
|
||||
## Sauvegarde
|
||||
|
||||
- localStorage (sprint 1 — immédiat, zéro infra)
|
||||
- Sync API backend (backend déjà en place — câblage sprint 1 si temps le permet)
|
||||
- Auto-save toutes les 30 secondes
|
||||
|
||||
---
|
||||
|
||||
## Hors scope Sprint 1
|
||||
|
||||
- Leaderboard (exclu — infra ranking = sprint 2)
|
||||
- Boucle 3 (méta, events, leaderboard)
|
||||
- Branches arbre d'évolution (linéaire suffit)
|
||||
- Cosmétiques / skins
|
||||
- Monétisation effective
|
||||
- Sound / musique
|
||||
- Mobile responsive (desktop first)
|
||||
- Offline gains calculés côté serveur (Sprint 2)
|
||||
- Migration Express → Fastify (si besoin Sprint 3+)
|
||||
- Intégration Twitch
|
||||
- Multijoueur
|
||||
|
||||
---
|
||||
|
||||
## Prochaines étapes → Step 2
|
||||
## Changelog
|
||||
|
||||
Fondations techniques : init projet React/TS/Vite, boucle core clic → +ressource, 1er générateur idle, 1er upgrade.
|
||||
| Date | Changement |
|
||||
|------|------------|
|
||||
| 2026-03-17 | GDD initial — sprint1-step1, stack React+TS+Vite, mécaniques core |
|
||||
| 2026-03-20 | Refonte game-designer — Tetard Universe, Arbre d'Évolution, anti-triche backend, SuperOAuth, stack confirmée Express |
|
||||
|
||||
167
docs/SPRINT1.md
Normal file
167
docs/SPRINT1.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# SPRINT1.md — Fondations Tetard Universe
|
||||
|
||||
> Brief technique — Sprint 1
|
||||
> Date : 2026-03-20
|
||||
> Réf GDD : docs/GDD.md
|
||||
> Agents : game-designer (design) → build (implémentation)
|
||||
|
||||
---
|
||||
|
||||
## Objectif
|
||||
|
||||
Transformer le prototype Xmass Clicker en Clickerz Tetard Universe avec :
|
||||
- Rethème complet (noms, visuels, textes)
|
||||
- Arbre d'Évolution (permanent, jamais reset)
|
||||
- Save serveur (anti-triche, fin du localStorage)
|
||||
- SuperOAuth login
|
||||
- Core loop jouable de bout en bout : Ponte → Générateurs → Prestige → Arbre → Nouvelle run
|
||||
|
||||
---
|
||||
|
||||
## Existant à conserver
|
||||
|
||||
| Composant | Fichier | État |
|
||||
|-----------|---------|------|
|
||||
| Core economy | `Frontend/src/core/economy.ts` | ✅ Solide — lazy calc, 5 generators, prestige |
|
||||
| Tests economy | `Frontend/src/__tests__/economy.test.ts` | ✅ 13 tests |
|
||||
| Backend auth | `Backend/src/controllers/authControllers.js` | ✅ JWT + SuperOAuth ID |
|
||||
| DB schema | `Backend/database/schema.sql` | ✅ users + super_oauth_id |
|
||||
| Prestige UI | Commit 9f0ccda | ✅ PrestigePanel + MilestoneBar |
|
||||
|
||||
---
|
||||
|
||||
## Steps
|
||||
|
||||
### Step 1 — Rethème Tetard Universe
|
||||
|
||||
**Scope :** Renommage complet, zéro changement mécanique.
|
||||
|
||||
- [ ] `economy.ts` : renommer generators (Manic → Nid, Tasse à café → Mare, Sucre → Marécage, Usine → Étang Ancien, Portail → Lac Mystique)
|
||||
- [ ] `shop.json` : réécrire avec noms/descriptions Tetard Universe (ou supprimer si redondant avec economy.ts)
|
||||
- [ ] `Achievements.json` : adapter les textes au thème marais
|
||||
- [ ] UI : remplacer "cookies" / "Xmass" par "têtards" / "Clickerz" partout
|
||||
- [ ] Pages : Cookie.jsx (page légale) → adapter mentions "Xmass Clicker" → "Clickerz"
|
||||
- [ ] Titre / meta : "Clickerz — Tetard Universe"
|
||||
|
||||
**Critère done :** aucune référence à "cookie", "Xmass", "Noël" dans le code.
|
||||
|
||||
---
|
||||
|
||||
### Step 2 — Arbre d'Évolution
|
||||
|
||||
**Scope :** Nouveau système permanent, intégré au prestige.
|
||||
|
||||
- [ ] Nouveau type `EvolutionNode` dans economy.ts :
|
||||
```ts
|
||||
interface EvolutionNode {
|
||||
id: string;
|
||||
name: string;
|
||||
cost: number; // en ADN Ancestral
|
||||
effect: EffectType; // multiplicateur, flat bonus, unlock
|
||||
value: number;
|
||||
unlocked: boolean;
|
||||
requires?: string; // id du nœud prérequis (linéaire Sprint 1)
|
||||
}
|
||||
```
|
||||
- [ ] Étendre `GameState` : ajouter `ancestralDna: number`, `evolutionTree: EvolutionNode[]`
|
||||
- [ ] Modifier `applyPrestige()` : calculer ADN gagné via `floor(150 × sqrt(lifetime / 1e9))`, ajouter à `ancestralDna`
|
||||
- [ ] 5 nœuds linéaires (GDD : Ponte Améliorée → Instinct Grégaire → Mémoire Génétique → Mutation Alpha → Symbiose)
|
||||
- [ ] `buyEvolutionNode(state, nodeId)` : acheter si ADN suffisant + prérequis débloqué
|
||||
- [ ] Appliquer les effets dans `totalProductionPerSecond()` et `applyClick()`
|
||||
- [ ] UI : `EvolutionTree.tsx` — panel visible après premier prestige
|
||||
- [ ] Tests : couvrir achat nœud, prérequis, effets sur production
|
||||
|
||||
**Critère done :** un joueur peut prestige, gagner de l'ADN, acheter des nœuds, et constater l'effet sur sa prochaine run.
|
||||
|
||||
---
|
||||
|
||||
### Step 3 — Save serveur + anti-triche
|
||||
|
||||
**Scope :** Migrer la persistence de localStorage vers API backend.
|
||||
|
||||
- [ ] Backend : nouvelle table `game_saves`
|
||||
```sql
|
||||
CREATE TABLE game_saves (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL UNIQUE,
|
||||
game_state JSON NOT NULL,
|
||||
last_save TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
lifetime_tadpoles BIGINT DEFAULT 0,
|
||||
prestige_count INT DEFAULT 0,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
);
|
||||
```
|
||||
- [ ] Backend routes : `POST /api/save` (write), `GET /api/save` (load) — JWT required
|
||||
- [ ] Validation snapshot sur `POST /api/save` :
|
||||
- Vérifier `elapsed_time × max_possible_production × 1.1 >= claimed_resources`
|
||||
- Si invalide → rejeter le save, logger l'anomalie
|
||||
- [ ] Frontend : `useSaveSync` hook — auto-save toutes les 30s via API
|
||||
- [ ] Frontend : load state depuis API au login (pas de localStorage game data)
|
||||
- [ ] Supprimer la persistence localStorage pour les données de jeu
|
||||
|
||||
**Critère done :** fermer l'onglet, rouvrir, login → retrouver exactement son état. F12 → modifier localStorage → aucun impact sur la save serveur.
|
||||
|
||||
---
|
||||
|
||||
### Step 4 — SuperOAuth login
|
||||
|
||||
**Scope :** Câbler le login via SuperOAuth existant.
|
||||
|
||||
- [ ] Vérifier le flow SuperOAuth backend (verifyOAuth.js existe)
|
||||
- [ ] Frontend : page Login avec bouton "Se connecter avec SuperOAuth"
|
||||
- [ ] Redirect vers SuperOAuth → callback → JWT → session
|
||||
- [ ] Protéger les routes /api/save derrière JWT
|
||||
- [ ] Fallback : mode "invité" sans save serveur (localStorage temporaire) — optionnel
|
||||
|
||||
**Critère done :** login SuperOAuth → jeu avec save serveur. Pas de register custom (SuperOAuth gère).
|
||||
|
||||
---
|
||||
|
||||
### Step 5 — Migration SCSS → Tailwind + Zustand
|
||||
|
||||
**Scope :** Moderniser le frontend pour la suite.
|
||||
|
||||
- [ ] Installer Tailwind CSS + config Vite
|
||||
- [ ] Migrer les composants clés (game view, shop, prestige panel) vers Tailwind
|
||||
- [ ] Installer Zustand, créer `useGameStore` — remplacer le state lifting actuel
|
||||
- [ ] Intégrer le game loop tick dans Zustand (requestAnimationFrame ou setInterval 1s)
|
||||
- [ ] Supprimer les fichiers SCSS migrés
|
||||
|
||||
**Critère done :** game loop tourne via Zustand, UI en Tailwind, SCSS supprimé sur les composants migrés.
|
||||
|
||||
---
|
||||
|
||||
### Step 6 — Polish & deploy
|
||||
|
||||
**Scope :** Rendre jouable et déployer.
|
||||
|
||||
- [ ] UI : écran d'accueil Clickerz (logo, "Entrer dans le Marais")
|
||||
- [ ] UI : feedback visuel Ponte (animation click)
|
||||
- [ ] UI : affichage formaté des grands nombres (1M, 1B, 1T...)
|
||||
- [ ] UI : responsive basique (jouable desktop, pas cassé mobile)
|
||||
- [ ] Deploy : clickerz.tetardtek.com (Apache vhost + pm2 backend)
|
||||
- [ ] Tests e2e : flow complet login → jeu → prestige → arbre → save → reload
|
||||
|
||||
**Critère done :** un joueur peut aller sur clickerz.tetardtek.com, login SuperOAuth, jouer, prestige, acheter dans l'arbre, fermer, revenir, retrouver sa progression.
|
||||
|
||||
---
|
||||
|
||||
## Résumé séquentiel
|
||||
|
||||
```
|
||||
Step 1 (rethème) → Step 2 (arbre évolution) → Step 3 (save serveur)
|
||||
→ Step 4 (SuperOAuth) → Step 5 (Tailwind+Zustand) → Step 6 (polish+deploy)
|
||||
```
|
||||
|
||||
Steps 1-2 = game design. Steps 3-4 = infra/auth. Step 5 = DX. Step 6 = ship.
|
||||
|
||||
---
|
||||
|
||||
## Risques identifiés
|
||||
|
||||
| Risque | Mitigation |
|
||||
|--------|------------|
|
||||
| Équilibrage ADN trop généreux/avare | Playtest après step 2, ajuster la formule |
|
||||
| SuperOAuth SDK pas à jour | verifyOAuth.js existe déjà — vérifier compat |
|
||||
| Migration SCSS → Tailwind longue | Migrer uniquement les composants touchés, pas tout |
|
||||
| Validation anti-triche trop stricte (faux positifs) | Marge ×1.1, logs avant rejet, soft-block d'abord |
|
||||
Reference in New Issue
Block a user