Files
SPT-Server-Build/Libraries/SPTarkov.Server.Core/Utils/App.cs
T
2025-12-24 14:33:24 +00:00

130 lines
4.7 KiB
C#

using Microsoft.Extensions.Hosting;
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.DI;
using SPTarkov.Server.Core.Extensions;
using SPTarkov.Server.Core.Models.Utils;
using SPTarkov.Server.Core.Servers;
using SPTarkov.Server.Core.Services;
using static SPTarkov.Server.Core.Extensions.StringExtensions;
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
namespace SPTarkov.Server.Core.Utils;
[Injectable(InjectionType.Singleton)]
public class App(
IServiceProvider serviceProvider,
ISptLogger<App> logger,
TimeUtil timeUtil,
RandomUtil randomUtil,
ServerLocalisationService serverLocalisationService,
HttpServer httpServer,
DatabaseService databaseService,
IHostApplicationLifetime appLifeTime,
IEnumerable<IOnLoad> onLoadComponents,
IEnumerable<IOnUpdate> onUpdateComponents
)
{
protected readonly Dictionary<string, long> _onUpdateLastRun = new();
public async Task InitializeAsync()
{
ServiceLocator.SetServiceProvider(serviceProvider);
if (logger.IsLogEnabled(LogLevel.Debug))
{
var totalMemoryBytes = GC.GetGCMemoryInfo().TotalAvailableMemoryBytes;
// Convert bytes to GB
var totalMemoryGb = totalMemoryBytes / (1024.0 * 1024.0 * 1024.0);
var pageFileGb = Environment.SystemPageSize / (1024.0 * 1024.0 * 1024.0);
logger.Debug($"OS: {Environment.OSVersion.Version} | {Environment.OSVersion.Platform}");
logger.Debug($"Pagefile: {pageFileGb:F2} GB");
logger.Debug($"RAM: {totalMemoryGb:F2} GB");
if (totalMemoryGb < 30)
{
logger.Warning(
$"Detected RAM ({totalMemoryGb:F2}GB) is smaller than recommended (32GB) you may experience crashes or reduced FPS on large maps"
);
}
logger.Debug($"Ran as admin: {Environment.IsPrivilegedProcess}");
logger.Debug($"CPU cores: {Environment.ProcessorCount}");
logger.Debug($"PATH: {(Environment.ProcessPath ?? "null returned").Encode(EncodeType.BASE64)}");
logger.Debug($"Server: {ProgramStatics.SPT_VERSION()}");
// _logger.Debug($"RAM: {(os.totalmem() / 1024 / 1024 / 1024).toFixed(2)}GB");
if (ProgramStatics.BUILD_TIME() != 0)
{
logger.Debug($"Date: {ProgramStatics.BUILD_TIME()}");
}
logger.Debug($"Commit: {ProgramStatics.COMMIT()}");
}
// execute onLoad callbacks
logger.Info(serverLocalisationService.GetText("executing_startup_callbacks"));
foreach (var onLoad in onLoadComponents)
{
await onLoad.OnLoad();
}
// Discard here, as this task will run indefinitely
_ = Task.Run(Update);
logger.Success(serverLocalisationService.GetText("started_webserver_success", httpServer.ListeningUrl()));
logger.Success(serverLocalisationService.GetText("websocket-started", httpServer.ListeningUrl().Replace("https://", "wss://")));
logger.Success(GetRandomisedStartMessage());
}
protected string GetRandomisedStartMessage()
{
if (randomUtil.GetInt(1, 1000) > 999)
{
return serverLocalisationService.GetRandomTextThatMatchesPartialKey("server_start_meme_");
}
return serverLocalisationService.GetText("server_start_success");
}
protected async Task Update()
{
while (!appLifeTime.ApplicationStopping.IsCancellationRequested)
{
foreach (var updateable in onUpdateComponents)
{
var updateableName = updateable.GetType().FullName;
if (string.IsNullOrEmpty(updateableName))
{
updateableName = $"{updateable.GetType().Namespace}.{updateable.GetType().Name}";
}
var lastRunTimeTimestamp = _onUpdateLastRun.GetValueOrDefault(updateableName, 0);
var secondsSinceLastRun = timeUtil.GetTimeStamp() - lastRunTimeTimestamp;
try
{
if (await updateable.OnUpdate(secondsSinceLastRun))
{
_onUpdateLastRun[updateableName] = timeUtil.GetTimeStamp();
}
}
catch (Exception err)
{
LogUpdateException(err, updateable);
}
}
await Task.Delay(5000, appLifeTime.ApplicationStopping);
}
}
protected void LogUpdateException(Exception err, IOnUpdate updateable)
{
logger.Error(serverLocalisationService.GetText("scheduled_event_failed_to_run", updateable.GetType().FullName));
logger.Error(err.ToString());
}
}