using Godot; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.Json; namespace TheGame { public class SaveData { public GameSeed GameSeed { get; set; } public List Instances { get; set; } = new List(); // Backward compatibility public float GameTime { get; set; } public DateTime SaveDate { get; set; } public string SaveName { get; set; } public string DisplayName { get; set; } = ""; public SaveData() { GameSeed = new GameSeed(); } public SaveData(GameSeed gameSeed) { GameSeed = gameSeed; } public SaveInstance GetLatestInstance() { if (Instances.Count == 0) return null; return Instances.OrderByDescending(i => i.SaveDate).First(); } public SaveInstance GetInstanceWithHighestGameTime() { if (Instances.Count == 0) return null; return Instances.OrderByDescending(i => i.GameTime).First(); } } public class SaveManager { private readonly string _saveDirectory; public SaveManager() { // Använd user data directory istället för executable directory string userDataDir = OS.GetUserDataDir(); _saveDirectory = Path.Combine(userDataDir, "saves"); // Skapa saves mapp om den inte finns if (!Directory.Exists(_saveDirectory)) { Directory.CreateDirectory(_saveDirectory); GD.Print($"Created saves directory: {_saveDirectory}"); } else { GD.Print($"Using saves directory: {_saveDirectory}"); } } public bool SaveGame(float gameTime, string displayName = "", GameSeed gameSeed = null, bool overwriteLatest = true) { try { // Om ingen seed angiven, använd nuvarande eller skapa ny if (gameSeed == null) { gameSeed = GameState.CurrentGameSeed ?? new GameSeed(); GameState.CurrentGameSeed = gameSeed; } // Sök efter befintlig SaveData för denna seed var existingSaveData = FindSaveDataBySeed(gameSeed); if (existingSaveData == null) { // Skapa ny SaveData för denna seed existingSaveData = new SaveData(gameSeed); } // Skapa ny instans var newInstance = new SaveInstance(gameTime, displayName); if (overwriteLatest && existingSaveData.Instances.Count > 0) { // Skriv över den senaste instansen var latestInstance = existingSaveData.GetLatestInstance(); existingSaveData.Instances.Remove(latestInstance); } existingSaveData.Instances.Add(newInstance); // Spara till fil bool saveSuccess = SaveSeedToFile(existingSaveData); if (saveSuccess) { GD.Print($"Game saved - Seed: {gameSeed.SeedValue}, Instance: {newInstance.DisplayName}"); return true; } else { GD.PrintErr($"Failed to save game - Seed: {gameSeed.SeedValue}"); return false; } } catch (Exception ex) { GD.PrintErr($"Error saving game: {ex.Message}"); return false; } } public SaveData FindSaveDataBySeed(GameSeed gameSeed) { string fileName = $"seed_{gameSeed.SeedValue}.json"; string filePath = Path.Combine(_saveDirectory, fileName); if (File.Exists(filePath)) { try { string jsonString = File.ReadAllText(filePath); var saveData = JsonSerializer.Deserialize(jsonString); return saveData; } catch (Exception ex) { GD.PrintErr($"Failed to load seed file {filePath}: {ex.Message}"); } } return null; } private bool SaveSeedToFile(SaveData saveData) { string fileName = $"seed_{saveData.GameSeed.SeedValue}.json"; string filePath = Path.Combine(_saveDirectory, fileName); try { string jsonString = JsonSerializer.Serialize(saveData, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(filePath, jsonString); GD.Print($"Seed saved to: {filePath}"); return true; } catch (Exception ex) { GD.PrintErr($"Failed to save seed file: {ex.Message}"); return false; } } public List GetSavedGames() { var savedGames = new List(); GD.Print($"Looking for saves in: {_saveDirectory}"); if (!Directory.Exists(_saveDirectory)) { GD.Print("Save directory does not exist"); return savedGames; } try { // Ladda både nya seed-filer och gamla format för backward compatibility var allFiles = Directory.GetFiles(_saveDirectory, "*.json"); GD.Print($"Found {allFiles.Length} save files"); foreach (string filePath in allFiles) { GD.Print($"Processing save file: {filePath}"); try { string jsonString = File.ReadAllText(filePath); if (Path.GetFileName(filePath).StartsWith("seed_")) { // Ny seed-baserad fil var saveData = JsonSerializer.Deserialize(jsonString); if (saveData != null && saveData.Instances.Count > 0) { savedGames.Add(saveData); GD.Print($"Successfully loaded seed: {saveData.GameSeed.SeedValue} with {saveData.Instances.Count} instances"); } } else { // Gammal fil - konvertera till nytt format var oldSaveData = JsonSerializer.Deserialize>(jsonString); if (oldSaveData != null) { var convertedSave = ConvertOldSaveFormat(oldSaveData); if (convertedSave != null) { savedGames.Add(convertedSave); GD.Print($"Converted old save format"); } } } } catch (Exception ex) { GD.PrintErr($"Failed to load save file {filePath}: {ex.Message}"); } } // Sortera efter senaste aktivitet savedGames = savedGames.OrderByDescending(s => s.GetLatestInstance()?.SaveDate ?? DateTime.MinValue).ToList(); GD.Print($"Total loaded saves: {savedGames.Count}"); } catch (Exception ex) { GD.PrintErr($"Failed to read saves directory: {ex.Message}"); } return savedGames; } private SaveData ConvertOldSaveFormat(Dictionary oldData) { try { // Extrahera värden från gammal format var gameTime = Convert.ToSingle(oldData.GetValueOrDefault("GameTime", 0f)); var saveDateStr = oldData.GetValueOrDefault("SaveDate", "")?.ToString(); var displayName = oldData.GetValueOrDefault("DisplayName", "")?.ToString(); if (DateTime.TryParse(saveDateStr, out DateTime saveDate)) { var gameSeed = new GameSeed($"OLD_{DateTime.Now.Ticks % 100000000:X}", "Converted Save"); var saveData = new SaveData(gameSeed); var instance = new SaveInstance(gameTime, displayName ?? "Converted Save"); instance.SaveDate = saveDate; saveData.Instances.Add(instance); return saveData; } } catch (Exception ex) { GD.PrintErr($"Failed to convert old save format: {ex.Message}"); } return null; } public bool LoadGame(SaveData saveData, SaveInstance instance = null) { try { // Om ingen specifik instans angiven, ta den med högst speltid if (instance == null) { instance = saveData.GetInstanceWithHighestGameTime(); } if (instance == null) { GD.PrintErr("No valid instance found to load"); return false; } GameState.LoadedGameTime = instance.GameTime; GameState.CurrentGameSeed = saveData.GameSeed; GameState.LoadedInstance = instance; GD.Print($"Loaded game - Seed: {saveData.GameSeed.SeedValue}, Instance: {instance.DisplayName}, Time: {instance.GetFormattedGameTime()}"); return true; } catch (Exception ex) { GD.PrintErr($"Failed to load game: {ex.Message}"); return false; } } } }