evershade/Assets/Scripts/Managers/GameTimeManager.cs

221 lines
6.7 KiB
C#

using System;
using System.Collections;
using FishNet.Object;
using FishNet.Object.Synchronizing;
using Types;
using UnityEngine;
// possible future additions
// weather sys
// skybox changes based on time of day
// moon and stars
// clouds
// rain
// Sound effects, bird chrirping, crickets, wind, etc
// Temperture?
// Lighting effects! So that the transition is more visually appealing
// Moonlight phases based on day of month ect
// Seasons - impact the length of day, temp, weather, etc
namespace Managers
{
public class GameTimeManager : NetworkBehaviour
{
public Gradient lightColorGradient;
public Gradient lightIntensityGradient;
private readonly int _daysPerMonth = 28;
private readonly int _monthsPerYear = 4;
public readonly SyncVar<string> dayText;
public readonly SyncVar<string> seasonText;
// public Light2D globalLight;
public readonly SyncVar<string> timeText;
private bool _isFirstDay = true;
private void Awake()
{
}
private void Start()
{
if (IsServerInitialized)
{
dayText.Value = GetCurrentDayOfMonth().ToString();
StartCoroutine(ServerDayNightCycleCoroutine());
_isFirstDay = false;
}
}
private void Update()
{
if (GameManager.Instance == null)
{
Debug.LogError("GameManager.Instance is null in GameTimeManager.Update()");
return;
}
timeText.Value = GetCurrentTime();
//todo: optimize to only update on day change
dayText.Value = GetCurrentDayOfMonth().ToString();
seasonText.Value = GetCurrentSeason().ToString();
var timeSettings = GameManager.Instance.GetTimeSettings();
timeSettings.CurrentTime = timeSettings.DayStartTimeInHours / 24 *
timeSettings.DayLengthInMinutes * 60;
GameManager.Instance.RequestUpdateTimeSettingsServerRpc(timeSettings);
}
public override void OnStartClient()
{
base.OnStartClient();
UpdateUIDisplay();
}
private void UpdateUIDisplay()
{
timeText.Value = GetCurrentTime();
//todo: optimize to only update on day change
dayText.Value = GetCurrentDayOfMonth().ToString();
seasonText.Value = GetCurrentSeason().ToString();
}
public override void OnStartServer()
{
base.OnStartServer();
StartCoroutine(ServerDayNightCycleCoroutine());
}
public static event Action OnDayChange;
public static event Action OnSeasonChange;
public Season GetCurrentSeason()
{
return GetCurrentSeason(GetDaysPassed());
}
public Season GetCurrentSeason(int daysPassed)
{
var month = GetCurrentMonth(daysPassed);
return month switch
{
0 => Season.Spring,
1 => Season.Summer,
2 => Season.Fall,
3 => Season.Winter,
_ => Season.Spring
};
}
public int GetCurrentDayOfMonth()
{
return GameManager.Instance.GetTimeSettings().DaysPassed % _daysPerMonth;
}
public int GetCurrentMonth()
{
return GetDaysPassed() / _daysPerMonth % _monthsPerYear;
}
public int GetCurrentMonth(int daysPassed)
{
return daysPassed / _daysPerMonth % _monthsPerYear;
}
private string GetCurrentTime()
{
if (GameManager.Instance == null)
{
Debug.LogError("GameManager not found");
return "00:00";
}
var timeSettings = GameManager.Instance.GetTimeSettings();
// Calculate the current hour and minute based on the time of day
var timeOfDay = timeSettings.CurrentTime / (timeSettings.DayLengthInMinutes * 60);
var hours = Mathf.FloorToInt(timeOfDay * 24);
var minutes = Mathf.FloorToInt((timeOfDay * 24 - hours) * 60);
// Convert to 12-hour format and add AM/PM
var hours12 = hours % 12;
if (hours12 == 0) hours12 = 12;
var amPm = hours < 12 ? "AM" : "PM";
return $"{hours12:D2}:{minutes:D2} {amPm}";
}
public int GetDaysPassed()
{
var timeSettings = GameManager.Instance.GetTimeSettings();
return timeSettings.DaysPassed;
}
[Server]
private IEnumerator ServerDayNightCycleCoroutine()
{
// var previousSeason = GetCurrentSeason();
while (true)
{
var timeSettings = GameManager.Instance.GetTimeSettings();
// Calculate the current time of day between 0 (midnight) and 1 (next midnight)
var timeOfDay = timeSettings.CurrentTime / (timeSettings.DayLengthInMinutes * 60);
/*// Adjust the intensity of the light source based on the time of day
globalLight.color = lightColorGradient.Evaluate(timeOfDay);
globalLight.intensity = lightIntensityGradient.Evaluate(timeOfDay).a;*/
// increment current time
timeSettings.CurrentTime += Time.deltaTime;
// check if a day has passed
if (timeSettings.CurrentTime >= timeSettings.DayLengthInMinutes * 60)
{
timeSettings.DaysPassed++;
Debug.Log("Day " + timeSettings.DaysPassed + " has passed");
timeSettings.CurrentTime = 0;
_isFirstDay = false;
OnDayChange?.Invoke();
var newSeason = GetCurrentSeason(timeSettings.DaysPassed);
if (newSeason != timeSettings.Season)
{
Debug.Log("Season changed from " + timeSettings.Season + " to " + newSeason);
timeSettings.Season = newSeason;
OnSeasonChange?.Invoke();
}
}
GameManager.Instance.RequestUpdateTimeSettingsServerRpc(timeSettings);
UpdateClientsRpc(timeOfDay);
yield return null;
}
}
[ObserversRpc]
private void UpdateClientsRpc(float timeOfDay)
{
// globalLight.color = lightColorGradient.Evaluate(timeOfDay);
// globalLight.intensity = lightIntensityGradient.Evaluate(timeOfDay).a;
UpdateUIDisplay();
}
}
}