'Méthode non autorisée.']); exit; } requireLemonAuth(); requireCsrfToken(); $score = $_POST['score'] ?? null; $lifetimeScore = $_POST['lifetime_score'] ?? null; $prestigeLevel = $_POST['prestige_level'] ?? null; $prestigeBonus = $_POST['prestige_bonus'] ?? null; $gameState = $_POST['game_state'] ?? null; // Validation basique : évite qu'une requête forgée n'enregistre n'importe quoi if ( !is_numeric($score) || $score < 0 || !is_numeric($lifetimeScore) || $lifetimeScore < 0 || !is_numeric($prestigeLevel) || $prestigeLevel < 0 || !is_numeric($prestigeBonus) || $prestigeBonus < 0 ) { http_response_code(400); echo json_encode(['error' => 'Données de sauvegarde invalides.']); exit; } // game_state : JSON de taille raisonnable (20 Ko largement suffisant pour la liste // des bâtiments/améliorations possédés), sinon on refuse plutôt que de tronquer if ($gameState !== null && (strlen($gameState) > 20000 || json_decode($gameState) === null)) { http_response_code(400); echo json_encode(['error' => 'État de jeu invalide.']); exit; } try { $stmt = $dbh->prepare(' UPDATE lemon_players SET score = :score, lifetime_score = :lifetime_score, prestige_level = :prestige_level, prestige_bonus = :prestige_bonus, game_state = :game_state, last_played = NOW() WHERE id = :id '); $stmt->bindValue(':score', (float) $score); $stmt->bindValue(':lifetime_score', (float) $lifetimeScore); $stmt->bindValue(':prestige_level', (int) $prestigeLevel, PDO::PARAM_INT); $stmt->bindValue(':prestige_bonus', (float) $prestigeBonus); $stmt->bindValue(':game_state', $gameState, $gameState === null ? PDO::PARAM_NULL : PDO::PARAM_STR); $stmt->bindValue(':id', (int) $_SESSION['lemon_player_id'], PDO::PARAM_INT); $stmt->execute(); echo json_encode(['ok' => true]); } catch (PDOException $e) { http_response_code(500); echo json_encode(['error' => 'Erreur serveur.']); }