mirror of
https://github.com/daffyyyy/CS2-SimpleAdmin.git
synced 2026-10-17 20:37:05 +02:00
The admin notification on player connect always reported 0 bans, gags, mutes and silences. - MuteManager.GetPlayerMutes ran GetRetrieveMutesQuery (the unmute id lookup, which needs @pattern/@muteType) instead of GetMuteStatsQuery. The query threw, the catch returned (0,0,0), so mute counts were always 0. - CacheManager.GetPlayerBansBySteamId read _steamIdIndex, which only holds ACTIVE bans. Anyone with an active ban is kicked before the message is sent, so the count was always 0. It now counts all of the player's bans in _banCache (expired/unbanned included). The connect message is its only caller; the ban check still uses the active index.
268 lines
No EOL
9.2 KiB
C#
268 lines
No EOL
9.2 KiB
C#
using CounterStrikeSharp.API;
|
|
using CounterStrikeSharp.API.Core;
|
|
using CounterStrikeSharp.API.Core.Attributes;
|
|
using CounterStrikeSharp.API.Core.Capabilities;
|
|
using CounterStrikeSharp.API.Modules.Commands;
|
|
using CounterStrikeSharp.API.Modules.Commands.Targeting;
|
|
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
|
using CS2_SimpleAdmin.Database;
|
|
using CS2_SimpleAdmin.Managers;
|
|
using CS2_SimpleAdmin.Menus;
|
|
using CS2_SimpleAdminApi;
|
|
using Microsoft.Extensions.Logging;
|
|
using MySqlConnector;
|
|
|
|
namespace CS2_SimpleAdmin;
|
|
|
|
[MinimumApiVersion(369)]
|
|
public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdminConfig>
|
|
{
|
|
internal static CS2_SimpleAdmin Instance { get; private set; } = new();
|
|
|
|
public override string ModuleName => "CS2-SimpleAdmin" + (Helper.IsDebugBuild ? " (DEBUG)" : " (RELEASE)");
|
|
public override string ModuleDescription => "Simple admin plugin for Counter-Strike 2 :)";
|
|
public override string ModuleAuthor => "daffyy";
|
|
public override string ModuleVersion => "1.9.1";
|
|
|
|
public override void Load(bool hotReload)
|
|
{
|
|
Instance = this;
|
|
if (hotReload)
|
|
{
|
|
ServerLoaded = false;
|
|
_serverLoading = false;
|
|
|
|
CacheManager?.Dispose();
|
|
CacheManager = new CacheManager();
|
|
|
|
// OnGameServerSteamAPIActivated();
|
|
OnMapStart(string.Empty);
|
|
|
|
AddTimer(6.0f, () =>
|
|
{
|
|
if (DatabaseProvider == null) return;
|
|
|
|
PlayersInfo.Clear();
|
|
CachedPlayers.Clear();
|
|
BotPlayers.Clear();
|
|
|
|
foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && p is { Connected: PlayerConnectedState.Connected, IsHLTV: false }).ToArray())
|
|
{
|
|
if (!player.IsBot)
|
|
PlayerManager.LoadPlayerData(player, true);
|
|
else
|
|
BotPlayers.Add(player);
|
|
};
|
|
});
|
|
|
|
}
|
|
_cBasePlayerControllerSetPawnFunc = new MemoryFunctionVoid<CBasePlayerController, CCSPlayerPawn, bool, bool>(GameData.GetSignature("CBasePlayerController_SetPawn"));
|
|
|
|
SimpleAdminApi = new Api.CS2_SimpleAdminApi();
|
|
Capabilities.RegisterPluginCapability(ICS2_SimpleAdminApi.PluginCapability, () => SimpleAdminApi);
|
|
|
|
PlayersTimer?.Kill();
|
|
PlayersTimer = null;
|
|
PlayerManager.CheckPlayersTimer();
|
|
|
|
Menus.MenuManager.Instance.InitializeDefaultCategories();
|
|
BasicMenu.Initialize();
|
|
}
|
|
|
|
public override void OnAllPluginsLoaded(bool hotReload)
|
|
{
|
|
try
|
|
{
|
|
MenuApi = MenuCapability.Get();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.LogError("Unable to load required plugins ... \n{exception}", ex.Message);
|
|
Unload(false);
|
|
}
|
|
|
|
RegisterEvents();
|
|
AddTimer(0.5f, RegisterCommands.InitializeCommands);
|
|
// Admins are reloaded by ServerManager once ServerId is known (or on its failure paths).
|
|
// Loading the plugin mid-map (css_plugins load) fires no map start, so kick server loading off ourselves.
|
|
AddTimer(5.0f, () =>
|
|
{
|
|
if (!ServerLoaded) OnGameServerSteamAPIActivated();
|
|
});
|
|
|
|
if (!CoreConfig.UnlockConCommands)
|
|
{
|
|
_logger?.LogError(
|
|
$"⚠️ Warning: 'UnlockConCommands' is disabled in core.json. " +
|
|
$"Players will not be automatically banned when kicked and will be able " +
|
|
$"to rejoin the server for 60 seconds. " +
|
|
$"To enable instant banning, set 'UnlockConCommands': true"
|
|
);
|
|
}
|
|
}
|
|
|
|
public void OnConfigParsed(CS2_SimpleAdminConfig config)
|
|
{
|
|
Helper.UpdateConfig(config);
|
|
|
|
_logger = Logger;
|
|
Config = config;
|
|
|
|
bool missing = false;
|
|
var cssPath = Path.Combine(Server.GameDirectory, "csgo", "addons", "counterstrikesharp");
|
|
var pluginsPath = Path.Combine(cssPath, "plugins");
|
|
var sharedPath = Path.Combine(cssPath, "shared");
|
|
|
|
foreach (var plugin in _requiredPlugins)
|
|
{
|
|
var pluginDirPath = Path.Combine(pluginsPath, plugin);
|
|
var pluginDllPath = Path.Combine(pluginDirPath, $"{plugin}.dll");
|
|
|
|
if (!Directory.Exists(pluginDirPath))
|
|
{
|
|
_logger?.LogError(
|
|
$"❌ Plugin directory '{plugin}' missing at: {pluginDirPath}"
|
|
);
|
|
missing = true;
|
|
}
|
|
|
|
if (!File.Exists(pluginDllPath))
|
|
{
|
|
_logger?.LogError(
|
|
$"❌ Plugin DLL '{plugin}.dll' missing at: {pluginDllPath}"
|
|
);
|
|
missing = true;
|
|
}
|
|
}
|
|
|
|
foreach (var shared in _requiredShared)
|
|
{
|
|
var sharedDirPath = Path.Combine(sharedPath, shared);
|
|
var sharedDllPath = Path.Combine(sharedDirPath, $"{shared}.dll");
|
|
|
|
if (!Directory.Exists(sharedDirPath))
|
|
{
|
|
_logger?.LogError(
|
|
$"❌ Shared library directory '{shared}' missing at: {sharedDirPath}"
|
|
);
|
|
missing = true;
|
|
}
|
|
|
|
if (!File.Exists(sharedDllPath))
|
|
{
|
|
_logger?.LogError(
|
|
$"❌ Shared library DLL '{shared}.dll' missing at: {sharedDllPath}"
|
|
);
|
|
missing = true;
|
|
}
|
|
}
|
|
|
|
if (missing)
|
|
{
|
|
Server.ExecuteCommand($"css_plugins unload {ModuleDirectory}");
|
|
return;
|
|
}
|
|
|
|
Instance = this;
|
|
|
|
if (Config.DatabaseConfig.DatabaseType.Contains("mysql", StringComparison.CurrentCultureIgnoreCase))
|
|
{
|
|
if (string.IsNullOrWhiteSpace(config.DatabaseConfig.DatabaseHost) ||
|
|
string.IsNullOrWhiteSpace(config.DatabaseConfig.DatabaseName) ||
|
|
string.IsNullOrWhiteSpace(config.DatabaseConfig.DatabaseUser))
|
|
{
|
|
throw new Exception("[CS2-SimpleAdmin] You need to setup MySQL credentials in config!");
|
|
}
|
|
|
|
var builder = new MySqlConnectionStringBuilder()
|
|
{
|
|
Server = config.DatabaseConfig.DatabaseHost,
|
|
Database = config.DatabaseConfig.DatabaseName,
|
|
UserID = config.DatabaseConfig.DatabaseUser,
|
|
Password = config.DatabaseConfig.DatabasePassword,
|
|
Port = (uint)config.DatabaseConfig.DatabasePort,
|
|
SslMode = Enum.TryParse(config.DatabaseConfig.DatabaseSSlMode, true, out MySqlSslMode sslMode)
|
|
? sslMode
|
|
: MySqlSslMode.Preferred,
|
|
Pooling = true,
|
|
};
|
|
|
|
DbConnectionString = builder.ConnectionString;
|
|
DatabaseProvider = new MySqlDatabaseProvider(DbConnectionString);
|
|
}
|
|
else
|
|
{
|
|
if (string.IsNullOrWhiteSpace(config.DatabaseConfig.SqliteFilePath))
|
|
{
|
|
throw new Exception("[CS2-SimpleAdmin] You need to specify SQLite file path in config!");
|
|
}
|
|
|
|
DatabaseProvider = new SqliteDatabaseProvider(ModuleDirectory + "/" + config.DatabaseConfig.SqliteFilePath);
|
|
}
|
|
|
|
var (success, exception) = Task.Run(() => DatabaseProvider.CheckConnectionAsync()).GetAwaiter().GetResult();
|
|
if (!success)
|
|
{
|
|
if (exception != null)
|
|
Logger.LogError("Problem with database connection! \n{exception}", exception);
|
|
|
|
Unload(false);
|
|
return;
|
|
}
|
|
|
|
Task.Run(() => DatabaseProvider.DatabaseMigrationAsync());
|
|
|
|
if (!Directory.Exists(ModuleDirectory + "/data"))
|
|
{
|
|
Directory.CreateDirectory(ModuleDirectory + "/data");
|
|
}
|
|
|
|
_localizer = Localizer;
|
|
|
|
if (!string.IsNullOrEmpty(Config.Discord.DiscordLogWebhook))
|
|
DiscordWebhookClientLog = new DiscordManager(Config.Discord.DiscordLogWebhook);
|
|
|
|
if (Config.EnableUpdateCheck)
|
|
Task.Run(async () => await PluginInfo.CheckVersion(ModuleVersion, Logger));
|
|
|
|
PermissionManager = new PermissionManager(DatabaseProvider);
|
|
BanManager = new BanManager(DatabaseProvider);
|
|
MuteManager = new MuteManager(DatabaseProvider);
|
|
WarnManager = new WarnManager(DatabaseProvider);
|
|
}
|
|
|
|
internal static TargetResult? GetTarget(CommandInfo command, int argument = 1)
|
|
{
|
|
var matches = command.GetArgTargetResult(argument);
|
|
|
|
if (!matches.Any())
|
|
{
|
|
command.ReplyToCommand($"Target {command.GetArg(argument)} not found.");
|
|
return null;
|
|
}
|
|
|
|
if (command.GetArg(argument).StartsWith('@'))
|
|
return matches;
|
|
|
|
if (matches.Count() == 1)
|
|
return matches;
|
|
|
|
command.ReplyToCommand($"Multiple targets found for \"{command.GetArg(argument)}\".");
|
|
return null;
|
|
}
|
|
|
|
public override void Unload(bool hotReload)
|
|
{
|
|
CacheManager?.Dispose();
|
|
CacheManager = null;
|
|
PlayersTimer?.Kill();
|
|
PlayersTimer = null;
|
|
|
|
UnregisterEvents();
|
|
|
|
if (hotReload)
|
|
PlayersInfo.Clear();
|
|
else
|
|
Server.ExecuteCommand($"css_plugins unload {ModuleDirectory}");
|
|
}
|
|
} |