CSSPanel Support

This commit is contained in:
Sachin 2024-10-28 17:50:22 +05:30
parent d30ac80a36
commit f01beebea9
21 changed files with 762 additions and 214 deletions

3
.gitignore vendored
View file

@ -3,4 +3,5 @@ obj/
.vs/ .vs/
.git .git
.vscode/ .vscode/
.idea/ .idea/
*.sln

View file

@ -1,11 +1,15 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.8.34309.116 VisualStudioVersion = 17.5.002.0
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CS2-SimpleAdmin", "CS2-SimpleAdmin\CS2-SimpleAdmin.csproj", "{CC7C3B4D-26C9-4DE7-B4E1-0864350468D0}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CS2-SimpleAdmin", "CS2-SimpleAdmin\CS2-SimpleAdmin.csproj", "{10611B4A-49BC-4556-A000-C1F922C4979D}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CS2-SimpleAdminApi", "CS2-SimpleAdminApi\CS2-SimpleAdminApi.csproj", "{8BEF0C35-7E4E-4BAF-B632-8584FAFCA922}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CS2-SimpleAdminApi", "CS2-SimpleAdminApi\CS2-SimpleAdminApi.csproj", "{2A46E7D8-A0AC-4EB2-BCEA-BBC9049A83DB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{264FAD58-0947-4A02-86C6-39FF99B8EA51}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CS2-SimpleAdmin_ExampleModule", "Modules\CS2-SimpleAdmin_ExampleModule\CS2-SimpleAdmin_ExampleModule.csproj", "{FD770842-F4CE-468A-A0DC-7A3A30A0CED6}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -13,19 +17,26 @@ Global
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CC7C3B4D-26C9-4DE7-B4E1-0864350468D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {10611B4A-49BC-4556-A000-C1F922C4979D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CC7C3B4D-26C9-4DE7-B4E1-0864350468D0}.Debug|Any CPU.Build.0 = Debug|Any CPU {10611B4A-49BC-4556-A000-C1F922C4979D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CC7C3B4D-26C9-4DE7-B4E1-0864350468D0}.Release|Any CPU.ActiveCfg = Release|Any CPU {10611B4A-49BC-4556-A000-C1F922C4979D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CC7C3B4D-26C9-4DE7-B4E1-0864350468D0}.Release|Any CPU.Build.0 = Release|Any CPU {10611B4A-49BC-4556-A000-C1F922C4979D}.Release|Any CPU.Build.0 = Release|Any CPU
{8BEF0C35-7E4E-4BAF-B632-8584FAFCA922}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A46E7D8-A0AC-4EB2-BCEA-BBC9049A83DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8BEF0C35-7E4E-4BAF-B632-8584FAFCA922}.Debug|Any CPU.Build.0 = Debug|Any CPU {2A46E7D8-A0AC-4EB2-BCEA-BBC9049A83DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8BEF0C35-7E4E-4BAF-B632-8584FAFCA922}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A46E7D8-A0AC-4EB2-BCEA-BBC9049A83DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8BEF0C35-7E4E-4BAF-B632-8584FAFCA922}.Release|Any CPU.Build.0 = Release|Any CPU {2A46E7D8-A0AC-4EB2-BCEA-BBC9049A83DB}.Release|Any CPU.Build.0 = Release|Any CPU
{FD770842-F4CE-468A-A0DC-7A3A30A0CED6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD770842-F4CE-468A-A0DC-7A3A30A0CED6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD770842-F4CE-468A-A0DC-7A3A30A0CED6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD770842-F4CE-468A-A0DC-7A3A30A0CED6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{FD770842-F4CE-468A-A0DC-7A3A30A0CED6} = {264FAD58-0947-4A02-86C6-39FF99B8EA51}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {86114444-059F-4DB8-9A55-E6D1BB76238D} SolutionGuid = {27D147C9-0BD5-467F-8602-83A82E4792D6}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View file

@ -51,6 +51,8 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdmin
Capabilities.RegisterPluginCapability(ICS2_SimpleAdminApi.PluginCapability, () => SimpleAdminApi); Capabilities.RegisterPluginCapability(ICS2_SimpleAdminApi.PluginCapability, () => SimpleAdminApi);
new PlayerManager().CheckPlayersTimer(); new PlayerManager().CheckPlayersTimer();
ChatManager = new ChatManager();
} }
public override void OnAllPluginsLoaded(bool hotReload) public override void OnAllPluginsLoaded(bool hotReload)

View file

@ -111,7 +111,7 @@ public partial class CS2_SimpleAdmin
} }
// Execute ban command if necessary // Execute ban command if necessary
if (UnlockedCommands) if (UnlockedCommands && Config.BanIDBan)
{ {
Server.ExecuteCommand($"banid 1 {new SteamID(player.SteamID).SteamId3}"); Server.ExecuteCommand($"banid 1 {new SteamID(player.SteamID).SteamId3}");
} }
@ -177,7 +177,7 @@ public partial class CS2_SimpleAdmin
Helper.LogCommand(caller, command); Helper.LogCommand(caller, command);
if (UnlockedCommands) if (UnlockedCommands && Config.BanIDBan)
Server.ExecuteCommand($"banid 1 {steamId.SteamId3}"); Server.ExecuteCommand($"banid 1 {steamId.SteamId3}");
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Ban, reason, time); SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Ban, reason, time);

View file

@ -365,27 +365,29 @@ public partial class CS2_SimpleAdmin
AdminManager.RemovePlayerAdminData(steamId); AdminManager.RemovePlayerAdminData(steamId);
} }
Task.Run(async () => if(!Config.IsCSSPanel)
{ {
await PermissionManager.CrateGroupsJsonFile(); Task.Run(async () =>
await PermissionManager.CreateAdminsJsonFile();
var adminsFile = await File.ReadAllTextAsync(Instance.ModuleDirectory + "/data/admins.json");
var groupsFile = await File.ReadAllTextAsync(Instance.ModuleDirectory + "/data/groups.json");
await Server.NextFrameAsync(() =>
{ {
if (!string.IsNullOrEmpty(adminsFile)) await PermissionManager.CreateGroupsJsonFile();
AddTimer(0.5f, () => AdminManager.LoadAdminData(ModuleDirectory + "/data/admins.json")); await PermissionManager.CreateAdminsJsonFile();
if (!string.IsNullOrEmpty(groupsFile))
AddTimer(1.0f, () => AdminManager.LoadAdminGroups(ModuleDirectory + "/data/groups.json"));
if (!string.IsNullOrEmpty(adminsFile))
AddTimer(1.5f, () => AdminManager.LoadAdminData(ModuleDirectory + "/data/admins.json"));
});
});
//_ = _adminManager.GiveAllGroupsFlags(); var adminsFile = await File.ReadAllTextAsync(Instance.ModuleDirectory + "/data/admins.json");
//_ = _adminManager.GiveAllFlags(); var groupsFile = await File.ReadAllTextAsync(Instance.ModuleDirectory + "/data/groups.json");
await Server.NextFrameAsync(() =>
{
if (!string.IsNullOrEmpty(adminsFile))
AddTimer(0.5f, () => AdminManager.LoadAdminData(ModuleDirectory + "/data/admins.json"));
if (!string.IsNullOrEmpty(groupsFile))
AddTimer(1.0f, () => AdminManager.LoadAdminGroups(ModuleDirectory + "/data/groups.json"));
if (!string.IsNullOrEmpty(adminsFile))
AddTimer(1.5f, () => AdminManager.LoadAdminData(ModuleDirectory + "/data/admins.json"));
});
});
}
else
_ = PermissionManager.GiveAllFlags();
} }
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)] [CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
@ -761,6 +763,8 @@ public partial class CS2_SimpleAdmin
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console"; var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
map = map.ToLower(); map = map.ToLower();
var wsMaps = Config.WorkshopMaps;
if (map.StartsWith("ws:")) if (map.StartsWith("ws:"))
{ {
var issuedCommand = long.TryParse(map.Replace("ws:", ""), out var mapId) var issuedCommand = long.TryParse(map.Replace("ws:", ""), out var mapId)
@ -776,14 +780,21 @@ public partial class CS2_SimpleAdmin
{ {
if (!Server.IsMapValid(map)) if (!Server.IsMapValid(map))
{ {
var msg = $"Map {map} not found."; if(wsMaps.ContainsKey(map))
if (command != null) {
command.ReplyToCommand(msg); map = wsMaps.Where(m => m.Key == map).FirstOrDefault().Key;
else if (caller != null && caller.IsValid) }
caller.PrintToChat(msg);
else else
Server.PrintToConsole(msg); {
return; var msg = $"Map {map} not found.";
if (command != null)
command.ReplyToCommand(msg);
else if (caller != null && caller.IsValid)
caller.PrintToChat(msg);
else
Server.PrintToConsole(msg);
return;
}
} }
AddTimer(3.0f, () => AddTimer(3.0f, () =>

View file

@ -273,7 +273,8 @@ public partial class CS2_SimpleAdmin
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null; var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
// Set player's voice flags to muted // Set player's voice flags to muted
player.VoiceFlags = VoiceFlags.Muted; if (!player.VoiceFlags.HasFlag(VoiceFlags.Muted))
player.VoiceFlags |= VoiceFlags.Muted;
// Asynchronously handle mute logic // Asynchronously handle mute logic
Task.Run(async () => Task.Run(async () =>
@ -402,7 +403,8 @@ public partial class CS2_SimpleAdmin
if (player != null && player.IsValid) if (player != null && player.IsValid)
{ {
PlayerPenaltyManager.RemovePenaltiesByType(player.Slot, PenaltyType.Mute); PlayerPenaltyManager.RemovePenaltiesByType(player.Slot, PenaltyType.Mute);
player.VoiceFlags = VoiceFlags.Normal; if (player.VoiceFlags.HasFlag(VoiceFlags.Muted))
player.VoiceFlags &= ~VoiceFlags.Muted;
Task.Run(async () => Task.Run(async () =>
{ {
@ -421,7 +423,8 @@ public partial class CS2_SimpleAdmin
if (namePlayer != null && namePlayer.IsValid) if (namePlayer != null && namePlayer.IsValid)
{ {
PlayerPenaltyManager.RemovePenaltiesByType(namePlayer.Slot, PenaltyType.Mute); PlayerPenaltyManager.RemovePenaltiesByType(namePlayer.Slot, PenaltyType.Mute);
namePlayer.VoiceFlags = VoiceFlags.Normal; if (namePlayer.VoiceFlags.HasFlag(VoiceFlags.Muted))
namePlayer.VoiceFlags &= ~VoiceFlags.Muted;
if (namePlayer.UserId.HasValue && PlayersInfo[namePlayer.UserId.Value].TotalMutes > 0) if (namePlayer.UserId.HasValue && PlayersInfo[namePlayer.UserId.Value].TotalMutes > 0)
PlayersInfo[namePlayer.UserId.Value].TotalMutes--; PlayersInfo[namePlayer.UserId.Value].TotalMutes--;
@ -491,6 +494,10 @@ public partial class CS2_SimpleAdmin
var playerInfo = PlayersInfo[player.UserId.Value]; var playerInfo = PlayersInfo[player.UserId.Value];
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null; var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
// Set player's voice flags to muted
if (!player.VoiceFlags.HasFlag(VoiceFlags.Muted))
player.VoiceFlags |= VoiceFlags.Muted;
// Asynchronously handle silence logic // Asynchronously handle silence logic
Task.Run(async () => Task.Run(async () =>
{ {
@ -620,7 +627,8 @@ public partial class CS2_SimpleAdmin
PlayerPenaltyManager.RemovePenaltiesByType(player.Slot, PenaltyType.Silence); PlayerPenaltyManager.RemovePenaltiesByType(player.Slot, PenaltyType.Silence);
// Reset voice flags to normal // Reset voice flags to normal
player.VoiceFlags = VoiceFlags.Normal; if (player.VoiceFlags.HasFlag(VoiceFlags.Muted))
player.VoiceFlags &= ~VoiceFlags.Muted;
Task.Run(async () => Task.Run(async () =>
{ {
@ -641,7 +649,8 @@ public partial class CS2_SimpleAdmin
PlayerPenaltyManager.RemovePenaltiesByType(namePlayer.Slot, PenaltyType.Silence); PlayerPenaltyManager.RemovePenaltiesByType(namePlayer.Slot, PenaltyType.Silence);
// Reset voice flags to normal // Reset voice flags to normal
namePlayer.VoiceFlags = VoiceFlags.Normal; if (namePlayer.VoiceFlags.HasFlag(VoiceFlags.Muted))
namePlayer.VoiceFlags &= ~VoiceFlags.Muted;
if (namePlayer.UserId.HasValue && PlayersInfo[namePlayer.UserId.Value].TotalSilences > 0) if (namePlayer.UserId.HasValue && PlayersInfo[namePlayer.UserId.Value].TotalSilences > 0)
PlayersInfo[namePlayer.UserId.Value].TotalSilences--; PlayersInfo[namePlayer.UserId.Value].TotalSilences--;

View file

@ -0,0 +1,136 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes.Registration;
using CounterStrikeSharp.API.Core.Translations;
using CounterStrikeSharp.API.Modules.Admin;
using CounterStrikeSharp.API.Modules.Commands;
using CounterStrikeSharp.API.Modules.Cvars;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Menu;
using CounterStrikeSharp.API.Modules.Utils;
using CS2_SimpleAdmin.Managers;
using CS2_SimpleAdmin.Menus;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Globalization;
using System.Text;
namespace CS2_SimpleAdmin;
public partial class CS2_SimpleAdmin
{
[ConsoleCommand("css_panel_say", "Say to all players from the panel.")]
[CommandHelper(1, "<message>")]
[RequiresPermissions("@css/root")]
public void OnPanelSayCommand(CCSPlayerController? caller, CommandInfo command)
{
if (!Config.IsCSSPanel) return;
if (command.GetCommandString[command.GetCommandString.IndexOf(' ')..].Length == 0) return;
byte[] utf8BytesString = Encoding.UTF8.GetBytes(command.GetCommandString[command.GetCommandString.IndexOf(' ')..]);
string utf8String = Encoding.UTF8.GetString(utf8BytesString);
foreach (CCSPlayerController player in Utilities.GetPlayers().Where(p => !p.IsBot && !p.IsHLTV))
{
player.PrintToChat(StringExtensions.ReplaceColorTags(utf8String));
}
}
/**
* Prints the server info and a list of players to the console
*/
[ConsoleCommand("css_query")]
[CommandHelper(whoCanExecute: CommandUsage.SERVER_ONLY)]
[RequiresPermissions("@css/root")]
public void OnQueryCommand(CCSPlayerController? caller, CommandInfo command)
{
if (!Config.IsCSSPanel) return;
List<CCSPlayerController> playersToTarget = Utilities.GetPlayers().Where(player => caller!.CanTarget(player) && !player.IsHLTV).ToList();
string Map = Server.MapName;
int Players = playersToTarget.Count;
int MaxPlayers = Server.MaxPlayers;
string[] Maps;
MaxPlayers = ConVar.Find("sv_visiblemaxplayers")?.GetPrimitiveValue<int>() ?? -1;
MaxPlayers = MaxPlayers <= -1 ? Server.MaxPlayers : MaxPlayers;
try
{
Maps = Server.GetMapList();
}
catch (Exception)
{
Maps = Array.Empty<string>(); // return an empty array
}
var server = new
{
map = Map,
p = Players,
mP = MaxPlayers,
// maps = Maps,
pr = ModuleVersion
};
List<Task<object>> playerTasks = playersToTarget
.FindAll(player => !player.IsBot && !player.IsHLTV && player.PlayerName != "")
.Select(player =>
{
string deaths = player.ActionTrackingServices!.MatchStats.Deaths.ToString();
string headshots = player.ActionTrackingServices!.MatchStats.HeadShotKills.ToString();
string assists = player.ActionTrackingServices!.MatchStats.Assists.ToString();
string damage = player.ActionTrackingServices!.MatchStats.Damage.ToString();
string kills = player.ActionTrackingServices!.MatchStats.Kills.ToString();
string time = player.ActionTrackingServices!.MatchStats.LiveTime.ToString();
var user = new
{
id = player.UserId,
// playerName = player.PlayerName,
// ipAddress = player.IpAddress?.Split(":")[0],
// accountId = player.AuthorizedSteamID?.AccountId.ToString(),
// steamId2 = player.AuthorizedSteamID?.SteamId2,
// steamId3 = player.AuthorizedSteamID?.SteamId3,
s64 = player.AuthorizedSteamID?.SteamId64.ToString(),
// ping = player.Ping,
t = player.Team,
// clanName = player.ClanName,
k = kills,
d = deaths,
// assists,
// headshots,
// damage,
s = player.Score,
// roundScore = player.RoundScore,
// roundsWon = player.RoundsWon,
// mvps = player.MVPs,
// time, // ? Fix this, it's not the time the player has been connected
// avatar = player.AuthorizedSteamID != null ? await GetProfilePictureAsync(player.AuthorizedSteamID.SteamId64.ToString(), true) : ""
};
return Task.FromResult((object)user);
}).ToList();
List<object> players = new List<object>();
try
{
players = Task.WhenAll(playerTasks).Result.ToList();
}
catch (AggregateException ex)
{
foreach (var innerEx in ex.InnerExceptions)
{
Logger.LogError(innerEx, "Error while querying players");
}
}
string jsonString = JsonConvert.SerializeObject(
new
{
server,
players
}
);
Server.PrintToConsole(jsonString);
}
}

View file

@ -307,7 +307,6 @@ public partial class CS2_SimpleAdmin
} }
} }
[ConsoleCommand("css_gravity")]
[RequiresPermissions("@css/slay")] [RequiresPermissions("@css/slay")]
[CommandHelper(minArgs: 1, usage: "<#userid or name> <gravity>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] [CommandHelper(minArgs: 1, usage: "<#userid or name> <gravity>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnGravityCommand(CCSPlayerController? caller, CommandInfo command) public void OnGravityCommand(CCSPlayerController? caller, CommandInfo command)

View file

@ -91,6 +91,21 @@ public class Discord
]; ];
} }
public class ChatLog
{
[JsonPropertyName("ChatLog_Enable")]
public bool ChatLog_Enable { get; set; } = true;
[JsonPropertyName("ChatLog_ExcludeMessageContains")]
public string ExcludeMessageContains { get; set; } = "!./";
[JsonPropertyName("ChatLog_ExcludeMessageContainsLessThanXLetters")]
public int ExcludeMessageContainsLessThanXLetters { get; set; } = 0;
[JsonPropertyName("ChatLog_ExcludeMessageDuplicate")]
public bool ExcludeMessageDuplicate { get; set; } = false;
}
public class CustomServerCommandData public class CustomServerCommandData
{ {
[JsonPropertyName("Flag")] [JsonPropertyName("Flag")]
@ -273,4 +288,16 @@ public class CS2_SimpleAdminConfig : BasePluginConfig
[JsonPropertyName("MenuConfig")] [JsonPropertyName("MenuConfig")]
public MenuConfig MenuConfigs { get; set; } = new(); public MenuConfig MenuConfigs { get; set; } = new();
[JsonPropertyName("ChatLog")]
public ChatLog ChatLog { get; set; } = new ChatLog();
[JsonPropertyName("Statistics_Enable")]
public bool Statistics_Enable { get; set; } = true;
[JsonPropertyName("IsCSSPanel")]
public bool IsCSSPanel { get; set; } = false;
[JsonPropertyName("BanIDBan")]
public bool BanIDBan { get; set; } = true;
} }

View file

@ -45,6 +45,36 @@ CREATE TABLE IF NOT EXISTS `sa_servers` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`hostname` varchar(128) NOT NULL, `hostname` varchar(128) NOT NULL,
`address` varchar(64) NOT NULL, `address` varchar(64) NOT NULL,
`rcon` varchar(64) NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `address` (`address`) UNIQUE KEY `address` (`address`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS `sa_chatlogs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`serverId` varchar(64) NOT NULL,
`playerSteam64` varchar(64) NOT NULL,
`playerName` varchar(64) NOT NULL,
`message` TEXT,
`team` BOOLEAN NOT NULL,
`created` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS `sa_statistics` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`serverId` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
`playerId` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
`playerName` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
`playerIP` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
`connectDate` timestamp DEFAULT CURRENT_TIMESTAMP,
`connectTime` INT(20) NOT NULL,
`disconnectDate` timestamp NULL DEFAULT NULL,
`disconnectTime` INT(20) NULL DEFAULT NULL,
`duration` INT(20) NULL DEFAULT NULL,
`kills` INT(10) NULL DEFAULT NULL,
`flags` TEXT COLLATE 'utf8mb4_general_ci',
`map` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
PRIMARY KEY (`id`) USING BTREE,
INDEX `playerId` (`playerId`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

View file

@ -0,0 +1,30 @@
ALTER TABLE `sa_servers` ADD `rcon` varchar(64) NOT NULL AFTER `address`;
CREATE TABLE IF NOT EXISTS `sa_chatlogs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`serverId` varchar(64) NOT NULL,
`playerSteam64` varchar(64) NOT NULL,
`playerName` varchar(64) NOT NULL,
`message` TEXT,
`team` BOOLEAN NOT NULL,
`created` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS `sa_statistics` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`serverId` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
`playerId` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
`playerName` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
`playerIP` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
`connectDate` timestamp DEFAULT CURRENT_TIMESTAMP,
`connectTime` INT(20) NOT NULL,
`disconnectDate` timestamp NULL DEFAULT NULL,
`disconnectTime` INT(20) NULL DEFAULT NULL,
`duration` INT(20) NULL DEFAULT NULL,
`kills` INT(10) NULL DEFAULT NULL,
`flags` TEXT COLLATE 'utf8mb4_general_ci',
`map` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
PRIMARY KEY (`id`) USING BTREE,
INDEX `playerId` (`playerId`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

View file

@ -117,7 +117,13 @@ public partial class CS2_SimpleAdmin
if (player == null || !player.IsValid || player.IsBot) if (player == null || !player.IsValid || player.IsBot)
return HookResult.Continue; return HookResult.Continue;
new PlayerManager().LoadPlayerData(player); AddTimer(1.25f, () =>
{
if(player == null || !player.IsValid)
return;
new PlayerManager().LoadPlayerData(player);
});
return HookResult.Continue; return HookResult.Continue;
} }
@ -164,7 +170,8 @@ public partial class CS2_SimpleAdmin
if (!command.Contains("say")) if (!command.Contains("say"))
return HookResult.Continue; return HookResult.Continue;
if (info.GetArg(1).StartsWith($"/") if (string.IsNullOrWhiteSpace(info.GetArg(1))
|| info.GetArg(1).StartsWith($"/")
|| info.GetArg(1).StartsWith($"!")) || info.GetArg(1).StartsWith($"!"))
return HookResult.Continue; return HookResult.Continue;
@ -180,6 +187,36 @@ public partial class CS2_SimpleAdmin
player.ExecuteClientCommandFromServer($"css_say {info.GetArg(1).Remove(0, 1)}"); player.ExecuteClientCommandFromServer($"css_say {info.GetArg(1).Remove(0, 1)}");
return HookResult.Stop; return HookResult.Stop;
} }
if ((command == "say" || command == "say_team") && Config.IsCSSPanel)
{
var message = info.GetArg(1);
string trimmedMessage1 = message.TrimStart();
string trimmedMessage = trimmedMessage1.TrimEnd();
//Console.WriteLine($"{IsStringValid(trimmedMessage)} | {Config.ChatLog.ExcludeMessageContainsLessThanXLetters} | {CountLetters(trimmedMessage)}");
if (IsStringValid(trimmedMessage) && (Config.ChatLog.ExcludeMessageContainsLessThanXLetters <= 0 || CountLetters(trimmedMessage) > Config.ChatLog.ExcludeMessageContainsLessThanXLetters))
{
var vplayername = player.PlayerName;
var steamId64 = (player.AuthorizedSteamID != null) ? player.AuthorizedSteamID.SteamId64.ToString() : "InvalidSteamID";
secondMessage = firstMessage;
firstMessage = trimmedMessage;
if (!Config.ChatLog.ExcludeMessageDuplicate || secondMessage != firstMessage)
{
// Add to db
ChatManager.AddChatMessageDB(
steamId64,
vplayername,
trimmedMessage,
command.Contains("say_team")
);
}
}
}
if (command != "say_team" || !info.GetArg(1).StartsWith($"@")) return HookResult.Continue; if (command != "say_team" || !info.GetArg(1).StartsWith($"@")) return HookResult.Continue;

View file

@ -0,0 +1,130 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes.Registration;
using CounterStrikeSharp.API.Modules.Commands;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Utils;
using CS2_SimpleAdmin.Managers;
using CS2_SimpleAdmin.Models;
using Microsoft.Extensions.Logging;
using System.Text;
using CounterStrikeSharp.API.Modules.Admin;
using Dapper;
namespace CS2_SimpleAdmin;
public partial class CS2_SimpleAdmin
{
[GameEventHandler]
public HookResult OnPlayerConnectStatistics(EventPlayerConnectFull @event, GameEventInfo info)
{
if (!Config.IsCSSPanel) return HookResult.Continue;
if (Config.Statistics_Enable == false) return HookResult.Continue;
CCSPlayerController? player = @event.Userid;
if (player == null || string.IsNullOrEmpty(player.IpAddress) || player.IpAddress.Contains("127.0.0.1")
|| player.IsBot || player.IsHLTV || !player.UserId.HasValue || player.AuthorizedSteamID == null)
{
return HookResult.Continue;
}
if (Database == null) return HookResult.Continue;
SteamID authorizedSteamID = player.AuthorizedSteamID!;
string ipAddress = player.IpAddress!.Split(":")[0];
string playerId = authorizedSteamID.SteamId64.ToString();
string playerName = player.PlayerName;
// Unix timestamp
long Time = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
string Map = Server.MapName;
if (ServerId == null)
return HookResult.Continue;
Task.Run(async () =>
{
try
{
await using var connection = await Database.GetConnectionAsync();
string sql = "INSERT INTO `sa_statistics` (`serverId`, `playerId`, `playerName`, `playerIP`, `connectTime`, `flags`, `map`) " +
"VALUES (@serverId, @playerId, @playerName, @playerIP, @connectTime, @flags, @map)";
List<string> adminFlags = await PermissionManager.GetAdminFlagsAsString(playerId);
await connection.ExecuteAsync(sql, new
{
serverId = ServerId,
playerId,
playerName,
playerIP = ipAddress,
connectTime = Time,
flags = adminFlags.Count > 0 ? string.Join(",", adminFlags) : null,
map = Map
});
}
catch (Exception ex)
{
Logger.LogError($"An error occurred in OnPlayerConnect: {ex.Message}");
}
});
return HookResult.Continue;
}
[GameEventHandler]
public HookResult OnClientDisconnectStatistics(EventPlayerDisconnect @event, GameEventInfo info)
{
if (!Config.IsCSSPanel) return HookResult.Continue;
if (Config.Statistics_Enable == false) return HookResult.Continue;
CCSPlayerController? player = @event.Userid;
if (player == null || string.IsNullOrEmpty(player.IpAddress) || player.IpAddress.Contains("127.0.0.1")
|| player.IsBot || player.IsHLTV || !player.UserId.HasValue || player.AuthorizedSteamID == null)
return HookResult.Continue;
if (Database == null) return HookResult.Continue;
SteamID authorizedSteamID = player.AuthorizedSteamID!;
string ipAddress = player.IpAddress!.Split(":")[0];
string playerId = authorizedSteamID.SteamId64.ToString();
string playerName = player.PlayerName;
DateTime now = DateTime.Now;
// Unix timestamp
long Time = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
string kills = player.ActionTrackingServices!.MatchStats.Kills.ToString();
Task.Run(async () =>
{
try
{
await using var connection = await Database.GetConnectionAsync();
string sql = "UPDATE `sa_statistics` SET `disconnectTime` = @disconnectTime, `disconnectDate` = @disconnectDate, `kills` = @kills, `duration` = @disconnectTime - `connectTime` " +
"WHERE `playerId` = @playerId AND `disconnectTime` IS NULL";
await connection.ExecuteAsync(sql, new
{
disconnectTime = Time,
disconnectDate = now,
kills,
playerId,
});
}
catch (Exception ex)
{
Logger.LogError($"An error occurred in OnClientDisconnectStatistics: {ex.Message}");
}
});
return HookResult.Continue;
}
}

View file

@ -22,6 +22,33 @@ using CS2_SimpleAdmin.Managers;
namespace CS2_SimpleAdmin; namespace CS2_SimpleAdmin;
public partial class CS2_SimpleAdmin
{
bool IsStringValid(string input)
{
if (!string.IsNullOrEmpty(input) && (string.IsNullOrEmpty(Config.ChatLog.ExcludeMessageContains) || !input.Any(c => Config.ChatLog.ExcludeMessageContains.Contains(c))) && !char.IsWhiteSpace(input.Last()))
{
return true;
}
return false;
}
static int CountLetters(string input)
{
int count = 0;
foreach (char c in input)
{
if (char.IsLetter(c))
{
count++;
}
}
return count;
}
}
internal static class Helper internal static class Helper
{ {
private static readonly string AssemblyName = Assembly.GetExecutingAssembly().GetName().Name ?? ""; private static readonly string AssemblyName = Assembly.GetExecutingAssembly().GetName().Name ?? "";

View file

@ -0,0 +1,40 @@
using Dapper;
using Microsoft.Extensions.Logging;
namespace CS2_SimpleAdmin.Managers;
public class ChatManager
{
public void AddChatMessageDB(string playerSteam64, string playerName, string message, bool? team)
{
if (CS2_SimpleAdmin.Database == null) return;
Task.Run(async () =>
{
try
{
await using var connection = await CS2_SimpleAdmin.Database.GetConnectionAsync();
var sql = "INSERT INTO `sa_chatlogs` (`playerSteam64`, `playerName`, `message`, `team`, `created`, `serverId`) " +
"VALUES (@playerSteam64, @playerName, @message, @team, @created, @serverId)";
int? serverId = CS2_SimpleAdmin.ServerId;
if (serverId == null)
return;
DateTime now = DateTime.Now;
await connection.ExecuteAsync(sql, new
{
playerSteam64,
playerName,
message,
team = team ?? null,
created = now,
serverid = serverId
});
}
catch (Exception e)
{
CS2_SimpleAdmin._logger?.LogError(e.Message);
}
});
}
}

View file

@ -1,4 +1,5 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Entities;
using Dapper; using Dapper;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -14,22 +15,77 @@ public class PermissionManager(Database.Database? database)
//public static readonly ConcurrentDictionary<string, ConcurrentBag<string>> _adminCache = new ConcurrentDictionary<string, ConcurrentBag<string>>(); //public static readonly ConcurrentDictionary<string, ConcurrentBag<string>> _adminCache = new ConcurrentDictionary<string, ConcurrentBag<string>>();
public static readonly ConcurrentDictionary<SteamID, DateTime?> AdminCache = new(); public static readonly ConcurrentDictionary<SteamID, DateTime?> AdminCache = new();
/* // Get the relevant server groups from the sa_servers_groups table by searching if the serverId is in the servers set column
public async Task<List<(List<string>, int)>> GetAdminFlags(string steamId) public async Task<List<string>> GetServerGroups()
{ {
DateTime now = Time.ActualDateTime(); if (database == null) return [];
await using MySqlConnection connection = await database.GetConnectionAsync();
await using MySqlConnection connection = await _database.GetConnectionAsync(); string sql = "SELECT id FROM sa_servers_groups WHERE FIND_IN_SET(@ServerId, servers)";
List<dynamic>? serverGroups = (await connection.QueryAsync(sql, new { ServerId = CS2_SimpleAdmin.ServerId }))?.ToList();
if (serverGroups == null)
{
return new List<string>();
}
List<string> serverGroupsList = new List<string>();
foreach (dynamic serverGroup in serverGroups)
{
if (serverGroup is not IDictionary<string, object> serverGroupDict)
{
Console.WriteLine("[GetServerGroups] Failed to parse server group.");
continue;
}
if (!serverGroupDict.TryGetValue("id", out var idObj))
{
Console.WriteLine("[GetServerGroups] Failed to get server group id.");
continue;
}
if (idObj is not string id)
{
// Convert to string and add it to the list
// Console.WriteLine("[GetServerGroups] Failed to parse server group id.");
serverGroupsList.Add(idObj.ToString()!);
continue;
}
serverGroupsList.Add(id);
}
Console.WriteLine($"[GetServerGroups] Server Groups List: {string.Join(", ", serverGroupsList)}");
return serverGroupsList;
}
public async Task<List<string>> GetAdminFlagsAsString(string steamId)
{
if (database == null) return [];
DateTime now = DateTime.UtcNow.ToLocalTime();
await using MySqlConnection connection = await database.GetConnectionAsync();
// string sql = "SELECT flags, immunity, ends FROM sa_admins WHERE player_steamid = @PlayerSteamID AND (ends IS NULL OR ends > @CurrentTime) AND (server_id IS NULL OR FIND_IN_SET(@serverid, server_id) > 0)";
// string sql = "SELECT player_steamid, flags, immunity, ends FROM sa_admins WHERE (ends IS NULL OR ends > @CurrentTime) AND (server_id IS NULL OR FIND_IN_SET(@serverid, server_id) > 0)";
List<string> serverGroups = await GetServerGroups();
string serverGroupsCondition = string.Join(" OR ", serverGroups.Select(g => $"FIND_IN_SET({g}, servers_groups) > 0"));
string GroupCheck = serverGroups.Count > 0 ? $"AND (((server_id IS NULL AND servers_groups IS NULL) OR FIND_IN_SET(@serverid, server_id) > 0) OR (servers_groups IS NULL OR {serverGroupsCondition}))" : "AND ((server_id IS NULL AND servers_groups IS NULL) OR FIND_IN_SET(@serverid, server_id) > 0)";
string sql = $"SELECT flags, immunity, ends FROM sa_admins WHERE player_steamid = @PlayerSteamID AND (ends IS NULL OR ends > @CurrentTime) {GroupCheck}";
string sql = "SELECT flags, immunity, ends FROM sa_admins WHERE player_steamid = @PlayerSteamID AND (ends IS NULL OR ends > @CurrentTime) AND (server_id IS NULL OR server_id = @serverid)";
List<dynamic>? activeFlags = (await connection.QueryAsync(sql, new { PlayerSteamID = steamId, CurrentTime = now, serverid = CS2_SimpleAdmin.ServerId }))?.ToList(); List<dynamic>? activeFlags = (await connection.QueryAsync(sql, new { PlayerSteamID = steamId, CurrentTime = now, serverid = CS2_SimpleAdmin.ServerId }))?.ToList();
if (activeFlags == null) if (activeFlags == null)
{ {
return new List<(List<string>, int)>(); return new List<string>();
} }
List<(List<string>, int)> filteredFlagsWithImmunity = []; List<string> flagsList = new List<string>();
foreach (dynamic flags in activeFlags) foreach (dynamic flags in activeFlags)
{ {
@ -38,26 +94,160 @@ public class PermissionManager(Database.Database? database)
continue; continue;
} }
if (!flagsDict.TryGetValue("flags", out var flagsValueObj) || !flagsDict.TryGetValue("immunity", out var immunityValueObj)) if (!flagsDict.TryGetValue("flags", out var flagsValueObj))
{ {
continue; continue;
} }
if (!(flagsValueObj is string flagsValue) || !int.TryParse(immunityValueObj.ToString(), out var immunityValue)) if (!(flagsValueObj is string flagsValue))
{ {
continue; continue;
} }
//Console.WriteLine($"Flags: {flagsValue}, Immunity: {immunityValue}"); // If flags start with '#', fetch flags from sa_admins_groups
if (flagsValue.StartsWith("#"))
{
string groupSql = "SELECT flags FROM sa_admins_groups WHERE id = @GroupId";
var group = await connection.QueryFirstOrDefaultAsync(groupSql, new { GroupId = flagsValue });
filteredFlagsWithImmunity.Add((flagsValue.Split(',').ToList(), immunityValue)); if (group != null)
{
flagsValue = group.flags;
}
}
flagsList.AddRange(flagsValue.Split(','));
} }
return filteredFlagsWithImmunity; return flagsList;
} }
*/
private async Task<List<(string, string, List<string>, int, DateTime?)>> GetAllPlayersFlags() public async Task<List<(string, List<string>, int, DateTime?)>> GetAllPlayersFlags()
{
if (database == null) return [];
DateTime now = DateTime.UtcNow.ToLocalTime();
try
{
await using MySqlConnection connection = await database.GetConnectionAsync();
// string sql = "SELECT player_steamid, flags, immunity, ends FROM sa_admins WHERE (ends IS NULL OR ends > @CurrentTime) AND (server_id IS NULL OR FIND_IN_SET(@serverid, server_id) > 0)";
List<string> serverGroups = await GetServerGroups();
string serverGroupsCondition = string.Join(" OR ", serverGroups.Select(g => $"FIND_IN_SET({g}, servers_groups) > 0"));
string GroupCheck = serverGroups.Count > 0 ? $"AND (((server_id IS NULL AND servers_groups IS NULL) OR FIND_IN_SET(@serverid, server_id) > 0) OR (servers_groups IS NULL OR {serverGroupsCondition}))" : "AND ((server_id IS NULL AND servers_groups IS NULL) OR FIND_IN_SET(@serverid, server_id) > 0)";
string sql = $"SELECT player_steamid, flags, immunity, ends FROM sa_admins WHERE (ends IS NULL OR ends > @CurrentTime) {GroupCheck}";
List<dynamic>? activeFlags = (await connection.QueryAsync(sql, new { CurrentTime = now, serverid = CS2_SimpleAdmin.ServerId }))?.ToList();
if (activeFlags == null)
{
return new List<(string, List<string>, int, DateTime?)>();
}
List<(string, List<string>, int, DateTime?)> filteredFlagsWithImmunity = new List<(string, List<string>, int, DateTime?)>();
foreach (dynamic flags in activeFlags)
{
if (flags is not IDictionary<string, object> flagsDict)
{
continue;
}
if (!flagsDict.TryGetValue("player_steamid", out var steamIdObj) ||
!flagsDict.TryGetValue("flags", out var flagsValueObj) ||
!flagsDict.TryGetValue("immunity", out var immunityValueObj) ||
!flagsDict.TryGetValue("ends", out var endsObj))
{
//Console.WriteLine("One or more required keys are missing.");
continue;
}
DateTime? ends = null;
if (endsObj != null) // Check if "ends" is not null
{
if (!DateTime.TryParse(endsObj.ToString(), out var parsedEnds))
{
//Console.WriteLine("Failed to parse 'ends' value.");
continue;
}
ends = parsedEnds;
}
if (!(steamIdObj is string steamId) ||
!(flagsValueObj is string flagsValue) ||
!int.TryParse(immunityValueObj.ToString(), out var immunityValue))
{
//Console.WriteLine("Failed to parse one or more values.");
continue;
}
//
if (flagsValue.StartsWith("#"))
{
string groupSql = "SELECT flags, immunity FROM sa_admins_groups WHERE id = @GroupId";
var group = await connection.QueryFirstOrDefaultAsync(groupSql, new { GroupId = flagsValue });
if (group != null)
{
flagsValue = group.flags;
if (int.TryParse(group.immunity.ToString(), out int immunityGroupValue))
{
filteredFlagsWithImmunity.Add((steamId, flagsValue.Split(',').ToList(), immunityGroupValue, ends));
// Console.WriteLine($"Flags Check (Group): SteamId {steamId} Flags: {flagsValue}, Immunity: {immunityValue}");
continue;
}
else
{
Console.WriteLine($"Failed to parse immunity: {group.immunity}");
}
}
}
filteredFlagsWithImmunity.Add((steamId, flagsValue.Split(',').ToList(), immunityValue, ends));
}
return filteredFlagsWithImmunity;
}
catch (Exception e)
{
Console.WriteLine($"Error: {e.Message}");
return new List<(string, List<string>, int, DateTime?)>();
}
}
public async Task GiveAllFlags()
{
List<(string, List<string>, int, DateTime?)> allPlayers = await GetAllPlayersFlags();
foreach (var record in allPlayers)
{
string steamIdStr = record.Item1;
List<string> flags = record.Item2;
int immunity = record.Item3;
DateTime? ends = record.Item4;
if (!string.IsNullOrEmpty(steamIdStr) && SteamID.TryParse(steamIdStr, out var steamId) && steamId != null)
{
if (!AdminCache.ContainsKey(steamId))
{
AdminCache.TryAdd(steamId, ends);
//_adminCacheTimestamps.Add(steamId, ends);
}
Helper.GivePlayerFlags(steamId, flags, (uint)immunity);
// Often need to call 2 times
Helper.GivePlayerFlags(steamId, flags, (uint)immunity);
}
}
}
private async Task<List<(string, string, List<string>, int, DateTime?)>> GetAllPlayersFlagsSA()
{ {
if (database == null) return []; if (database == null) return [];
@ -111,71 +301,6 @@ public class PermissionManager(Database.Database? database)
} }
} }
/*
public async Task<Dictionary<int, Tuple<List<string>, List<Tuple<string, DateTime?>>, int>>> GetAllGroupsFlags()
{
try
{
await using MySqlConnection connection = await _database.GetConnectionAsync();
string sql = "SELECT group_id FROM sa_groups_servers WHERE server_id = @serverid";
var groupIds = connection.Query<int>(sql, new { serverid = CS2_SimpleAdmin.ServerId }).ToList();
sql = @"
SELECT g.group_id, f.flag
FROM sa_groups_flags f
JOIN sa_groups_servers g ON f.group_id = g.group_id
WHERE g.server_id = @serverid";
var groupFlagData = connection.Query(sql, new { serverid = CS2_SimpleAdmin.ServerId }).ToList();
if (groupIds.Count == 0 || groupFlagData.Count == 0)
{
return [];
}
var groupInfoDictionary = new Dictionary<int, Tuple<List<string>, List<Tuple<string, DateTime?>>, int>>();
foreach (var groupId in groupIds)
{
groupInfoDictionary[groupId] = new Tuple<List<string>, List<Tuple<string, DateTime?>>, int>([], [], 0);
}
foreach (var row in groupFlagData)
{
var groupId = (int)row.group_id;
var flag = (string)row.flag;
groupInfoDictionary[groupId].Item1.Add(flag);
}
sql = @"
SELECT a.group_id, a.player_steamid, a.ends, g.immunity, g.name
FROM sa_admins a
JOIN sa_groups g ON a.group_id = g.id
WHERE a.group_id IN @groupIds";
var playerData = (await connection.QueryAsync(sql, new { groupIds })).ToList();
foreach (var row in playerData)
{
var groupId = (int)row.group_id;
var playerSteamid = (string)row.player_steamid;
var ends = row.ends as DateTime?;
var immunity = (int)row.immunity;
groupInfoDictionary[groupId].Item2.Add(new Tuple<string, DateTime?>(playerSteamid, ends));
groupInfoDictionary[groupId] = new Tuple<List<string>, List<Tuple<string, DateTime?>>, int>(groupInfoDictionary[groupId].Item1, groupInfoDictionary[groupId].Item2, immunity);
}
return groupInfoDictionary;
}
catch { }
return [];
}
*/
private async Task<Dictionary<string, (List<string>, int)>> GetAllGroupsData() private async Task<Dictionary<string, (List<string>, int)>> GetAllGroupsData()
{ {
if (database == null) return []; if (database == null) return [];
@ -184,6 +309,7 @@ public class PermissionManager(Database.Database? database)
try try
{ {
var sql = "SELECT group_id FROM sa_groups_servers WHERE (server_id = @serverid OR server_id IS NULL)"; var sql = "SELECT group_id FROM sa_groups_servers WHERE (server_id = @serverid OR server_id IS NULL)";
var groupDataSql = connection.Query<int>(sql, new { serverid = CS2_SimpleAdmin.ServerId }).ToList(); var groupDataSql = connection.Query<int>(sql, new { serverid = CS2_SimpleAdmin.ServerId }).ToList();
sql = """ sql = """
@ -230,7 +356,7 @@ public class PermissionManager(Database.Database? database)
return []; return [];
} }
public async Task CrateGroupsJsonFile() public async Task CreateGroupsJsonFile()
{ {
var groupsData = await GetAllGroupsData(); var groupsData = await GetAllGroupsData();
@ -252,69 +378,9 @@ public class PermissionManager(Database.Database? database)
await File.WriteAllTextAsync(filePath, json); await File.WriteAllTextAsync(filePath, json);
} }
/*
public async Task GiveAllGroupsFlags()
{
Dictionary<int, Tuple<List<string>, List<Tuple<string, DateTime?>>, int>> groupFlags = await GetAllGroupsFlags();
foreach (var kvp in groupFlags)
{
var flags = kvp.Value.Item1;
var players = kvp.Value.Item2;
int immunity = kvp.Value.Item3;
foreach (var playerTuple in players)
{
var steamIdStr = playerTuple.Item1;
var ends = playerTuple.Item2;
if (!string.IsNullOrEmpty(steamIdStr) && SteamID.TryParse(steamIdStr, out var steamId) && steamId != null)
{
if (!_adminCache.ContainsKey(steamId))
{
_adminCache.TryAdd(steamId, ends);
}
Helper.GivePlayerFlags(steamId, flags, (uint)immunity);
// Often need to call 2 times
Helper.GivePlayerFlags(steamId, flags, (uint)immunity);
}
}
}
}
*/
/*
public async Task GiveAllFlags()
{
List<(string, string, List<string>, int, DateTime?)> allPlayers = await GetAllPlayersFlags();
foreach (var record in allPlayers)
{
string steamIdStr = record.Item1;
List<string> flags = record.Item2;
int immunity = record.Item3;
DateTime? ends = record.Item4;
if (!string.IsNullOrEmpty(steamIdStr) && SteamID.TryParse(steamIdStr, out var steamId) && steamId != null)
{
if (!_adminCache.ContainsKey(steamId))
{
_adminCache.TryAdd(steamId, ends);
//_adminCacheTimestamps.Add(steamId, ends);
}
Helper.GivePlayerFlags(steamId, flags, (uint)immunity);
// Often need to call 2 times
Helper.GivePlayerFlags(steamId, flags, (uint)immunity);
}
}
}
*/
public async Task CreateAdminsJsonFile() public async Task CreateAdminsJsonFile()
{ {
List<(string identity, string name, List<string> flags, int immunity, DateTime? ends)> allPlayers = await GetAllPlayersFlags(); List<(string identity, string name, List<string> flags, int immunity, DateTime? ends)> allPlayers = await GetAllPlayersFlagsSA();
var validPlayers = allPlayers var validPlayers = allPlayers
.Where(player => SteamID.TryParse(player.identity, out _)) // Filter invalid SteamID .Where(player => SteamID.TryParse(player.identity, out _)) // Filter invalid SteamID
.ToList(); .ToList();

View file

@ -109,7 +109,7 @@ public class PlayerManager
if (victim?.UserId == null) return; if (victim?.UserId == null) return;
if (CS2_SimpleAdmin.UnlockedCommands) if (CS2_SimpleAdmin.UnlockedCommands && _config.BanIDBan)
Server.ExecuteCommand($"banid 1 {userId}"); Server.ExecuteCommand($"banid 1 {userId}");
Helper.KickPlayer(userId, NetworkDisconnectionReason.NETWORK_DISCONNECT_REJECT_BANNED); Helper.KickPlayer(userId, NetworkDisconnectionReason.NETWORK_DISCONNECT_REJECT_BANNED);
@ -178,7 +178,9 @@ public class PlayerManager
AdminManager.PlayerHasPermissions(p, "@css/ban")) && AdminManager.PlayerHasPermissions(p, "@css/ban")) &&
p.Connected == PlayerConnectedState.PlayerConnected && !CS2_SimpleAdmin.AdminDisabledJoinComms.Contains(p.SteamID))) p.Connected == PlayerConnectedState.PlayerConnected && !CS2_SimpleAdmin.AdminDisabledJoinComms.Contains(p.SteamID)))
{ {
if (CS2_SimpleAdmin._localizer != null && admin != player) if (CS2_SimpleAdmin._localizer != null && admin != player
&& (CS2_SimpleAdmin.PlayersInfo[userId].TotalBans > 0 || CS2_SimpleAdmin.PlayersInfo[userId].TotalGags > 0 || CS2_SimpleAdmin.PlayersInfo[userId].TotalMutes > 0 || CS2_SimpleAdmin.PlayersInfo[userId].TotalSilences > 0 || CS2_SimpleAdmin.PlayersInfo[userId].TotalWarns > 0)
)
admin.SendLocalizedMessage(CS2_SimpleAdmin._localizer, "sa_admin_penalty_info", admin.SendLocalizedMessage(CS2_SimpleAdmin._localizer, "sa_admin_penalty_info",
player.PlayerName, player.PlayerName,
CS2_SimpleAdmin.PlayersInfo[userId].TotalBans, CS2_SimpleAdmin.PlayersInfo[userId].TotalBans,
@ -253,13 +255,14 @@ public class PlayerManager
{ {
foreach (var player in players.Where(player => PlayerPenaltyManager.IsSlotInPenalties(player.Slot))) foreach (var player in players.Where(player => PlayerPenaltyManager.IsSlotInPenalties(player.Slot)))
{ {
if (!PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Mute) && !PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence)) if (!PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Mute) && !PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence) && player.VoiceFlags.HasFlag(VoiceFlags.Muted))
player.VoiceFlags = VoiceFlags.Normal; player.VoiceFlags &= ~VoiceFlags.Muted;
if (PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence) || if (PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence) ||
PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Mute) || PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Mute) ||
PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Gag)) continue; PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Gag)) continue;
player.VoiceFlags = VoiceFlags.Normal; if (player.VoiceFlags.HasFlag(VoiceFlags.Muted))
player.VoiceFlags &= ~VoiceFlags.Muted;
} }
PlayerPenaltyManager.RemoveExpiredPenalties(); PlayerPenaltyManager.RemoveExpiredPenalties();

View file

@ -34,6 +34,7 @@ public class ServerManager
var address = $"{ipAddress}:{ConVar.Find("hostport")?.GetPrimitiveValue<int>()}"; var address = $"{ipAddress}:{ConVar.Find("hostport")?.GetPrimitiveValue<int>()}";
var hostname = ConVar.Find("hostname")!.StringValue; var hostname = ConVar.Find("hostname")!.StringValue;
var rcon = ConVar.Find("rcon_password")!.StringValue;
CS2_SimpleAdmin.IpAddress = address; CS2_SimpleAdmin.IpAddress = address;
Task.Run(async () => Task.Run(async () =>
@ -48,14 +49,14 @@ public class ServerManager
if (!addressExists) if (!addressExists)
{ {
await connection.ExecuteAsync( await connection.ExecuteAsync(
"INSERT INTO sa_servers (address, hostname) VALUES (@address, @hostname)", "INSERT INTO sa_servers (address, hostname, rcon) VALUES (@address, @hostname, @rcon)",
new { address, hostname }); new { address, hostname, rcon });
} }
else else
{ {
await connection.ExecuteAsync( await connection.ExecuteAsync(
"UPDATE `sa_servers` SET `hostname` = @hostname, `id` = `id` WHERE `address` = @address", "UPDATE `sa_servers` SET `hostname` = @hostname, rcon = @rcon, `id` = `id` WHERE `address` = @address",
new { address, hostname }); new { address, rcon, hostname });
} }
int? serverId = await connection.ExecuteScalarAsync<int>( int? serverId = await connection.ExecuteScalarAsync<int>(

View file

@ -69,4 +69,8 @@ public partial class CS2_SimpleAdmin
internal BanManager BanManager = new(Database); internal BanManager BanManager = new(Database);
internal MuteManager MuteManager = new(Database); internal MuteManager MuteManager = new(Database);
internal WarnManager WarnManager = new(Database); internal WarnManager WarnManager = new(Database);
internal ChatManager ChatManager = new();
static string firstMessage = "";
static string secondMessage = "";
} }

View file

@ -1,16 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CS2-SimpleAdmin_ExampleModule", "CS2-SimpleAdmin_ExampleModule.csproj", "{D940F3E9-0E3F-467A-B336-149E3A624FB6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D940F3E9-0E3F-467A-B336-149E3A624FB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D940F3E9-0E3F-467A-B336-149E3A624FB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D940F3E9-0E3F-467A-B336-149E3A624FB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D940F3E9-0E3F-467A-B336-149E3A624FB6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal