b451f83174
Captures the pre-Godot-port state of the codebase. This is the rollback anchor for the Godot port (M0 of theriapolis-rpg-implementation-plan-godot-port.md). All Phase 0 through Phase 6.5 work is included; Phase 7 is in flight. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
57 lines
1.9 KiB
C#
57 lines
1.9 KiB
C#
using System.Text.Json.Serialization;
|
|
|
|
namespace Theriapolis.Core.Persistence;
|
|
|
|
/// <summary>
|
|
/// JSON-serializable metadata stored at the front of a save file. Designed so
|
|
/// the slot picker can deserialize just the header (with a 4-byte length
|
|
/// prefix preceding it) without touching the binary body.
|
|
/// </summary>
|
|
public sealed class SaveHeader
|
|
{
|
|
/// <summary>Schema version. Bump on breaking changes — see SaveMigrations.</summary>
|
|
[JsonPropertyName("version")]
|
|
public int Version { get; set; } = C.SAVE_SCHEMA_VERSION;
|
|
|
|
[JsonPropertyName("worldSeed")]
|
|
public string WorldSeedHex { get; set; } = "0x0";
|
|
|
|
[JsonPropertyName("stageHashes")]
|
|
public Dictionary<string, string> StageHashes { get; set; } = new();
|
|
|
|
[JsonPropertyName("playerName")]
|
|
public string PlayerName { get; set; } = "Wanderer";
|
|
|
|
[JsonPropertyName("playerTier")]
|
|
public int PlayerTier { get; set; }
|
|
|
|
[JsonPropertyName("inGameSeconds")]
|
|
public long InGameSeconds { get; set; }
|
|
|
|
[JsonPropertyName("savedAt")]
|
|
public string SavedAtUtc { get; set; } = "";
|
|
|
|
[JsonPropertyName("appVersion")]
|
|
public string AppVersion { get; set; } = "0.4.0";
|
|
|
|
/// <summary>Convenience: a one-line label for the slot picker.</summary>
|
|
public string SlotLabel()
|
|
{
|
|
// "Wanderer — Y0 Spring D5 (Tier 1)" style
|
|
long sec = InGameSeconds;
|
|
long days = sec / Time.WorldClock.SecondsPerDay;
|
|
int year = (int)(days / Time.WorldClock.DaysPerYear);
|
|
var season = (Time.Season)((days / Time.WorldClock.DaysPerSeason) % 4);
|
|
long dayOfSeason = days % Time.WorldClock.DaysPerSeason;
|
|
return $"{PlayerName} — Y{year} {season} D{dayOfSeason} (Tier {PlayerTier})";
|
|
}
|
|
|
|
public ulong ParseSeed()
|
|
{
|
|
string s = WorldSeedHex.Trim();
|
|
if (s.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
|
|
return Convert.ToUInt64(s[2..], 16);
|
|
return ulong.Parse(s);
|
|
}
|
|
}
|