Aller au contenu principal

Projet 08 : Persistent system

Dans le Projet 07, ta mission accordait de l'argent via un drapeau en mémoire vive. Dans le Projet 08, tu franchis une étape déterminante vers l'ingénierie logicielle : concevoir un moteur de réputation de factions où ton rang auprès des Families et des Ballas est sauvegardé sur disque, survit à la fermeture du jeu et encaisse les fichiers corrompus sans jamais faire planter le moteur.


La mission

Concevoir un système de persistance disque résilient remplissant six objectifs majeurs :

  1. Sérialiser et désérialiser des données de profil structurées en JSON via System.Text.Json.
  2. Créer automatiquement l'arborescence de dossiers cible (scripts/my_mod/) à la volée sans lever d'exception.
  3. Charger les données au premier tick et afficher une notification confirmant la réputation active et la version du schéma.
  4. Mettre en œuvre une tolérance aux pannes en deux vagues : créer des valeurs par défaut si le fichier manque, et récupérer proprement un JSON corrompu.
  5. Protéger le système contre les évolutions de schéma futures grâce à un contrôle de version entier (Profile.CurrentVersion).
  6. Sauvegarder l'état sur disque lors du déchargement du script dans OnAborted.

Spécifications, contraintes

  • Résilience absolue aux pannes : encapsuler toutes les opérations d'E/S et de parsing JSON dans des blocs try-catch défensifs ; un fichier corrompu doit basculer sur les données par défaut sans faire planter le jeu.
  • Gestion explicite des versions : maintenir un champ entier Version dans le modèle de données afin de repérer les formats obsolètes ou incompatibles.
  • Journalisation secondaire silencieuse : l'écriture de logs dans profile.log ne doit en aucun cas lever d'exception non gérée ni perturber l'expérience de jeu.
  • Formatage lisible par un humain : indenter le fichier JSON généré avec new JsonSerializerOptions { WriteIndented = true }.
  • Sauvegarde au déchargement : enregistrer les données actives dans OnAborted pour prévenir toute perte d'avancement.

Étapes de réalisation

  1. Définir le modèle de données : crée une classe Profile contenant Version, Reputation et un Dictionary<string, int> FactionStandings.
  2. Déclarer le script de persistance : dans JsonPersistence, définis le chemin du fichier et un champ privé _profile.
  3. Brancher les événements : dans le constructeur, enregistre des gestionnaires pour Tick et Aborted.
  4. Programmer le chargement différé : dans OnTick, vérifie si _profile est nul. Si oui, initialise-le avec LoadProfile() et affiche un téléscripteur d'information.
  5. Bâtir le chargement défensif dans LoadProfile :
    • Vérifier File.Exists(SavePath). Si absent, instancier DefaultProfile(), l'enregistrer sur disque et le renvoyer.
    • Lire le texte et désérialiser vers Profile.
    • Contrôler la compatibilité de version : si la version diffère de Profile.CurrentVersion, consigner un avertissement et renvoyer les données par défaut.
    • Encadrer le tout dans un try-catch pour récupérer toute erreur de syntaxe JSON et renvoyer le profil par défaut.
  6. Programmer la sauvegarde défensive dans SaveProfile :
    • S'assurer de l'existence du dossier parent avec Directory.CreateDirectory.
    • Sérialiser avec indentation et écrire le fichier.
  7. Créer la journalisation silencieuse : ajouter des lignes horodatées dans profile.log au sein d'un try-catch muet.
  8. Sauvegarder à l'arrêt : dans OnAborted, exécuter SaveProfile(_profile).

APIs, outils à explorer

  • System.Text.Json.JsonSerializer.Serialize<T>(T value, JsonSerializerOptions options) : convertit des objets .NET en texte JSON.
  • System.Text.Json.JsonSerializer.Deserialize<T>(string json) : reconstruit des objets C# typés à partir d'une chaîne JSON.
  • System.IO.File.ReadAllText(string path) / File.WriteAllText(string path, string contents) : lit et écrit l'intégralité d'un fichier texte.
  • System.IO.Directory.CreateDirectory(string path) : crée récursivement tous les répertoires et sous-répertoires du chemin spécifié.
  • System.Collections.Generic.Dictionary<TKey, TValue> : dictionnaire clé-valeur pour stocker les scores des différentes factions.

Critères de validation

Ton mod est validé dès que :

  • Premier lancement sans fichier : profile.json est généré avec les valeurs par défaut, et la notification affiche "Reputation chargee : 100 (v1)".
  • Inspection du fichier profile.json : le document est indenté et contient la version 1, 100 de réputation et les scores des Families (50) et Ballas (-50).
  • Corruption du fichier avec du texte incohérent : au rechargement, le script restaure les valeurs par défaut sans planter et consigne l'erreur dans profile.log.
  • Modification de "Version": 99 dans le JSON : le script détecte l'incompatibilité, bascule sur les valeurs par défaut et poursuit sa route.
  • Rechargement avec Inser : le profil actif est sauvegardé sur disque sans perte de données.

Solution, explications

Partner
Solution vérifiée et explications du code

Le sujet, les contraintes et les étapes de réalisation restent 100% libres pour t'exercer par toi-même. Le code source de référence vérifié et les explications détaillées de production sont réservés aux membres du tier Partner.