feat: Add metro transit, gadgets, shop, social apps, and traffic models checkpoint
This commit is contained in:
1 parent
caa42b84ed
commit
74e2963a12
79 files changed
+527962
-496
No files matched your search
@@ -0,0 +1,86 @@
|
||||
using System.Text.Json;
|
||||
using Ananta.Server.Configuration;
|
||||
using Ananta.Server.Protocol.Client4229938;
|
||||
|
||||
namespace Ananta.Server.Handlers.Game;
|
||||
|
||||
/// <summary>
|
||||
/// Persists per-player vehicle tuning (bought parts / suits / session unlocks) to
|
||||
/// save/vehicles/<pid>.json so purchases survive a server restart.
|
||||
/// </summary>
|
||||
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<uint, uint>(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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Loads saved tuning into the (fresh) world state — called on world entry.</summary>
|
||||
public static void LoadInto(ulong pid, WorldEntryState world)
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = FileFor(pid);
|
||||
if (!File.Exists(path))
|
||||
return;
|
||||
var dto = JsonSerializer.Deserialize<TuningDto>(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<uint> Unlocked { get; set; } = [];
|
||||
public Dictionary<uint, List<PartDto>> Parts { get; set; } = [];
|
||||
public Dictionary<uint, uint> Suits { get; set; } = [];
|
||||
}
|
||||
|
||||
private sealed class PartDto
|
||||
{
|
||||
public uint Type { get; set; }
|
||||
public uint PartId { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user