cs2-SimpleAdmin/CS2-SimpleAdmin/Managers/ServerManager.cs
Salvatore 460d8b2b85 Migrate menus and votes to Panorama UI Kit
Replace MenuManagerCS2 with Panorama UI Kit for the admin menus and
css_vote. Layout names (menu, vote, banner, toast) are configurable
under MenuConfig and preloaded on startup; MenuType is removed and
ConfigVersion bumped to 26.

- Drop MenuManagerApi.dll and the old chat menu classes
- Reference PanoramaUiKit.Shared.dll, bump CounterStrikeSharp to 1.0.376
- Add .editorconfig and CODING_CONVENTIONS.md, apply them codebase-wide
- Remove the CS2-SimpleAdmin-docs site
- Rewrite README for the fork
2026-10-21 18:51:18 +02:00

151 lines
6.3 KiB
C#

using System.Data.Common;
using CounterStrikeSharp.API.Modules.Cvars;
using Dapper;
using Microsoft.Extensions.Logging;
namespace CS2_SimpleAdmin.Managers;
public class ServerManager
{
private int _getIpTryCount;
/// <summary>
/// Checks whether the server setting <c>sv_hibernate_when_empty</c> is enabled.
/// Logs an error if this setting is true, since it prevents the plugin from working properly.
/// </summary>
public static void CheckHibernationStatus()
{
ConVar? convar = ConVar.Find("sv_hibernate_when_empty");
if (convar == null || !convar.GetPrimitiveValue<bool>())
{
return;
}
CS2_SimpleAdmin._logger?.LogError("Detected setting \"sv_hibernate_when_empty true\", set false to make plugin work properly");
}
/// <summary>
/// Initiates the asynchronous process to load server data such as IP address, port, hostname, and RCON password.
/// Handles retry attempts if IP address is not immediately available.
/// Updates or inserts the server record in the database accordingly.
/// After loading, triggers admin reload and cache initialization.
/// Also optionally sends plugin usage metrics if enabled in configuration.
/// </summary>
public void LoadServerData()
{
CS2_SimpleAdmin.Instance.AddTimer(1.0f, () =>
{
if (CS2_SimpleAdmin.ServerLoaded || CS2_SimpleAdmin.DatabaseProvider == null)
{
return;
}
// Optimization: Get server IP once and reuse
string serverIp = Helper.GetServerIp();
bool isInvalidIp = string.IsNullOrEmpty(serverIp) || serverIp.StartsWith("0.0.0");
// Check if we've exceeded retry limit with invalid IP
if (_getIpTryCount > 32 && isInvalidIp)
{
CS2_SimpleAdmin._logger?.LogError("Unable to load server data - can't fetch ip address!");
CS2_SimpleAdmin.Instance.ReloadAdmins(null); // still load global admins
_ = CS2_SimpleAdmin.PlayerManager.LoadRenamedPlayers();
return;
}
// Optimization: Cache ConVar lookups
ConVar? ipConVar = ConVar.Find("ip");
string? ipAddress = ipConVar?.StringValue;
// Use Helper IP if ConVar IP is invalid
if (string.IsNullOrEmpty(ipAddress) || ipAddress.StartsWith("0.0.0"))
{
ipAddress = serverIp;
// Retry if still invalid and under retry limit
if (_getIpTryCount <= 32 && isInvalidIp)
{
_getIpTryCount++;
LoadServerData();
return;
}
}
// Optimization: Cache remaining ConVar lookups
ConVar? hostportConVar = ConVar.Find("hostport");
ConVar? hostnameConVar = ConVar.Find("hostname");
ConVar? rconPasswordConVar = ConVar.Find("rcon_password");
string address = $"{ipAddress}:{hostportConVar?.GetPrimitiveValue<int>()}";
string hostname = hostnameConVar?.StringValue ?? CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown";
string rconPassword = rconPasswordConVar?.StringValue ?? "";
CS2_SimpleAdmin.IpAddress = address;
Task.Run(async () =>
{
try
{
await using DbConnection connection = await CS2_SimpleAdmin.DatabaseProvider.CreateConnectionAsync();
int? serverId = await connection.ExecuteScalarAsync<int?>(
"SELECT id FROM sa_servers WHERE address = @address",
new { address });
if (serverId == null)
{
await connection.ExecuteAsync(
"INSERT INTO sa_servers (address, hostname, rcon_password) VALUES (@address, @hostname, @rconPassword)",
new { address, hostname, rconPassword });
serverId = await connection.ExecuteScalarAsync<int>(
"SELECT id FROM sa_servers WHERE address = @address",
new { address });
}
else
{
await connection.ExecuteAsync(
"UPDATE sa_servers SET hostname = @hostname, rcon_password = @rconPassword WHERE address = @address",
new { address, hostname, rconPassword });
}
CS2_SimpleAdmin.ServerId = serverId;
CS2_SimpleAdmin._logger?.LogInformation("Loaded server with ip {ip}", ipAddress);
CS2_SimpleAdmin.ServerLoaded = true;
if (CS2_SimpleAdmin.Instance.CacheManager != null)
{
await CS2_SimpleAdmin.Instance.CacheManager.InitializeCacheAsync();
}
// Admins are loaded only now, once ServerId is known, so server-specific admins are included
CS2_SimpleAdmin.Instance.ReloadAdmins(null);
}
catch (Exception ex)
{
CS2_SimpleAdmin._logger?.LogCritical("Unable to create or get server_id: " + ex.Message);
CS2_SimpleAdmin.Instance.ReloadAdmins(null); // still load global admins
}
// Renames are server-independent, so load them even when the server row could not be resolved
await CS2_SimpleAdmin.PlayerManager.LoadRenamedPlayers();
if (CS2_SimpleAdmin.Instance.Config.EnableMetrics)
{
string queryString = $"?address={address}&hostname={hostname}";
HttpClient client = CS2_SimpleAdmin.HttpClient;
try
{
await client.GetAsync($"https://api.daffyy.dev/index.php{queryString}");
}
catch (HttpRequestException ex)
{
CS2_SimpleAdmin._logger?.LogWarning($"Unable to make metrics call: {ex.Message}");
}
}
});
CS2_SimpleAdmin.SimpleAdminApi?.OnSimpleAdminReadyEvent();
});
}
}