|
|
---
|
|
|
description: Server-authoritative architecture blueprint — authority boundaries, WS protocol contract, and gap priorities. Reference docs/blueprint_server_authoritative.md for full details.
|
|
|
alwaysApply: true
|
|
|
---
|
|
|
|
|
|
# Server-Authoritative Architecture
|
|
|
|
|
|
Full blueprint: `docs/blueprint_server_authoritative.md`
|
|
|
|
|
|
## Authority Boundary
|
|
|
|
|
|
**Server owns:** combat simulation, damage/crit rolls, HP changes, XP/gold awards, level-ups, loot generation, buff/debuff logic, enemy spawning, death detection.
|
|
|
|
|
|
**Client owns:** rendering (PixiJS), camera, animations, walking visuals, UI overlays (HUD, HP bars, buff bars, popups), input (touch/click), sound/haptics triggered by server events.
|
|
|
|
|
|
**Client must NOT:** compute damage, roll crits, award XP/gold, generate loot, run level-up calculations, or send hero stats to server.
|
|
|
|
|
|
## WS Message Envelope (mandatory)
|
|
|
|
|
|
All messages (both directions) use `{"type": string, "payload": object}`. Text `"ping"`/`"pong"` for heartbeat (not inside envelope).
|
|
|
|
|
|
### Server → Client Events
|
|
|
|
|
|
| Type | Key Payload Fields |
|
|
|
|------|-------------------|
|
|
|
| `hero_state` | Full hero JSON (sent on connect/revive) |
|
|
|
| `combat_start` | `enemy`, `heroHp`, `heroMaxHp` |
|
|
|
| `attack` | `source` (hero\|enemy), `damage`, `isCrit`, `heroHp`, `enemyHp`, `debuffApplied` |
|
|
|
| `hero_died` | `heroHp`, `enemyHp`, `killedBy` |
|
|
|
| `combat_end` | `xpGained`, `goldGained`, `newXp`, `newGold`, `newLevel`, `leveledUp`, `loot[]` |
|
|
|
| `level_up` | `newLevel`, all stat fields |
|
|
|
| `buff_applied` | `buffType`, `magnitude`, `durationMs`, `expiresAt` |
|
|
|
| `debuff_applied` | `debuffType`, `magnitude`, `durationMs`, `expiresAt` |
|
|
|
|
|
|
### Client → Server Commands
|
|
|
|
|
|
| Type | Payload |
|
|
|
|------|---------|
|
|
|
| `request_encounter` | `{}` |
|
|
|
| `request_revive` | `{}` |
|
|
|
| `activate_buff` | `{"buffType": "rage"}` |
|
|
|
|
|
|
## Critical Gaps (P0 — must fix)
|
|
|
|
|
|
1. **GAP-1:** `SaveHero` accepts arbitrary stats — **delete it**, replace with preferences-only endpoint
|
|
|
2. **GAP-2:** Combat is client-only — wire `engine.StartCombat()` into encounter handlers
|
|
|
3. **GAP-3:** XP/gold/level client-dictated — server awards on `handleEnemyDeath`, persists to DB
|
|
|
4. **GAP-4:** Auth middleware disabled — uncomment and enforce Telegram HMAC validation
|
|
|
|
|
|
## Backend Rules
|
|
|
|
|
|
- Engine emits `WSMessage` (not raw `CombatEvent`) through `eventCh`
|
|
|
- `handleEnemyDeath` must persist hero to DB after awarding rewards
|
|
|
- WS handler extracts heroID from Telegram auth `initData`, not hardcoded
|
|
|
- On client disconnect during combat: `StopCombat(heroID)` + persist state
|
|
|
- Engine is the single writer for heroes in active combat (REST reads from engine, not DB)
|
|
|
|
|
|
## Frontend Rules
|
|
|
|
|
|
- Remove `_simulateFighting`, `_onEnemyDefeated`, `_spawnEnemy`, `_requestEncounter` (client combat sim)
|
|
|
- Remove `_serverAuthoritative` flag — always server-authoritative
|
|
|
- Remove auto-save (`_triggerSave`, `sendBeacon`, `heroStateToSaveRequest`)
|
|
|
- Walking requests encounters via WS every ~3s; server enforces cooldown
|
|
|
- Revive and buff activation go through WS commands (REST as fallback)
|
|
|
- On WS disconnect: show "Reconnecting..." overlay; server sends `hero_state` on reconnect
|
|
|
|
|
|
## Implementation Order
|
|
|
|
|
|
1. Enable auth middleware (blocks everything)
|
|
|
2. WS envelope + ping/pong + heroID from auth
|
|
|
3. Wire `StartCombat` into encounter handler
|
|
|
4. Engine events with rewards + DB persist on death
|
|
|
5. Delete `SaveHero`
|
|
|
6. Frontend: remove client combat sim, add server event handlers
|
|
|
7. Frontend: switch encounter/revive/buff to WS commands
|
|
|
8. Buff/debuff DB persistence
|
|
|
9. Server-side loot generation
|
|
|
10. CORS + WS `CheckOrigin` hardening
|
|
|
|
|
|
Steps 1–5 (backend) and 6–7 (frontend) parallelize once WS contract is agreed.
|