refactor(runtime): own world environment state
This commit is contained in:
parent
b972f539f7
commit
902076c0a4
27 changed files with 886 additions and 295 deletions
103
src/AcDream.Core/World/DerethCalendar.cs
Normal file
103
src/AcDream.Core/World/DerethCalendar.cs
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
namespace AcDream.Core.World;
|
||||
|
||||
/// <summary>
|
||||
/// Instance-scoped Dereth calendar projection. Retail stores the Region
|
||||
/// <c>GameTime.ZeroTimeOfYear</c> beside the active world rather than in a
|
||||
/// process-global calendar. Keeping that origin on this object lets multiple
|
||||
/// Runtime sessions use different Region definitions without corrupting one
|
||||
/// another.
|
||||
/// </summary>
|
||||
public sealed class DerethCalendar
|
||||
{
|
||||
public DerethCalendar(
|
||||
double originOffsetTicks = DerethDateTime.DayFractionOriginOffsetTicks)
|
||||
{
|
||||
SetOriginOffset(originOffsetTicks);
|
||||
}
|
||||
|
||||
public double OriginOffsetTicks { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Installs the Region DAT origin for this world lifetime.
|
||||
/// </summary>
|
||||
public void SetOriginOffset(double originOffsetTicks)
|
||||
{
|
||||
if (!double.IsFinite(originOffsetTicks))
|
||||
throw new ArgumentOutOfRangeException(nameof(originOffsetTicks));
|
||||
|
||||
OriginOffsetTicks = originOffsetTicks;
|
||||
}
|
||||
|
||||
public double DayFraction(double ticks)
|
||||
{
|
||||
double shifted = Shift(ticks);
|
||||
double rem = shifted
|
||||
- Math.Floor(shifted / DerethDateTime.DayTicks)
|
||||
* DerethDateTime.DayTicks;
|
||||
return rem / DerethDateTime.DayTicks;
|
||||
}
|
||||
|
||||
public DerethDateTime.HourName CurrentHour(double ticks)
|
||||
{
|
||||
int slot = (int)Math.Floor(
|
||||
DayFraction(ticks) * DerethDateTime.HoursInADay);
|
||||
slot = Math.Clamp(slot, 0, DerethDateTime.HoursInADay - 1);
|
||||
return (DerethDateTime.HourName)slot;
|
||||
}
|
||||
|
||||
public bool IsDaytime(double ticks)
|
||||
{
|
||||
int hour = (int)CurrentHour(ticks);
|
||||
return hour >= (int)DerethDateTime.HourName.Dawnsong
|
||||
&& hour <= (int)DerethDateTime.HourName.WarmtideAndHalf;
|
||||
}
|
||||
|
||||
public DerethDateTime.Calendar ToCalendar(double ticks)
|
||||
{
|
||||
double shifted = Shift(ticks);
|
||||
int relativeYear = (int)(shifted / DerethDateTime.YearTicks);
|
||||
double withinYear =
|
||||
shifted - relativeYear * DerethDateTime.YearTicks;
|
||||
int month = Math.Min(
|
||||
DerethDateTime.MonthsInAYear - 1,
|
||||
(int)(withinYear / DerethDateTime.MonthTicks));
|
||||
double withinMonth =
|
||||
withinYear - month * DerethDateTime.MonthTicks;
|
||||
int day = Math.Min(
|
||||
DerethDateTime.DaysInAMonth,
|
||||
(int)(withinMonth / DerethDateTime.DayTicks) + 1);
|
||||
|
||||
return new DerethDateTime.Calendar(
|
||||
relativeYear + DerethDateTime.ZeroYear,
|
||||
(DerethDateTime.MonthName)month,
|
||||
day,
|
||||
CurrentHour(ticks));
|
||||
}
|
||||
|
||||
public int Year(double ticks) =>
|
||||
(int)(Shift(ticks) / DerethDateTime.YearTicks);
|
||||
|
||||
public int AbsoluteYear(double ticks) =>
|
||||
Year(ticks) + DerethDateTime.ZeroYear;
|
||||
|
||||
public int DayOfYear(double ticks)
|
||||
{
|
||||
double shifted = Shift(ticks);
|
||||
int year = (int)(shifted / DerethDateTime.YearTicks);
|
||||
double withinYear =
|
||||
shifted - year * DerethDateTime.YearTicks;
|
||||
return Math.Clamp(
|
||||
(int)(withinYear / DerethDateTime.DayTicks),
|
||||
0,
|
||||
DerethDateTime.DaysInAMonth
|
||||
* DerethDateTime.MonthsInAYear
|
||||
- 1);
|
||||
}
|
||||
|
||||
private double Shift(double ticks)
|
||||
{
|
||||
if (!double.IsFinite(ticks))
|
||||
throw new ArgumentOutOfRangeException(nameof(ticks));
|
||||
return Math.Max(0d, ticks) + OriginOffsetTicks;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue