49 lines
1.9 KiB
C#
49 lines
1.9 KiB
C#
|
|
namespace Theriapolis.Core.Time;
|
|||
|
|
|
|||
|
|
public enum Season : byte { Spring, Summer, Autumn, Winter }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Single in-game time counter. Measured in whole seconds so it serializes
|
|||
|
|
/// trivially and stays deterministic — no floating-point drift over a long
|
|||
|
|
/// playthrough.
|
|||
|
|
///
|
|||
|
|
/// Phase 4 callers advance the clock from world-map travel and tactical
|
|||
|
|
/// stepping. Phase 8 weather/seasons reads from it.
|
|||
|
|
/// </summary>
|
|||
|
|
public sealed class WorldClock
|
|||
|
|
{
|
|||
|
|
/// <summary>In-game seconds since world creation. Game time, not real time.</summary>
|
|||
|
|
public long InGameSeconds { get; private set; }
|
|||
|
|
|
|||
|
|
// Calendar constants. A 96-day year (24 days × 4 seasons) keeps the math
|
|||
|
|
// tight; a real-world year would mean each season is a 90-hour playthrough.
|
|||
|
|
public const int SecondsPerMinute = 60;
|
|||
|
|
public const int SecondsPerHour = 3600;
|
|||
|
|
public const int SecondsPerDay = SecondsPerHour * 24;
|
|||
|
|
public const int DaysPerSeason = 24;
|
|||
|
|
public const int DaysPerYear = DaysPerSeason * 4;
|
|||
|
|
|
|||
|
|
public int Day => (int)(InGameSeconds / SecondsPerDay);
|
|||
|
|
public int Hour => (int)((InGameSeconds % SecondsPerDay) / SecondsPerHour);
|
|||
|
|
public int Minute => (int)((InGameSeconds % SecondsPerHour) / SecondsPerMinute);
|
|||
|
|
public int Year => Day / DaysPerYear;
|
|||
|
|
public Season Season => (Season)((Day / DaysPerSeason) % 4);
|
|||
|
|
|
|||
|
|
public void Advance(long seconds)
|
|||
|
|
{
|
|||
|
|
if (seconds < 0) throw new ArgumentOutOfRangeException(nameof(seconds));
|
|||
|
|
InGameSeconds += seconds;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public WorldClockState CaptureState() => new() { InGameSeconds = InGameSeconds };
|
|||
|
|
public void RestoreState(WorldClockState s) => InGameSeconds = s.InGameSeconds;
|
|||
|
|
|
|||
|
|
/// <summary>Pretty-print like "Y0 Spring D5 14:23".</summary>
|
|||
|
|
public string Format() => $"Y{Year} {Season} D{Day % DaysPerSeason} {Hour:D2}:{Minute:D2}";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public sealed class WorldClockState
|
|||
|
|
{
|
|||
|
|
public long InGameSeconds;
|
|||
|
|
}
|