refactor: enhance GameStateStore integration and improve skill management

This commit is contained in:
2026-03-19 02:33:07 +01:00
parent 3e36e48e97
commit eeefca4d4e
31 changed files with 260 additions and 419 deletions

View File

@@ -1,7 +1,8 @@
using System.Collections.Generic;
using System.Text.Json;
using Godot;
using Godot.Collections;
using Mr.BrickAdventures.scripts;
using Mr.BrickAdventures.scripts.State;
namespace Mr.BrickAdventures.Autoloads;
@@ -24,14 +25,14 @@ public partial class GhostManager : Node
public void StartRecording(int levelIndex)
{
if (!IsPlaybackEnabled) return;
_currentLevelIndex = levelIndex;
_currentRecording.Clear();
_startTime = Time.GetTicksMsec() / 1000.0;
IsRecording = true;
GD.Print("Ghost recording started.");
}
public void StopRecording(bool levelCompleted, double finalTime)
{
if (!IsRecording) return;
@@ -48,23 +49,22 @@ public partial class GhostManager : Node
}
_currentRecording.Clear();
}
public void RecordFrame(Vector2 position)
{
if (!IsRecording) return;
var frame = new GhostFrame
_currentRecording.Add(new GhostFrame
{
Timestamp = (Time.GetTicksMsec() / 1000.0) - _startTime,
Position = position
};
_currentRecording.Add(frame);
});
}
public void SpawnGhostPlayer(int levelIndex, Node parent)
{
if (!IsPlaybackEnabled || GhostPlayerScene == null) return;
var ghostData = LoadGhostData(levelIndex);
if (ghostData.Count > 0)
{
@@ -74,44 +74,63 @@ public partial class GhostManager : Node
GD.Print($"Ghost player spawned for level {levelIndex}.");
}
}
private void SaveGhostData(int levelIndex, double time)
{
var path = $"user://ghost_level_{levelIndex}.dat";
using var file = FileAccess.Open(path, FileAccess.ModeFlags.Write);
var dataToSave = new Godot.Collections.Dictionary
var path = $"user://ghost_level_{levelIndex}.json";
var saveData = new GhostSaveData { BestTime = time };
foreach (var frame in _currentRecording)
saveData.Frames.Add(new GhostFrameDto { Timestamp = frame.Timestamp, X = frame.Position.X, Y = frame.Position.Y });
try
{
{ "time", time },
{ "frames", _currentRecording.ToArray() }
};
file.StoreVar(dataToSave);
var json = JsonSerializer.Serialize(saveData, SaveSystem.JsonOptions);
using var file = FileAccess.Open(path, FileAccess.ModeFlags.Write);
file.StoreString(json);
}
catch (System.Exception e)
{
GD.PrintErr($"GhostManager: Failed to save ghost data: {e.Message}");
}
}
private List<GhostFrame> LoadGhostData(int levelIndex)
{
var path = $"user://ghost_level_{levelIndex}.dat";
var path = $"user://ghost_level_{levelIndex}.json";
if (!FileAccess.FileExists(path)) return [];
using var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);
var savedData = (Dictionary)file.GetVar();
var framesArray = (Array)savedData["frames"];
var frames = new List<GhostFrame>();
foreach (var obj in framesArray)
try
{
frames.Add((GhostFrame)obj);
using var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);
var saveData = JsonSerializer.Deserialize<GhostSaveData>(file.GetAsText(), SaveSystem.JsonOptions);
if (saveData == null) return [];
var frames = new List<GhostFrame>();
foreach (var dto in saveData.Frames)
frames.Add(new GhostFrame { Timestamp = dto.Timestamp, Position = new Vector2(dto.X, dto.Y) });
return frames;
}
catch (System.Exception e)
{
GD.PrintErr($"GhostManager: Failed to load ghost data: {e.Message}");
return [];
}
return frames;
}
private double LoadBestTime(int levelIndex)
{
var path = $"user://ghost_level_{levelIndex}.dat";
var path = $"user://ghost_level_{levelIndex}.json";
if (!FileAccess.FileExists(path)) return double.MaxValue;
using var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);
var data = (Dictionary)file.GetVar();
return (double)data["time"];
try
{
using var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);
var saveData = JsonSerializer.Deserialize<GhostSaveData>(file.GetAsText(), SaveSystem.JsonOptions);
return saveData?.BestTime ?? double.MaxValue;
}
catch
{
return double.MaxValue;
}
}
}
}