evershade/Assets/Scripts/Managers/GameTimeManager.cs

328 lines
10 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 static GameTimeManager Instance;
[SerializeField] private bool isPaused = true;
[SerializeField] private bool isFirstDay = true;
private readonly int _daysPerMonth = 28;
private readonly SyncVar<string> _dayText = new(new SyncTypeSettings
{
WritePermission = WritePermission.ServerOnly,
ReadPermission = ReadPermission.Observers
});
private readonly int _monthsPerYear = 4;
private readonly SyncVar<string> _seasonText = new(new SyncTypeSettings
{
WritePermission = WritePermission.ServerOnly,
ReadPermission = ReadPermission.Observers
});
private readonly SyncVar<string> _timeText = new(new SyncTypeSettings
{
WritePermission = WritePermission.ServerOnly,
ReadPermission = ReadPermission.Observers
});
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
}
/*private void Start()
{
/*if (IsServerInitialized)
{
dayText.Value = GetCurrentDayOfMonth().ToString();
StartCoroutine(ServerDayNightCycleCoroutine());
_isFirstDay = false;
}#1#
}*/
private void Start()
{
// if (IsServerInitialized) InitializeServerData();
}
private void Update()
{
if (isPaused) return;
if (GameManager.Instance == null)
Debug.LogError("GameManager.Instance is null in GameTimeManager.Update()");
// var timeSettings = GameManager.Instance.GetTimeSettings();
// if (timeSettings == null) return;
// timeSettings.CurrentTime = CalculateCurrentTime();
// GameManager.Instance.RequestUpdateTimeSettingsServerRpc(timeSettings);
}
private void InitializeServerData()
{
if (GameManager.Instance == null)
{
Debug.LogError("GameManager.Instance is null in GameTimeManager.InitializeServerData()");
return;
}
var timeSettings = GameManager.Instance.GetTimeSettings();
if (timeSettings == null)
{
Debug.LogError("TimeSettings is null in GameTimeManager.InitializeServerData()");
return;
}
_dayText.Value = GetCurrentDayOfMonth().ToString();
StartCoroutine(ServerDayNightCycleCoroutine());
isFirstDay = false;
}
public override void OnStartClient()
{
base.OnStartClient();
/*UpdateUIDisplay();*/
}
/*private void UpdateUIDisplay()
{
_timeText.Value = GetCurrentTimeFormatted();
//todo: optimize to only update on day change
_dayText.Value = GetCurrentDayOfMonth().ToString();
_seasonText.Value = GetCurrentSeason().ToString();
}*/
public override void OnStartServer()
{
base.OnStartServer();
/*// StartCoroutine(ServerDayNightCycleCoroutine());
Debug.Log("GameTimeManager.OnStartServer() triggered");
*/
if (IsServerInitialized)
{
Debug.Log("GameTimeManager.OnStartServer() triggered, initializing server data");
InitializeServerData();
}
}
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;
}
public GameTime GetGameTime()
{
if (GameManager.Instance == null)
{
Debug.LogError("GameManager not found");
return new GameTime();
}
var timeSettings = GameManager.Instance.GetTimeSettings();
if (timeSettings == null) return new GameTime();
// 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);
var seconds = Mathf.FloorToInt((timeOfDay * 24 - hours) * 60 * 60);
return new GameTime
{
hour = hours,
minute = minutes,
second = seconds
};
}
public string GetCurrentTimeFormatted()
{
if (GameManager.Instance == null)
{
Debug.LogError("GameManager not found");
return "00:00";
}
var timeSettings = GameManager.Instance.GetTimeSettings();
Debug.Log("Current settings start time: " + timeSettings.DayStartTimeInHours);
Debug.Log("Current settings day length: " + timeSettings.DayLengthInMinutes);
if (timeSettings == null) return "00:00";
// Calculate the current hour and minute based on the time of day
var gameTime = GetGameTime();
Debug.Log("Current time: " + gameTime.hour + ":" + gameTime.minute);
var hours = gameTime.hour;
var minutes = gameTime.minute;
// Convert to 12-hour format and add AM/PM
var hours12 = hours % 12;
if (hours12 == 0) hours12 = 12;
var amPm = hours < 12 ? "AM" : "PM";
Debug.Log("Hours: " + hours + " AM/PM: " + amPm);
return $"{(int)hours12:D2}:{(int)minutes:D2} {amPm}";
}
public int GetDaysPassed()
{
var timeSettings = GameManager.Instance.GetTimeSettings();
return timeSettings?.DaysPassed ?? 0;
}
public void Pause()
{
Debug.Log("GameTimeManager.Pause()");
isPaused = true;
}
public void Resume()
{
Debug.Log("GameTimeManager.Resume()");
isPaused = false;
}
[Server]
private IEnumerator ServerDayNightCycleCoroutine()
{
// var previousSeason = GetCurrentSeason();
while (true)
{
if (isPaused) yield return new WaitForSeconds(0.5f);
if (GameManager.Instance == null)
{
Debug.LogWarning("GameManager.Instance is null in GameTimeManager.ServerDayNightCycleCoroutine()");
yield return new WaitForSeconds(0.5f);
continue;
}
var timeSettings = GameManager.Instance.GetTimeSettings();
if (timeSettings == null)
{
Debug.LogWarning("TimeSettings is null in GameTimeManager.ServerDayNightCycleCoroutine()");
yield return new WaitForSeconds(0.5f);
continue;
}
// 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();
}
}
}