using System; using UnityEngine; namespace DanieleMarotta.RiversongCodeShowcase { [RequiresWorldReadyForUpdate] [GameSystemGroup(typeof(EarlyGameSystemGroup))] public class WorldTimeSystem : GameSystem, IUpdatable { [InjectService] private GameConfig _config; [InjectService] private World _world; [InjectService] private ISignalBus _signalBus; public WorldTimeSystem(IServiceLocator serviceLocator) : base(serviceLocator) { } public void Update() { AdvanceCalendar(); AdvanceDayNightCycle(); } private void AdvanceCalendar() { var timeState = _world.TimeState; if (timeState.DayNightCycleStep != DayNightCycleStep.Day) return; var weekDuration = _config.Time.WeekDuration; timeState.WeekTime += Time.deltaTime; if (timeState.WeekTime > weekDuration) { timeState.WeekTime -= weekDuration; timeState.TotalWeeks++; timeState.WeekNumber = (timeState.WeekNumber + 1) % 4; if (timeState.WeekNumber > 0) { _signalBus.Raise(new EndOfWeekSignal()); return; } timeState.MonthNumber = (timeState.MonthNumber + 1) % 12; if (timeState.MonthNumber > 0) { _signalBus.Raise(new EndOfWeekSignal()); _signalBus.Raise(new EndOfMonthSignal()); return; } timeState.YearNumber++; _signalBus.Raise(new EndOfWeekSignal()); _signalBus.Raise(new EndOfMonthSignal()); _signalBus.Raise(new EndOfYearSignal()); } } private void AdvanceDayNightCycle() { var timeState = _world.TimeState; var config = _config.Time; timeState.DayNightCycleTime += Time.deltaTime; var stepDuration = timeState.DayNightCycleStep switch { DayNightCycleStep.Day => config.DayDuration, DayNightCycleStep.DayToNight => config.DayToNightDuration, DayNightCycleStep.Night => config.NightDuration, DayNightCycleStep.NightToDay => config.NightToDayDuration, _ => throw new ArgumentException() }; while (timeState.DayNightCycleTime > stepDuration) { timeState.DayNightCycleTime -= stepDuration; timeState.DayNightCycleStep = (DayNightCycleStep)(((int)timeState.DayNightCycleStep + 1) % 4); _signalBus.Raise(new DayNightCycleStepChangedSignal(timeState.DayNightCycleStep)); switch (timeState.DayNightCycleStep) { case DayNightCycleStep.Night: _signalBus.Raise(new NightStartedSignal()); break; case DayNightCycleStep.Day: _signalBus.Raise(new DayStartedSignal()); break; } } timeState.NightBlend = timeState.DayNightCycleStep switch { DayNightCycleStep.Day => 0, DayNightCycleStep.DayToNight => Mathf.Clamp01(timeState.DayNightCycleTime / config.DayToNightDuration), DayNightCycleStep.Night => 1, DayNightCycleStep.NightToDay => 1 - Mathf.Clamp01(timeState.DayNightCycleTime / config.NightToDayDuration), _ => throw new ArgumentException() }; } } }