using System.Text.Json;
using Ananta.Server.Configuration;
using Ananta.Server.Protocol.Client4229938;
namespace Ananta.Server.Handlers.Game;
///
/// Persists per-player vehicle tuning (bought parts / suits / session unlocks) to
/// save/vehicles/<pid>.json so purchases survive a server restart.
///
internal static class VehicleTuningStore
{
private static string DirFor(ulong pid)
{
string baseDir;
try { baseDir = PrivateServerConfigStore.ProjectRoot; }
catch { baseDir = AppContext.BaseDirectory; }
return Path.Combine(baseDir, "save", "vehicles");
}
private static string FileFor(ulong pid) => Path.Combine(DirFor(pid), $"{pid}.json");
public static void Save(ulong pid, WorldEntryState world)
{
try
{
var dir = DirFor(pid);
Directory.CreateDirectory(dir);
var dto = new TuningDto
{
Unlocked = world.SessionUnlockedVehicleConfigs.ToList(),
Parts = world.VehiclePartsByConfig.ToDictionary(
kv => kv.Key,
kv => kv.Value.Select(p => new PartDto { Type = p.Type, PartId = p.PartId }).ToList()),
Suits = new Dictionary(world.VehicleSuitByConfig),
};
var json = JsonSerializer.Serialize(dto, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(FileFor(pid), json);
}
catch (Exception ex)
{
Console.WriteLine($"[TUNING] save failed pid={pid}: {ex.Message}");
}
}
/// Loads saved tuning into the (fresh) world state — called on world entry.
public static void LoadInto(ulong pid, WorldEntryState world)
{
try
{
var path = FileFor(pid);
if (!File.Exists(path))
return;
var dto = JsonSerializer.Deserialize(File.ReadAllText(path));
if (dto is null)
return;
lock (world.SyncRoot)
{
foreach (var id in dto.Unlocked)
world.SessionUnlockedVehicleConfigs.Add(id);
foreach (var kv in dto.Parts)
world.VehiclePartsByConfig[kv.Key] = kv.Value.Select(p => (p.Type, p.PartId)).ToList();
foreach (var kv in dto.Suits)
world.VehicleSuitByConfig[kv.Key] = kv.Value;
}
Console.WriteLine($"[TUNING] loaded saved tuning pid={pid} vehicles={dto.Unlocked.Count} parts={dto.Parts.Count}");
}
catch (Exception ex)
{
Console.WriteLine($"[TUNING] load failed pid={pid}: {ex.Message}");
}
}
private sealed class TuningDto
{
public List Unlocked { get; set; } = [];
public Dictionary> Parts { get; set; } = [];
public Dictionary Suits { get; set; } = [];
}
private sealed class PartDto
{
public uint Type { get; set; }
public uint PartId { get; set; }
}
}