Aller au contenu principal

Persistance

Tout ce que tu stockes dans les champs d'un script (_recompenseAttribuee, _gangMembers) s'évapore dès que tu quittes GTA V ou recharges avec Insert. Si tu souhaites qu'un niveau de réputation, une planque achetée ou des réglages de véhicule survivent d'une session à l'autre, tu dois écrire cet état sur le disque.

La bonne nouvelle : il n'existe aucune native GTA pour sauvegarder des données. Tu utilises les bibliothèques C# et .NET éprouvées : System.IO et System.Text.Json.

Le contrat de données : une classe pure

Définis une classe dédiée pour représenter ton profil de sauvegarde :

public sealed class ProfilJoueur
{
public const int VersionActuelle = 1;

public int Version { get; set; } = VersionActuelle;
public int Reputation { get; set; }
public int MissionsTerminees { get; set; }
}

Remarque la propriété Version. Quand tu feras évoluer ton mod dans six mois en ajoutant de nouveaux paramètres, vérifier Version == VersionActuelle te dira immédiatement si le fichier sur disque est compatible ou s'il doit être migré.

Écrire du JSON sur disque

Sauvegarder se fait en deux étapes : sérialiser l'objet en chaîne de caractères JSON, puis l'écrire dans un fichier au sein du dossier de ton mod :

using System.IO;
using System.Text.Json;

private const string CheminSauvegarde = "scripts/mon_mod/profil.json";

private static void SauvegarderProfil(ProfilJoueur profil)
{
try
{
string dossier = Path.GetDirectoryName(CheminSauvegarde);
if (!Directory.Exists(dossier))
{
Directory.CreateDirectory(dossier);
}

string json = JsonSerializer.Serialize(profil, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(CheminSauvegarde, json);
}
catch (Exception ex)
{
// Ne jamais crasher le jeu en cas d'échec d'écriture : journaliser et continuer
File.AppendAllText("scripts/mon_mod/erreur.log", $"Échec sauvegarde : {ex.Message}\n");
}
}

Relire et survivre aux fichiers corrompus

C'est à la lecture que les crashs surviennent : le joueur a modifié le fichier à la main en oubliant une virgule, un antivirus verrouille l'accès, ou le fichier n'existe pas encore car c'est la toute première partie.

Enferme toujours la désérialisation dans une gestion d'erreurs défensive :

private static ProfilJoueur ChargerProfil()
{
try
{
// Cas 1 : Premier lancement -> profil par défaut
if (!File.Exists(CheminSauvegarde))
{
return new ProfilJoueur();
}

string json = File.ReadAllText(CheminSauvegarde);
ProfilJoueur charge = JsonSerializer.Deserialize<ProfilJoueur>(json);

// Cas 2 : Version obsolète ou corrompue -> profil par défaut
if (charge == null || charge.Version != ProfilJoueur.VersionActuelle)
{
return new ProfilJoueur();
}

return charge;
}
catch (Exception ex)
{
// Cas 3 : Fichier endommagé -> secours immédiat sans planter le jeu
File.AppendAllText("scripts/mon_mod/erreur.log", $"Sauvegarde corrompue récupérée : {ex.Message}\n");
return new ProfilJoueur();
}
}

Remarque que ChargerProfil ne laisse jamais échapper d'exception vers la boucle de jeu. Qu'il manque, soit corrompu ou illisible, la fonction renvoie un profil sain par défaut, journalise l'erreur et laisse le joueur s'amuser.

Dans le Projet 08, nous appliquons cette architecture pour créer un système de réputation persistant.