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