using System; using Godot; using Godot.Collections; using FileAccess = Godot.FileAccess; namespace Babushka.scripts.CSharp.Common.Savegame; /// /// Handles the saving and loading of game states. /// Holds the central SaveData object that serves as a temporary SaveFile. /// Automatically writes to disk on every scene change. /// Uses the Godot Json Serializer, which may implicitly convert integers to floats, so be careful when extending! /// public static class SavegameService { public static string SavePath = ""; public static Dictionary SaveDatas = new (); public static bool _loaded = false; public delegate void SaveGameDelegate(); public static event SaveGameDelegate OnSaveGameReset = delegate {}; public static void AppendDataToSave( string id, Dictionary payload) { var saveData = new SaveData(); saveData.Id = id; saveData.JsonPayload = Json.Stringify(payload, indent: "\t"); AppendSave(saveData); } /// /// Adds or overwrites an entry in the SaveData dictionary. /// /// private static void AppendSave(SaveData saveData) { if (SaveDatas.TryGetValue(saveData.Id, out var value)) { SaveDatas[saveData.Id] = saveData.JsonPayload; } else { SaveDatas.Add(saveData.Id, saveData.JsonPayload); } } /// /// Checks the SaveData dictionary for an entry and returns the jsondata as a string for it. /// Requires the scenename and object ID for lookup. /// /// /// /// public static Dictionary GetSaveData(string id) { Dictionary saveData = new(); string saveDataString = ""; if (!_loaded) { return saveData; } if (SaveDatas.ContainsKey(id)) { saveDataString = SaveDatas[id]; saveData = Json.ParseString(saveDataString).AsGodotDictionary(); } return saveData; } /// /// Writes the contents of the current SaveData dictionary to disk as a json file. /// public static void Save() { string json = Json.Stringify(SaveDatas, indent: "\t"); // create cloud directory CreateSaveDirectory(); try { using var file = FileAccess.Open(SavePath, FileAccess.ModeFlags.Write); file.StoreString(json); } catch (Exception e) { GD.Print(e.Message); } } private static void CreateSaveDirectory() { System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(SavePath) ?? ""); } /// /// Loads the current savegame file from disk and parses it into the SaveData dictionary. /// public static void Load() { try { if (!System.IO.File.Exists(SavePath)) { SaveDatas = new(); CreateSaveDirectory(); } string saveDataJson = FileAccess.GetFileAsString(SavePath); if(!string.IsNullOrEmpty(saveDataJson)) SaveDatas = Json.ParseString(saveDataJson).AsGodotDictionary(); } catch(Exception e) { GD.PrintRich(e.Message); return; } _loaded = true; } public static void Reset() { SaveDatas = new (); Save(); OnSaveGameReset(); } }