Files
SPT-Server-Build/Core/Services/RaidWeatherService.cs
T
2025-01-12 16:53:46 +00:00

125 lines
4.4 KiB
C#

using Core.Annotations;
using Core.Generators;
using Core.Helpers;
using Core.Models.Eft.Weather;
using Core.Models.Enums;
using Core.Models.Spt.Config;
using Core.Servers;
using Core.Utils;
using ILogger = Core.Models.Utils.ILogger;
namespace Core.Services;
[Injectable(InjectionType.Singleton)]
public class RaidWeatherService
{
private readonly ILogger _logger;
private readonly DatabaseService _databaseService;
private readonly TimeUtil _timeUtil;
private readonly WeatherGenerator _weatherGenerator;
private readonly SeasonalEventService _seasonalEventService;
private readonly WeightedRandomHelper _weightedRandomHelper;
private readonly ConfigServer _configServer;
private readonly List<Weather> _weatherForecast = [];
private readonly WeatherConfig _weatherConfig;
public RaidWeatherService(
ILogger logger,
DatabaseService databaseService,
TimeUtil timeUtil,
WeatherGenerator weatherGenerator,
SeasonalEventService seasonalEventService,
WeightedRandomHelper weightedRandomHelper,
ConfigServer configServer)
{
_logger = logger;
_databaseService = databaseService;
_timeUtil = timeUtil;
_weatherGenerator = weatherGenerator;
_seasonalEventService = seasonalEventService;
_weightedRandomHelper = weightedRandomHelper;
_configServer = configServer;
_weatherConfig = _configServer.GetConfig<WeatherConfig>(ConfigTypes.WEATHER);
}
/// <summary>
/// Generate 24 hours of weather data starting from midnight today
/// </summary>
public void GenerateWeather(Season currentSeason)
{
// When to start generating weather from in milliseconds
var staringTimestampMs = _timeUtil.GetTodayMidnightTimeStamp();
// How far into future do we generate weather
var futureTimestampToReachMs = staringTimestampMs + _timeUtil.GetHoursAsSeconds(_weatherConfig.Weather.GenerateWeatherAmountHours) * 1000; // Convert to milliseconds
// Keep adding new weather until we have reached desired future date
var nextTimestampMs = staringTimestampMs;
while (nextTimestampMs <= futureTimestampToReachMs)
{
var newWeatherToAddToCache = _weatherGenerator.GenerateWeather(currentSeason, nextTimestampMs);
// Add generated weather for time period to cache
_weatherForecast.Add(newWeatherToAddToCache);
// Increment timestamp so next loop can begin at correct time
nextTimestampMs += GetWeightedWeatherTimePeriodMs();
}
}
/// <summary>
/// Get a time period to increment by, e.g. 15 or 30 minutes as milliseconds
/// </summary>
/// <returns>milliseconds</returns>
protected long GetWeightedWeatherTimePeriodMs()
{
var chosenTimePeriodMinutes = _weightedRandomHelper.WeightedRandom(
_weatherConfig.Weather.TimePeriod.Values,
_weatherConfig.Weather.TimePeriod.Weights).Item;
return chosenTimePeriodMinutes * 60 * 1000; // Convert to milliseconds
}
/// <summary>
/// Find the first matching weather object that applies to the current time
/// </summary>
public Weather GetCurrentWeather()
{
var currentSeason = _seasonalEventService.GetActiveWeatherSeason();
ValidateWeatherDataExists(currentSeason);
return _weatherForecast.Find((weather) => weather.Timestamp >= _timeUtil.GetTimeStamp());
}
/// <summary>
/// Find all matching weather objects that applies to the current time + future
/// </summary>
public IEnumerable<Weather> GetUpcomingWeather()
{
var currentSeason = _seasonalEventService.GetActiveWeatherSeason();
ValidateWeatherDataExists(currentSeason);
return _weatherForecast.Where((weather) => weather.Timestamp >= _timeUtil.GetTimeStamp());
}
/// <summary>
/// Ensure future weather data exists
/// </summary>
protected void ValidateWeatherDataExists(Season currentSeason)
{
// Clear expired weather data
_weatherForecast.RemoveAll(weather => weather.Timestamp < _timeUtil.GetTimeStamp());
// Check data exists for current time
var result = _weatherForecast.Where((weather) => weather.Timestamp >= _timeUtil.GetTimeStamp());
if (!result.Any())
{
GenerateWeather(currentSeason);
}
}
}