221 lines
6.7 KiB
C#
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();
|
|
}
|
|
}
|
|
} |