refactor #6

Merged
GKaszewski merged 9 commits from refactor into master 2026-02-01 11:47:42 +00:00
2 changed files with 74 additions and 17 deletions
Showing only changes of commit 432a71a00c - Show all commits

View File

@@ -1,16 +1,18 @@
using System.Collections.Generic;
using System.Text.Json;
using Godot;
using Mr.BrickAdventures.scripts.Resources;
using Mr.BrickAdventures.scripts.State;
namespace Mr.BrickAdventures.Autoloads;
/// <summary>
/// Save system that serializes POCOs directly to JSON.
/// Save system that serializes state to JSON using DTOs.
/// </summary>
public partial class SaveSystem : Node
{
[Export] public string SavePath { get; set; } = "user://savegame.json";
[Export] public int Version { get; set; } = 2; // Bumped version for new format
[Export] public int Version { get; set; } = 2;
private static readonly JsonSerializerOptions JsonOptions = new()
{
@@ -18,11 +20,6 @@ public partial class SaveSystem : Node
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
public override void _Ready()
{
// No longer needs GameManager reference - works with GameStateStore directly
}
public void SaveGame()
{
var store = GameStateStore.Instance;
@@ -32,11 +29,18 @@ public partial class SaveSystem : Node
return;
}
var saveData = new SaveData
// Convert to DTO (only serializable data)
var saveData = new SaveDataDto
{
Version = Version,
Player = store.Player,
CurrentLevel = store.Session.CurrentLevel
Coins = store.Player.Coins,
Lives = store.Player.Lives,
CurrentLevel = store.Session.CurrentLevel,
CompletedLevels = [.. store.Player.CompletedLevels],
UnlockedLevels = new List<int>(store.Player.UnlockedLevels),
UnlockedSkillNames = GetSkillNames(store.Player.UnlockedSkills),
UnlockedAchievements = new List<string>(store.Player.UnlockedAchievements),
Statistics = new Dictionary<string, int>(store.Player.Statistics)
};
try
@@ -65,7 +69,7 @@ public partial class SaveSystem : Node
{
using var file = FileAccess.Open(SavePath, FileAccess.ModeFlags.Read);
var json = file.GetAsText();
var saveData = JsonSerializer.Deserialize<SaveData>(json, JsonOptions);
var saveData = JsonSerializer.Deserialize<SaveDataDto>(json, JsonOptions);
if (saveData == null)
{
@@ -87,9 +91,18 @@ public partial class SaveSystem : Node
}
// Apply loaded state
store.Player = saveData.Player ?? new PlayerState();
store.Player.Coins = saveData.Coins;
store.Player.Lives = saveData.Lives;
store.Session.CurrentLevel = saveData.CurrentLevel;
store.Player.CompletedLevels = saveData.CompletedLevels ?? new List<int>();
store.Player.UnlockedLevels = saveData.UnlockedLevels ?? new List<int> { 0 };
store.Player.UnlockedAchievements = saveData.UnlockedAchievements ?? new List<string>();
store.Player.Statistics = saveData.Statistics ?? new Dictionary<string, int>();
// Reload skills by name from SkillManager
store.Player.UnlockedSkills = LoadSkillsByName(saveData.UnlockedSkillNames);
GD.Print("Game loaded from: ", SavePath);
return true;
}
@@ -100,6 +113,44 @@ public partial class SaveSystem : Node
}
}
private static List<string> GetSkillNames(List<SkillData> skills)
{
var names = new List<string>();
foreach (var skill in skills)
{
if (skill != null)
names.Add(skill.Name);
}
return names;
}
private List<SkillData> LoadSkillsByName(List<string> skillNames)
{
var skills = new List<SkillData>();
if (skillNames == null) return skills;
var skillManager = GetNodeOrNull<SkillManager>(Constants.SkillManagerPath);
if (skillManager == null)
{
GD.PrintErr("SaveSystem: SkillManager not available to resolve skill names.");
return skills;
}
foreach (var name in skillNames)
{
var skill = skillManager.GetSkillByName(name);
if (skill != null)
{
skills.Add(skill);
}
else
{
GD.PrintErr($"SaveSystem: Skill '{name}' not found in SkillManager.");
}
}
return skills;
}
public bool CheckSaveExists() => FileAccess.FileExists(SavePath);
public void DeleteSave()
@@ -113,11 +164,17 @@ public partial class SaveSystem : Node
}
/// <summary>
/// Container for save data.
/// Serializable DTO for save data - no Godot types.
/// </summary>
public class SaveData
public class SaveDataDto
{
public int Version { get; set; }
public PlayerState Player { get; set; }
public int Coins { get; set; }
public int Lives { get; set; }
public int CurrentLevel { get; set; }
public List<int> CompletedLevels { get; set; }
public List<int> UnlockedLevels { get; set; }
public List<string> UnlockedSkillNames { get; set; }
public List<string> UnlockedAchievements { get; set; }
public Dictionary<string, int> Statistics { get; set; }
}

View File

@@ -32,7 +32,7 @@ public partial class PlayerDeathComponent : Node2D
effect.Scale = EffectScale;
}
_gameManager.RemoveLives(1);
_gameManager.ResetCurrentSessionState();
// Lives are now decremented by LivesStateHandler via PlayerDied event
// Session state is reset by LivesStateHandler as well
}
}