From 34342c51349ebfe2c8d9bc1f3f8fa819ad7fdca0 Mon Sep 17 00:00:00 2001 From: daffyyyy Date: Tue, 12 Dec 2023 12:20:27 +0100 Subject: [PATCH] 1.2.0a UPDATE Required CSS 124 --- BanManager.cs | 20 + CS2-SimpleAdmin.cs | 960 +++++++++++++++++++++++++++++++---------- CS2-SimpleAdmin.csproj | 6 +- Config.cs | 59 +-- Events.cs | 91 +++- Helper.cs | 2 + MuteManager.cs | 14 + PlayerUtils.cs | 8 + README.md | 11 +- TargetResult.cs | 8 - lang/en.json | 29 ++ lang/pl.json | 29 ++ 12 files changed, 919 insertions(+), 318 deletions(-) delete mode 100644 TargetResult.cs create mode 100644 lang/en.json create mode 100644 lang/pl.json diff --git a/BanManager.cs b/BanManager.cs index f41d5bf..2f37d71 100644 --- a/BanManager.cs +++ b/BanManager.cs @@ -109,6 +109,26 @@ namespace CS2_SimpleAdmin return banCount > 0; } + public async Task GetPlayerBans(PlayerInfo player) + { + string sql = "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP)"; + int banCount; + + await using var connection = _dbConnection; + await connection.OpenAsync(); + + if (!string.IsNullOrEmpty(player.IpAddress)) + { + banCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = player.SteamId, PlayerIP = player.IpAddress }); + } + else + { + banCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = player.SteamId, PlayerIP = DBNull.Value }); + } + + return banCount; + } + public async Task UnbanPlayer(string playerPattern) { if (playerPattern == null || playerPattern.Length <= 1) diff --git a/CS2-SimpleAdmin.cs b/CS2-SimpleAdmin.cs index 53b47b5..cf8dd24 100644 --- a/CS2-SimpleAdmin.cs +++ b/CS2-SimpleAdmin.cs @@ -4,25 +4,30 @@ using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Core.Attributes.Registration; using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Commands; +using CounterStrikeSharp.API.Modules.Commands.Targeting; using CounterStrikeSharp.API.Modules.Cvars; using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Utils; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using MySqlConnector; using System.Collections.Concurrent; +using System.Text; namespace CS2_SimpleAdmin; -[MinimumApiVersion(101)] +[MinimumApiVersion(124)] public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig { + public static IStringLocalizer? _localizer; public static ConcurrentBag gaggedPlayers = new ConcurrentBag(); + public static ConcurrentBag mutedPlayers = new ConcurrentBag(); public static bool TagsDetected = false; internal string dbConnectionString = string.Empty; public override string ModuleName => "CS2-SimpleAdmin"; public override string ModuleDescription => ""; public override string ModuleAuthor => "daffyy"; - public override string ModuleVersion => "1.0.5a"; + public override string ModuleVersion => "1.2.0a"; public CS2_SimpleAdminConfig Config { get; set; } = new(); @@ -105,6 +110,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] + [RequiresPermissions("@css/generic")] + public void OnWhoCommand(CCSPlayerController? caller, CommandInfo command) + { + TargetResult? targets = GetTarget(command); + if (targets == null) return; + List playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid && !player.IsBot && !player.IsHLTV).ToList(); + + BanManager _banManager = new(dbConnectionString); + MuteManager _muteManager = new(dbConnectionString); + + playersToTarget.ForEach(player => + { + PlayerInfo playerInfo = new PlayerInfo + { + UserId = player.UserId, + Index = (int)player.Index, + SteamId = player?.AuthorizedSteamID?.SteamId64.ToString(), + Name = player?.PlayerName, + IpAddress = player?.IpAddress?.Split(":")[0] + }; + + Task.Run(async () => + { + int totalBans = 0; + int totalMutes = 0; + + totalBans = await _banManager.GetPlayerBans(playerInfo); + totalMutes = await _muteManager.GetPlayerMutes(playerInfo.SteamId!); + + + Server.NextFrame(() => + { + caller!.PrintToConsole($"--------- INFO ABOUT \"{playerInfo.Name}\" ---------"); + + caller!.PrintToConsole($"• Clan: \"{player!.Clan}\" Name: \"{playerInfo.Name}\""); + caller!.PrintToConsole($"• UserID: \"{playerInfo.UserId}\""); + if (playerInfo.SteamId != null) + caller!.PrintToConsole($"• SteamID64: \"{playerInfo.SteamId}\""); + if (player.AuthorizedSteamID != null) + { + caller!.PrintToConsole($"• SteamID2: \"{player.AuthorizedSteamID.SteamId2}\""); + caller!.PrintToConsole($"• Community link: \"{player.AuthorizedSteamID.ToCommunityUrl()}\""); + } + if (playerInfo.IpAddress != null) + caller!.PrintToConsole($"• IP Address: \"{playerInfo.IpAddress}\""); + caller!.PrintToConsole($"• Ping: \"{player.Ping}\""); + if (player.AuthorizedSteamID != null) + { + caller!.PrintToConsole($"• Total Bans: \"{totalBans}\""); + caller!.PrintToConsole($"• Total Mutes: \"{totalMutes}\""); + } + + caller!.PrintToConsole($"--------- END INFO ABOUT \"{player.PlayerName}\" ---------"); + }); + }); + + }); + } + + [ConsoleCommand("css_players")] + [CommandHelper(whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] + [RequiresPermissions("@css/generic")] + public void OnPlayersCommand(CCSPlayerController? caller, CommandInfo command) + { + TargetResult? targets = GetTarget(command); + if (targets == null) return; + List playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid && !player.IsBot && !player.IsHLTV).ToList(); + + playersToTarget.ForEach(player => + { + caller!.PrintToConsole($"--------- PLAYER LIST ---------"); + + caller!.PrintToConsole($"• [#{player.UserId}] \"{player.PlayerName}\" (IP Address: \"{player.IpAddress?.Split(":")[0]}\" SteamID64: \"{player.AuthorizedSteamID?.SteamId64}\")"); + + caller!.PrintToConsole($"--------- END PLAYER LIST ---------"); + + }); + } + [ConsoleCommand("css_kick")] [RequiresPermissions("@css/kick")] [CommandHelper(minArgs: 1, usage: "<#userid or name> [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnKickCommand(CCSPlayerController? caller, CommandInfo command) { - if (!GetTarget(command, out var player) || player == null || !player.IsValid) - return; - - if (!caller!.CanTarget(player)) - { - command.ReplyToCommand($"{player.PlayerName} is more powerful than you!"); - return; - } - - player!.Pawn.Value!.Freeze(); string reason = "Unknown"; - if (command.ArgCount >= 2) + TargetResult? targets = GetTarget(command); + if (targets == null) return; + List playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid).ToList(); + + if (playersToTarget.Count > 1 && Config.DisableDangerousCommands) + { + return; + } + + if (command.ArgCount >= 2 && command.GetArg(2).Length > 0) reason = command.GetArg(2); - if (command.ArgCount >= 2) + targets.Players.ForEach(player => { - player!.PrintToCenter($"{Config.Messages.PlayerKickMessage}".Replace("{REASON}", reason).Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName)); - AddTimer(Config.KickTime, () => Helper.KickPlayer((ushort)player.UserId!, reason)); - } - else - { - AddTimer(Config.KickTime, () => Helper.KickPlayer((ushort)player.UserId!)); - } + player.Pawn.Value!.Freeze(); - Server.PrintToChatAll(Helper.ReplaceTags($" {Config.Prefix} {Config.Messages.AdminKickMessage}".Replace("{REASON}", reason).Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName).Replace("{PLAYER}", player.PlayerName))); + if (command.ArgCount >= 2) + { + player.PrintToCenter(_localizer!["sa_player_kick_message", reason, caller == null ? "Console" : caller.PlayerName]); + AddTimer(Config.KickTime, () => Helper.KickPlayer((ushort)player.UserId!, reason)); + } + else + { + AddTimer(Config.KickTime, () => Helper.KickPlayer((ushort)player.UserId!)); + } + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_kick_message", caller == null ? "Console" : caller.PlayerName, player.PlayerName, reason]); + Server.PrintToChatAll(sb.ToString()); + }); } [ConsoleCommand("css_gag")] @@ -159,73 +251,81 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnGagCommand(CCSPlayerController? caller, CommandInfo command) { - if (!GetTarget(command, out var player) || player == null || !player.IsValid) - return; - - if (!caller!.CanTarget(player) || command.ArgCount < 2) - { - command.ReplyToCommand($"{player.PlayerName} is more powerful than you!"); - return; - } - int time = 0; string reason = "Unknown"; + TargetResult? targets = GetTarget(command); + if (targets == null) return; + List playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid).ToList(); + + if (playersToTarget.Count > 1 && Config.DisableDangerousCommands) + { + return; + } + int.TryParse(command.GetArg(2), out time); - if (command.ArgCount >= 3) + if (command.ArgCount >= 3 && command.GetArg(3).Length > 0) reason = command.GetArg(3); - PlayerInfo playerInfo = new PlayerInfo + MuteManager _muteManager = new(dbConnectionString); + + playersToTarget.ForEach(player => { - SteamId = player?.AuthorizedSteamID?.SteamId64.ToString(), - Name = player?.PlayerName, - IpAddress = player?.IpAddress?.Split(":")[0] - }; - - PlayerInfo adminInfo = new PlayerInfo - { - SteamId = caller?.AuthorizedSteamID?.SteamId64.ToString(), - Name = caller?.PlayerName, - IpAddress = caller?.IpAddress?.Split(":")[0] - }; - - Task.Run(async () => - { - MuteManager _muteManager = new(dbConnectionString); - await _muteManager.MutePlayer(playerInfo, adminInfo, reason, time); - }); - - if (TagsDetected) - NativeAPI.IssueServerCommand($"css_tag_mute {player!.Index.ToString()}"); - - if (!gaggedPlayers.Contains((int)player!.Index)) - gaggedPlayers.Add((int)player.Index); - - if (time > 0 && time <= 30) - { - AddTimer(time * 60, () => + PlayerInfo playerInfo = new PlayerInfo { - if (player == null || !player.IsValid || player.AuthorizedSteamID == null) return; + SteamId = player?.AuthorizedSteamID?.SteamId64.ToString(), + Name = player?.PlayerName, + IpAddress = player?.IpAddress?.Split(":")[0] + }; - if (TagsDetected) - NativeAPI.IssueServerCommand($"css_tag_unmute {player.Index}"); + PlayerInfo adminInfo = new PlayerInfo + { + SteamId = caller?.AuthorizedSteamID?.SteamId64.ToString(), + Name = caller?.PlayerName, + IpAddress = caller?.IpAddress?.Split(":")[0] + }; - MuteManager _muteManager = new(dbConnectionString); - _ = _muteManager.UnmutePlayer(player.AuthorizedSteamID.SteamId64.ToString(), 0); - }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); - } + Task.Run(async () => + { + await _muteManager.MutePlayer(playerInfo, adminInfo, reason, time); + }); - if (time == 0) - { - player!.PrintToCenter($"{Config.Messages.PlayerGagMessagePerm}".Replace("{REASON}", reason).Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName)); - Server.PrintToChatAll(Helper.ReplaceTags($" {Config.Prefix} {Config.Messages.AdminGagMessagePerm}".Replace("{REASON}", reason).Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName).Replace("{PLAYER}", player.PlayerName))); - } - else - { - player!.PrintToCenter($"{Config.Messages.PlayerGagMessageTime}".Replace("{REASON}", reason).Replace("{TIME}", time.ToString()).Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName)); - Server.PrintToChatAll(Helper.ReplaceTags($" {Config.Prefix} {Config.Messages.AdminGagMessageTime}".Replace("{REASON}", reason).Replace("{TIME}", time.ToString()).Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName).Replace("{PLAYER}", player.PlayerName))); - } + if (TagsDetected) + NativeAPI.IssueServerCommand($"css_tag_mute {player!.Index.ToString()}"); + + if (!gaggedPlayers.Contains((int)player!.Index)) + gaggedPlayers.Add((int)player.Index); + + if (time > 0 && time <= 30) + { + AddTimer(time * 60, () => + { + if (player == null || !player.IsValid || player.AuthorizedSteamID == null) return; + + if (TagsDetected) + NativeAPI.IssueServerCommand($"css_tag_unmute {player.Index}"); + + MuteManager _muteManager = new(dbConnectionString); + _ = _muteManager.UnmutePlayer(player.AuthorizedSteamID.SteamId64.ToString(), 0); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + } + + if (time == 0) + { + player!.PrintToCenter(_localizer!["sa_player_gag_message_perm", reason, caller == null ? "Console" : caller.PlayerName]); + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_gag_message_perm", caller == null ? "Console" : caller.PlayerName, player.PlayerName, reason]); + Server.PrintToChatAll(sb.ToString()); + } + else + { + player!.PrintToCenter(_localizer!["sa_player_gag_message_time", reason, time, caller == null ? "Console" : caller.PlayerName]); + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_gag_message_time", caller == null ? "Console" : caller.PlayerName, player.PlayerName, reason, time]); + Server.PrintToChatAll(sb.ToString()); + } + }); } [ConsoleCommand("css_addgag")] @@ -252,7 +352,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig= 3) + if (command.ArgCount >= 3 && command.GetArg(3).Length > 0) reason = command.GetArg(3); PlayerInfo adminInfo = new PlayerInfo @@ -266,7 +366,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig ", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] - public void OnUnmuteCommand(CCSPlayerController? caller, CommandInfo command) + [CommandHelper(minArgs: 1, usage: "", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] + public void OnUngagCommand(CCSPlayerController? caller, CommandInfo command) { if (command.GetArg(1).Length <= 1) { @@ -320,8 +424,9 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig= 3) + if (found) { - string? action = command.GetArg(2)?.ToLower(); - - if (action == "gag") - { - _ = _muteManager.UnmutePlayer(pattern, 0); // Unmute by type 0 (gag) - } - else if (action == "mute") - { - _ = _muteManager.UnmutePlayer(pattern, 1); // Unmute by type 1 (mute) - } - } - else - { - _ = _muteManager.UnmutePlayer(pattern, 2); // Default unmute (all types) + _ = _muteManager.UnmutePlayer(pattern, 0); // Unmute by type 0 (gag) + command.ReplyToCommand($"Ungaged player with pattern {pattern}."); + return; } - command.ReplyToCommand($"Unmuted player with pattern {pattern}."); + TargetResult? targets = GetTarget(command); + if (targets == null) return; + List playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid).ToList(); + + if (playersToTarget.Count > 1 && Config.DisableDangerousCommands) + { + return; + } + + if (playersToTarget.Count > 1) + { + playersToTarget.ForEach(player => + { + if (gaggedPlayers.Contains((int)player.Index)) + { + if (gaggedPlayers.TryTake(out int removedItem) && removedItem != (int)player.Index) + { + gaggedPlayers.Add(removedItem); + } + } + + if (player.AuthorizedSteamID != null) + _ = _muteManager.UnmutePlayer(player.AuthorizedSteamID.SteamId64.ToString(), 0); // Unmute by type 0 (gag) + + if (TagsDetected) + NativeAPI.IssueServerCommand($"css_tag_unmute {player!.Index.ToString()}"); + }); + + command.ReplyToCommand($"Ungaged player with pattern {pattern}."); + return; + } } - [ConsoleCommand("css_ban")] - [RequiresPermissions("@css/ban")] + [ConsoleCommand("css_mute")] + [RequiresPermissions("@css/chat")] [CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] - public void OnBanCommand(CCSPlayerController? caller, CommandInfo command) + public void OnMuteCommand(CCSPlayerController? caller, CommandInfo command) { - if (!GetTarget(command, out var player) || command.ArgCount < 2) - return; - if (player == null || !player.IsValid || player.AuthorizedSteamID == null) return; + int time = 0; + string reason = "Unknown"; - if (!caller!.CanTarget(player)) + TargetResult? targets = GetTarget(command); + if (targets == null) return; + List playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid).ToList(); + + if (playersToTarget.Count > 1 && Config.DisableDangerousCommands) { - command.ReplyToCommand($"{player.PlayerName} is more powerful than you!"); + return; + } + + int.TryParse(command.GetArg(2), out time); + + if (command.ArgCount >= 3 && command.GetArg(3).Length > 0) + reason = command.GetArg(3); + + MuteManager _muteManager = new(dbConnectionString); + + playersToTarget.ForEach(player => + { + PlayerInfo playerInfo = new PlayerInfo + { + SteamId = player?.AuthorizedSteamID?.SteamId64.ToString(), + Name = player?.PlayerName, + IpAddress = player?.IpAddress?.Split(":")[0] + }; + + PlayerInfo adminInfo = new PlayerInfo + { + SteamId = caller?.AuthorizedSteamID?.SteamId64.ToString(), + Name = caller?.PlayerName, + IpAddress = caller?.IpAddress?.Split(":")[0] + }; + + if (!mutedPlayers.Contains((int)player!.Index)) + mutedPlayers.Add((int)player!.Index); + + Task.Run(async () => + { + await _muteManager.MutePlayer(playerInfo, adminInfo, reason, time, 1); + }); + + player.VoiceFlags = VoiceFlags.Muted; + + if (time > 0 && time <= 30) + { + AddTimer(time * 60, () => + { + if (player == null || !player.IsValid || player.AuthorizedSteamID == null) return; + + //MuteManager _muteManager = new(dbConnectionString); + //_ = _muteManager.UnmutePlayer(player.AuthorizedSteamID.SteamId64.ToString(), 1); + + if (mutedPlayers.Contains((int)player.Index)) + { + if (mutedPlayers.TryTake(out int removedItem) && removedItem != (int)player.Index) + { + mutedPlayers.Add(removedItem); + } + } + + player.VoiceFlags = VoiceFlags.Normal; + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + } + + if (time == 0) + { + player!.PrintToCenter(_localizer!["sa_player_mute_message_perm", reason, caller == null ? "Console" : caller.PlayerName]); + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_mute_message_perm", caller == null ? "Console" : caller.PlayerName, player.PlayerName, reason]); + Server.PrintToChatAll(sb.ToString()); + } + else + { + player!.PrintToCenter(_localizer!["sa_player_mute_message_time", reason, time, caller == null ? "Console" : caller.PlayerName]); + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_mute_message_time", caller == null ? "Console" : caller.PlayerName, player.PlayerName, reason, time]); + Server.PrintToChatAll(sb.ToString()); + } + }); + + } + + [ConsoleCommand("css_addmute")] + [RequiresPermissions("@css/chat")] + [CommandHelper(minArgs: 1, usage: " [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] + public void OnAddMuteCommand(CCSPlayerController? caller, CommandInfo command) + { + if (command.ArgCount < 2) + return; + if (string.IsNullOrEmpty(command.GetArg(1))) return; + + string steamid = command.GetArg(1); + + if (!Helper.IsValidSteamID64(steamid)) + { + command.ReplyToCommand($"Invalid SteamID64."); return; } int time = 0; string reason = "Unknown"; - player!.Pawn.Value!.Freeze(); + MuteManager _muteManager = new(dbConnectionString); int.TryParse(command.GetArg(2), out time); - if (command.ArgCount >= 3) + if (command.ArgCount >= 3 && command.GetArg(3).Length > 0) reason = command.GetArg(3); - PlayerInfo playerInfo = new PlayerInfo - { - SteamId = player?.AuthorizedSteamID?.SteamId64.ToString(), - Name = player?.PlayerName, - IpAddress = player?.IpAddress?.Split(":")[0] - }; - PlayerInfo adminInfo = new PlayerInfo { SteamId = caller?.AuthorizedSteamID?.SteamId64.ToString(), @@ -430,24 +640,225 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig + List matches = Helper.GetPlayerFromSteamid64(steamid); + if (matches.Count == 1) { - BanManager _banManager = new(dbConnectionString); - await _banManager.BanPlayer(playerInfo, adminInfo, reason, time); - }); + CCSPlayerController? player = matches.FirstOrDefault(); + if (player != null && player.IsValid) + { + if (!caller!.CanTarget(player)) + { + command.ReplyToCommand($"{player.PlayerName} is more powerful than you!"); + return; + } - if (time == 0) + if (time == 0) + { + player!.PrintToCenter(_localizer!["sa_player_mute_message_perm", reason, caller == null ? "Console" : caller.PlayerName]); + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_mute_message_perm", caller == null ? "Console" : caller.PlayerName, player.PlayerName, reason]); + Server.PrintToChatAll(sb.ToString()); + } + else + { + player!.PrintToCenter(_localizer!["sa_player_mute_message_time", reason, time, caller == null ? "Console" : caller.PlayerName]); + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_mute_message_time", caller == null ? "Console" : caller.PlayerName, player.PlayerName, reason, time]); + Server.PrintToChatAll(sb.ToString()); + } + + if (!mutedPlayers.Contains((int)player!.Index)) + mutedPlayers.Add((int)player!.Index); + + if (time > 0 && time <= 30) + { + AddTimer(time * 60, () => + { + if (player == null || !player.IsValid || player.AuthorizedSteamID == null) return; + + if (mutedPlayers.Contains((int)player.Index)) + { + if (mutedPlayers.TryTake(out int removedItem) && removedItem != (int)player.Index) + { + mutedPlayers.Add(removedItem); + } + } + + player.VoiceFlags = VoiceFlags.Normal; + + _ = _muteManager.UnmutePlayer(player.AuthorizedSteamID.SteamId64.ToString(), 1); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + } + } + } + _ = _muteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 1); + command.ReplyToCommand($"Muted player with steamid {steamid}."); + } + + [ConsoleCommand("css_unmute")] + [RequiresPermissions("@css/chat")] + [CommandHelper(minArgs: 1, usage: "", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] + public void OnUnmuteCommand(CCSPlayerController? caller, CommandInfo command) + { + if (command.GetArg(1).Length <= 1) { - player!.PrintToCenter($"{Config.Messages.PlayerBanMessagePerm}".Replace("{REASON}", reason).Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName)); - Server.PrintToChatAll(Helper.ReplaceTags($" {Config.Prefix} {Config.Messages.AdminBanMessagePerm}".Replace("{REASON}", reason).Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName).Replace("{PLAYER}", player.PlayerName))); + command.ReplyToCommand($"Too short pattern to search."); + return; + } + + string pattern = command.GetArg(1); + bool found = false; + MuteManager _muteManager = new(dbConnectionString); + + if (Helper.IsValidSteamID64(pattern)) + { + List matches = Helper.GetPlayerFromSteamid64(pattern); + if (matches.Count == 1) + { + CCSPlayerController? player = matches.FirstOrDefault(); + if (player != null && player.IsValid) + { + if (mutedPlayers.Contains((int)player.Index)) + { + if (mutedPlayers.TryTake(out int removedItem) && removedItem != (int)player.Index) + { + mutedPlayers.Add(removedItem); + } + } + + player.VoiceFlags = VoiceFlags.Normal; + found = true; + } + } } else { - player!.PrintToCenter($"{Config.Messages.PlayerBanMessageTime}".Replace("{REASON}", reason).Replace("{TIME}", time.ToString()).Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName)); - Server.PrintToChatAll(Helper.ReplaceTags($" {Config.Prefix} {Config.Messages.AdminBanMessageTime}".Replace("{REASON}", reason).Replace("{TIME}", time.ToString()).Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName).Replace("{PLAYER}", player.PlayerName))); + List matches = Helper.GetPlayerFromName(pattern); + if (matches.Count == 1) + { + CCSPlayerController? player = matches.FirstOrDefault(); + if (player != null && player.IsValid) + { + if (mutedPlayers.Contains((int)player.Index)) + { + if (mutedPlayers.TryTake(out int removedItem) && removedItem != (int)player.Index) + { + mutedPlayers.Add(removedItem); + } + } + + player.VoiceFlags = VoiceFlags.Normal; + pattern = player.AuthorizedSteamID!.SteamId64.ToString(); + found = true; + } + } } - AddTimer(Config.KickTime, () => Helper.KickPlayer((ushort)player.UserId!)); + if (found) + { + _ = _muteManager.UnmutePlayer(pattern, 1); // Unmute by type 1 (mute) + command.ReplyToCommand($"Unmuted player with pattern {pattern}."); + return; + } + + TargetResult? targets = GetTarget(command); + List playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid).ToList(); + + if (playersToTarget.Count > 1 && Config.DisableDangerousCommands) + { + return; + } + + if (playersToTarget.Count > 1) + { + playersToTarget.ForEach(player => + { + if (mutedPlayers.Contains((int)player.Index)) + { + if (mutedPlayers.TryTake(out int removedItem) && removedItem != (int)player.Index) + { + mutedPlayers.Add(removedItem); + } + } + + if (player.AuthorizedSteamID != null) + _ = _muteManager.UnmutePlayer(player.AuthorizedSteamID.SteamId64.ToString(), 1); // Unmute by type 1 (mute) + + player.VoiceFlags = VoiceFlags.Normal; + }); + + command.ReplyToCommand($"Unmuted player with pattern {pattern}."); + return; + } + } + + [ConsoleCommand("css_ban")] + [RequiresPermissions("@css/ban")] + [CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] + public void OnBanCommand(CCSPlayerController? caller, CommandInfo command) + { + if (command.ArgCount < 2) + return; + + int time = 0; + string reason = "Unknown"; + + TargetResult? targets = GetTarget(command); + if (targets == null) return; + List playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid).ToList(); + + if (playersToTarget.Count > 1 && Config.DisableDangerousCommands) + { + return; + } + + BanManager _banManager = new(dbConnectionString); + + int.TryParse(command.GetArg(2), out time); + + if (command.ArgCount >= 3 && command.GetArg(3).Length > 0) + reason = command.GetArg(3); + + playersToTarget.ForEach(player => + { + player.Pawn.Value!.Freeze(); + + PlayerInfo playerInfo = new PlayerInfo + { + SteamId = player?.AuthorizedSteamID?.SteamId64.ToString(), + Name = player?.PlayerName, + IpAddress = player?.IpAddress?.Split(":")[0] + }; + + PlayerInfo adminInfo = new PlayerInfo + { + SteamId = caller?.AuthorizedSteamID?.SteamId64.ToString(), + Name = caller?.PlayerName, + IpAddress = caller?.IpAddress?.Split(":")[0] + }; + + Task.Run(async () => + { + await _banManager.BanPlayer(playerInfo, adminInfo, reason, time); + }); + + if (time == 0) + { + player!.PrintToCenter(_localizer!["sa_player_ban_message_perm", reason, caller == null ? "Console" : caller.PlayerName]); + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_ban_message_perm", caller == null ? "Console" : caller.PlayerName, player.PlayerName, reason]); + Server.PrintToChatAll(sb.ToString()); + } + else + { + player!.PrintToCenter(_localizer!["sa_player_ban_message_time", reason, time, caller == null ? "Console" : caller.PlayerName]); + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_ban_message_time", caller == null ? "Console" : caller.PlayerName, player.PlayerName, reason, time]); + Server.PrintToChatAll(sb.ToString()); + } + + AddTimer(Config.KickTime, () => Helper.KickPlayer((ushort)player.UserId!)); + }); } [ConsoleCommand("css_addban")] @@ -474,7 +885,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig= 3) + if (command.ArgCount >= 3 && command.GetArg(3).Length > 0) reason = command.GetArg(3); PlayerInfo adminInfo = new PlayerInfo @@ -489,7 +900,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig @@ -551,14 +966,14 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig= 3) + if (command.ArgCount >= 3 && command.GetArg(3).Length > 0) reason = command.GetArg(3); List matches = Helper.GetPlayerFromIp(ipAddress); if (matches.Count == 1) { CCSPlayerController? player = matches.FirstOrDefault(); - if (player != null) + if (player != null && player.IsValid) { if (!caller!.CanTarget(player)) { @@ -570,13 +985,17 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig @@ -616,21 +1035,62 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnSlayCommand(CCSPlayerController? caller, CommandInfo command) { - if (!GetTarget(command, out CCSPlayerController? player) || player == null || !player.IsValid) - return; + TargetResult? targets = GetTarget(command); + if (targets == null) return; + List playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid && player.PawnIsAlive).ToList(); - if (!caller!.CanTarget(player)) + playersToTarget.ForEach(player => { - command.ReplyToCommand($"{player.PlayerName} is more powerful than you!"); + player.CommitSuicide(false, true); + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_slay_message", caller == null ? "Console" : caller.PlayerName, player.PlayerName]); + Server.PrintToChatAll(sb.ToString()); + }); + } + + [ConsoleCommand("css_give")] + [RequiresPermissions("@css/cheats")] + [CommandHelper(minArgs: 2, usage: "<#userid or name> ", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] + public void OnGiveCommand(CCSPlayerController? caller, CommandInfo command) + { + TargetResult? targets = GetTarget(command); + if (targets == null) return; + List playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid && player.PawnIsAlive).ToList(); + + string weaponName = command.GetArg(2); + + // check if item is typed + if (weaponName == null || weaponName.Length < 5) + { + command.ReplyToCommand($"No weapon typed."); return; } - if (!player!.PawnIsAlive) + // check if item is valid + if (!weaponName.Contains("weapon_") || !weaponName.Contains("item_")) + { + command.ReplyToCommand($"{weaponName} is not a valid item."); return; + } - player!.CommitSuicide(false, true); + // check if weapon is knife + if (weaponName.Contains("_knife") || weaponName.Contains("bayonet")) + { + if (CoreConfig.FollowCS2ServerGuidelines) + { + command.ReplyToCommand($"Cannot Give {weaponName} because it's illegal to be given."); + return; + } + } - Server.PrintToChatAll(Helper.ReplaceTags($" {Config.Prefix} {Config.Messages.AdminSlayMessage}".Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName).Replace("{PLAYER}", player.PlayerName))); + playersToTarget.ForEach(player => + { + //give the weapon to player and announce it + player.GiveNamedItem(weaponName); + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_give_message", caller == null ? "Console" : caller.PlayerName, player.PlayerName, weaponName]); + Server.PrintToChatAll(sb.ToString()); + }); } [ConsoleCommand("css_slap")] @@ -638,28 +1098,24 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig [damage]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnSlapCommand(CCSPlayerController? caller, CommandInfo command) { - if (!GetTarget(command, out CCSPlayerController? player) || player == null || !player.IsValid) - return; - - if (!caller!.CanTarget(player)) - { - command.ReplyToCommand($"{player.PlayerName} is more powerful than you!"); - return; - } - - if (!player!.PawnIsAlive) - return; - int damage = 0; + TargetResult? targets = GetTarget(command); + if (targets == null) return; + List playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid && player.PawnIsAlive).ToList(); + if (command.ArgCount >= 2) { int.TryParse(command.GetArg(2), out damage); } - player!.Pawn.Value!.Slap(damage); - - Server.PrintToChatAll(Helper.ReplaceTags($" {Config.Prefix} {Config.Messages.AdminSlapMessage}".Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName).Replace("{PLAYER}", player.PlayerName))); + playersToTarget.ForEach(player => + { + player!.Pawn.Value!.Slap(damage); + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_slap_message", caller == null ? "Console" : caller.PlayerName, player.PlayerName]); + Server.PrintToChatAll(sb.ToString()); + }); } [ConsoleCommand("css_team")] @@ -667,18 +1123,13 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig []", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnTeamCommand(CCSPlayerController? caller, CommandInfo command) { - if (!GetTarget(command, out CCSPlayerController? player) || player == null || !player.IsValid) - return; - - if (!caller!.CanTarget(player)) - { - command.ReplyToCommand($"{player.PlayerName} is more powerful than you!"); - return; - } - string teamName = command.GetArg(2).ToLower(); CsTeam teamNum = CsTeam.Spectator; + TargetResult? targets = GetTarget(command); + if (targets == null) return; + List playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid).ToList(); + switch (teamName) { case "ct": @@ -695,18 +1146,16 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig { - command.ReplyToCommand($"{player.PlayerName} is already in selected team!"); - return; - } - - if (player.PawnIsAlive && teamNum != CsTeam.Spectator) - player.SwitchTeam(teamNum); - else - player.ChangeTeam(teamNum); - - command.ReplyToCommand($"Successfully changed team for {player.PlayerName}"); + if (player.TeamNum != ((byte)teamNum)) + { + if (player.PawnIsAlive && teamNum != CsTeam.Spectator) + player.SwitchTeam(teamNum); + else + player.ChangeTeam(teamNum); + } + }); } [ConsoleCommand("css_map")] @@ -727,7 +1176,9 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig { @@ -755,9 +1208,14 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig p.IsValid && !p.IsBot && !p.IsHLTV && AdminManager.PlayerHasPermissions(p, "@css/chat"))) { - p.PrintToChat($" {ChatColors.Lime}(ADMIN) {ChatColors.Default}{caller.PlayerName}: {command.GetCommandString[command.GetCommandString.IndexOf(' ')..]}"); + p.PrintToChat(sb.ToString()); } } @@ -766,7 +1224,9 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig playersToTarget = targets!.Players.Where(player => player != null && player.IsValid).ToList(); - var range = command.GetArg(0).Length + command.GetArg(1).Length + 2; - var message = command.GetCommandString[range..]; + int range = command.GetArg(0).Length + command.GetArg(1).Length + 2; + string message = command.GetCommandString[range..]; - command.ReplyToCommand(Helper.ReplaceTags($"({player!.PlayerName}) {message}")); - player.PrintToChat(Helper.ReplaceTags($"({caller!.PlayerName}) {message}")); + playersToTarget.ForEach(player => + { + player.PrintToChat(Helper.ReplaceTags($"({caller!.PlayerName}) {message}")); + }); + + command.ReplyToCommand(Helper.ReplaceTags($" Private message sent!")); } [ConsoleCommand("css_csay", "Say to all players (in center).")] @@ -808,18 +1273,16 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid && player.PawnIsAlive).ToList(); - if (!caller!.CanTarget(player)) + playersToTarget.ForEach(player => { - command.ReplyToCommand($"{player.PlayerName} is more powerful than you!"); - return; - } - - player!.Pawn.Value!.ToggleNoclip(); - - Server.PrintToChatAll(Helper.ReplaceTags($" {Config.Prefix} {Config.Messages.AdminNoclipMessage}".Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName).Replace("{PLAYER}", player.PlayerName))); + player!.Pawn.Value!.ToggleNoclip(); + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_noclip_message", caller == null ? "Console" : caller.PlayerName, player.PlayerName]); + Server.PrintToChatAll(sb.ToString()); + }); } [ConsoleCommand("css_freeze", "Freeze a player.")] @@ -827,24 +1290,23 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid && player.PawnIsAlive).ToList(); - if (time > 0) - AddTimer(time, () => player.Pawn.Value!.Unfreeze()); + playersToTarget.ForEach(player => + { + player!.Pawn.Value!.Freeze(); - Server.PrintToChatAll(Helper.ReplaceTags($" {Config.Prefix} {Config.Messages.AdminFreezeMessage}".Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName).Replace("{PLAYER}", player.PlayerName))); + if (time > 0) + AddTimer(time, () => player.Pawn.Value!.Unfreeze()); + + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_freeze_message", caller == null ? "Console" : caller.PlayerName, player.PlayerName]); + Server.PrintToChatAll(sb.ToString()); + }); } [ConsoleCommand("css_unfreeze", "Unfreeze a player.")] @@ -852,12 +1314,16 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid && player.PawnIsAlive).ToList(); - player!.Pawn.Value!.Unfreeze(); - - Server.PrintToChatAll(Helper.ReplaceTags($" {Config.Prefix} {Config.Messages.AdminUnFreezeMessage}".Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName).Replace("{PLAYER}", player.PlayerName))); + playersToTarget.ForEach(player => + { + player!.Pawn.Value!.Unfreeze(); + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_unfreeze_message", caller == null ? "Console" : caller.PlayerName, player.PlayerName]); + Server.PrintToChatAll(sb.ToString()); + }); } [ConsoleCommand("css_respawn", "Respawn a dead player.")] @@ -865,18 +1331,16 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig playersToTarget = targets!.Players.Where(player => caller!.CanTarget(player) && player != null && player.IsValid).ToList(); - if (!caller!.CanTarget(player)) + playersToTarget.ForEach(player => { - command.ReplyToCommand($"{player.PlayerName} is more powerful than you!"); - return; - } - - player!.Respawn(); - - Server.PrintToChatAll(Helper.ReplaceTags($" {Config.Prefix} {Config.Messages.AdminRespawnMessage}".Replace("{ADMIN}", caller?.PlayerName == null ? "Console" : caller.PlayerName).Replace("{PLAYER}", player.PlayerName))); + player!.Respawn(); + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_respawn_message", caller == null ? "Console" : caller.PlayerName, player.PlayerName]); + Server.PrintToChatAll(sb.ToString()); + }); } [ConsoleCommand("css_cvar", "Change a cvar.")] @@ -912,14 +1376,33 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig 1 || command.GetArg(1).StartsWith('@')) + return matches; + + if (matches.Count() == 1 || !command.GetArg(1).StartsWith('@')) + return matches; + + command.ReplyToCommand($"Multiple targets found for \"{command.GetArg(1)}\"."); + return null; + + /* var matches = Helper.GetTarget(command.GetArg(1), out player); switch (matches) @@ -933,6 +1416,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig - + + + + + diff --git a/Config.cs b/Config.cs index d9210b3..f92fcd2 100644 --- a/Config.cs +++ b/Config.cs @@ -3,58 +3,9 @@ using System.Text.Json.Serialization; namespace CS2_SimpleAdmin { - public class Messages - { - [JsonPropertyName("PlayerBanMessageTime")] - public string PlayerBanMessageTime { get; set; } = "You have been banned for {REASON} for {TIME} minutes by {ADMIN}!"; - [JsonPropertyName("PlayerBanMessagePerm")] - public string PlayerBanMessagePerm { get; set; } = "You have been banned permanently for {REASON} by {ADMIN}!"; - [JsonPropertyName("PlayerKickMessage")] - public string PlayerKickMessage { get; set; } = "You have been kicked for {REASON} by {ADMIN}!"; - [JsonPropertyName("PlayerGagMessageTime")] - public string PlayerGagMessageTime { get; set; } = "You have been gagged for {REASON} for {TIME} minutes by {ADMIN}!"; - [JsonPropertyName("PlayerGagMessagePerm")] - public string PlayerGagMessagePerm { get; set; } = "You have been gagged permanently for {REASON} by {ADMIN}!"; - [JsonPropertyName("AdminBanMessageTime")] - public string AdminBanMessageTime { get; set; } = "Admin {ADMIN} banned {PLAYER} for {REASON} for {TIME} minutes!"; - [JsonPropertyName("AdminBanMessagePerm")] - public string AdminBanMessagePerm { get; set; } = "Admin {ADMIN} banned {PLAYER} permanently for {REASON}"; - [JsonPropertyName("AdminKickMessage")] - public string AdminKickMessage { get; set; } = "Admin {ADMIN} kicked {PLAYER} for {REASON}!"; - [JsonPropertyName("AdminGagMessageTime")] - public string AdminGagMessageTime { get; set; } = "Admin {ADMIN} gagged {PLAYER} for {REASON} for {TIME} minutes!"; - [JsonPropertyName("AdminGagMessagePerm")] - public string AdminGagMessagePerm { get; set; } = "Admin {ADMIN} gagged {PLAYER} permanently for {REASON}"; - [JsonPropertyName("AdminSlayMessage")] - public string AdminSlayMessage { get; set; } = "Admin {ADMIN} slayed {PLAYER}!"; - [JsonPropertyName("AdminSlapMessage")] - public string AdminSlapMessage { get; set; } = "Admin {ADMIN} slapped {PLAYER}!"; - [JsonPropertyName("AdminChangeMap")] - public string AdminChangeMap { get; set; } = "Admin {ADMIN} changed map to {MAP}!"; - [JsonPropertyName("AdminNoclipMessage")] - public string AdminNoclipMessage { get; set; } = "Admin {ADMIN} toggled noclip for {PLAYER}!"; - [JsonPropertyName("AdminFreezeMessage")] - public string AdminFreezeMessage { get; set; } = "Admin {ADMIN} freezed {PLAYER}!"; - [JsonPropertyName("AdminUnFreezeMessage")] - public string AdminUnFreezeMessage { get; set; } = "Admin {ADMIN} unfreezed {PLAYER}!"; - [JsonPropertyName("AdminRespawnMessage")] - public string AdminRespawnMessage { get; set; } = "Admin {ADMIN} respawned {PLAYER}!"; - [JsonPropertyName("AdminSayPrefix")] - public string AdminSayPrefix { get; set; } = "{RED}ADMIN: {DEFAULT}"; - [JsonPropertyName("AdminHelpCommand")] - public string AdminHelpCommand { get; set; } = "{GREEN}[ CS2-SimpleAdmin HELP ]{DEFAULT}\n- css_ban <#userid or name> [time in minutes/0 perm] [reason] - Ban player\n- css_addban [time in minutes/0 perm] [reason] - Ban player via steamid64\n" + - "- css_banip [time in minutes/0 perm] [reason] - Ban player via IP address\n- css_unban - Unban player\n" + - "- css_kick <#userid or name> [reason] - Kick player\n- css_gag <#userid or name> [time in minutes/0 perm] [reason] - Gag player\n- css_addgag [time in minutes/0 perm] [reason] - Gag player via steamid64\n" + - "- css_unmute - Kill player\n- css_slap <#userid or name> [damage] - Slap player\n- css_map - Change map\n- css_wsmap - Change workshop map\n- css_say - Say message as admin in chat\n" + - "- css_psay <#userid or name> - Sends private message to player\n- css_csay - Say message as admin in center\n- css_hsay - Say message as admin in hud\n" + - "- css_noclip <#userid or name> - Toggle noclip for player\n- css_freeze <#userid or name> [duration] - Freeze player\n- css_unfreeze <#userid or name> - Unfreeze player\n" + - "- css_respawn <#userid or name> - Respawn player\n- css_cvar - Change cvar value\n- css_rcon - Run command as server"; - } - public class CS2_SimpleAdminConfig : BasePluginConfig { - public override int Version { get; set; } = 1; + public override int Version { get; set; } = 2; [JsonPropertyName("DatabaseHost")] public string DatabaseHost { get; set; } = ""; @@ -71,13 +22,9 @@ namespace CS2_SimpleAdmin [JsonPropertyName("DatabaseName")] public string DatabaseName { get; set; } = ""; - [JsonPropertyName("Prefix")] - public string Prefix { get; set; } = "{GREEN}[SimpleAdmin]"; [JsonPropertyName("KickTime")] public int KickTime { get; set; } = 10; - - [JsonPropertyName("Messages")] - public Messages Messages { get; set; } = new Messages(); + [JsonPropertyName("DisableDangerousCommands")] + public bool DisableDangerousCommands { get; set; } = true; } - } \ No newline at end of file diff --git a/Events.cs b/Events.cs index e12e167..dd7300e 100644 --- a/Events.cs +++ b/Events.cs @@ -3,7 +3,7 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Entities; -using CounterStrikeSharp.API.Modules.Utils; +using System.Text; using static CounterStrikeSharp.API.Core.Listeners; namespace CS2_SimpleAdmin @@ -17,8 +17,8 @@ namespace CS2_SimpleAdmin RegisterListener(OnMapStart); AddCommandListener("say", OnCommandSay); AddCommandListener("say_team", OnCommandTeamSay); + AddCommandListener("callvote", OnCommandCallVote); } - private HookResult OnCommandSay(CCSPlayerController? player, CommandInfo info) { if (player == null || !player.IsValid || info.GetArg(1).Length == 0) return HookResult.Continue; @@ -40,11 +40,26 @@ namespace CS2_SimpleAdmin return HookResult.Handled; } - if (info.GetArg(1).StartsWith("@") && AdminManager.PlayerHasPermissions(player, "@css/chat")) + if (info.GetArg(1).StartsWith("@")) { - foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid && !p.IsBot && !p.IsHLTV && AdminManager.PlayerHasPermissions(p, "@css/chat"))) + StringBuilder sb = new(); + + if (AdminManager.PlayerHasPermissions(player, "@css/chat")) { - p.PrintToChat($" {ChatColors.Lime}(ADMIN) {ChatColors.Default}{player.PlayerName}: {info.GetArg(1).Remove(0, 1)}"); + sb.Append(_localizer!["sa_adminchat_template_admin", player.PlayerName, info.GetArg(1).Remove(0, 1)]); + foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid && !p.IsBot && !p.IsHLTV && AdminManager.PlayerHasPermissions(p, "@css/chat"))) + { + p.PrintToChat(sb.ToString()); + } + } + else + { + sb.Append(_localizer!["sa_adminchat_template_player", player.PlayerName, info.GetArg(1).Remove(0, 1)]); + player.PrintToChat(sb.ToString()); + foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid && !p.IsBot && !p.IsHLTV && AdminManager.PlayerHasPermissions(p, "@css/chat"))) + { + p.PrintToChat(sb.ToString()); + } } return HookResult.Handled; @@ -53,11 +68,26 @@ namespace CS2_SimpleAdmin return HookResult.Continue; } + private HookResult OnCommandCallVote(CCSPlayerController? player, CommandInfo info) + { + string reason = info.GetArg(1); + + if (reason == "kick" || reason == "ban") + { + int.TryParse(info.GetArg(2), out int target); + if (target > 0) + { + if (!player!.CanTarget(Utilities.GetPlayerFromUserid(target))) + return HookResult.Handled; + } + } + + return HookResult.Continue; + } + private void OnClientAuthorized(int playerSlot, SteamID steamID) { - int playerIndex = playerSlot + 1; - - CCSPlayerController? player = Utilities.GetPlayerFromIndex(playerIndex); + CCSPlayerController? player = Utilities.GetPlayerFromSlot(playerSlot); if (player == null || !player.IsValid || player.IsBot || player.IsHLTV) return; @@ -82,7 +112,7 @@ namespace CS2_SimpleAdmin Task.Run(async () => { - if (player == null) return; + if (player == null || !player.IsValid) return; BanManager _banManager = new(dbConnectionString); bool isBanned = await _banManager.IsPlayerBanned(playerInfo); @@ -91,7 +121,7 @@ namespace CS2_SimpleAdmin Server.NextFrame(() => { - if (player == null) return; + if (player == null || !player.IsValid) return; if (isBanned) { Helper.KickPlayer((ushort)player.UserId!, "Banned"); @@ -108,12 +138,36 @@ namespace CS2_SimpleAdmin if (muteType == "GAG") { + // Chat mute if (!gaggedPlayers.Any(index => index == player.Index)) gaggedPlayers.Add((int)player.Index); if (TagsDetected) NativeAPI.IssueServerCommand($"css_tag_mute {player.Index}"); + if (duration.Minutes >= 0 && duration.Minutes <= 30) + { + AddTimer(durationInSeconds, () => + { + if (player == null || !player.IsValid || player.AuthorizedSteamID == null) return; + + if (gaggedPlayers.Contains((int)player.Index)) + { + if (gaggedPlayers.TryTake(out int removedItem) && removedItem != (int)player.Index) + { + gaggedPlayers.Add(removedItem); + } + } + + if (TagsDetected) + NativeAPI.IssueServerCommand($"css_tag_unmute {player.Index}"); + + MuteManager _muteManager = new(dbConnectionString); + _ = _muteManager.UnmutePlayer(player.AuthorizedSteamID.SteamId64.ToString(), 0); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + } + + /* CCSPlayerController currentPlayer = player; @@ -130,13 +184,26 @@ namespace CS2_SimpleAdmin } else { - // Mic mute + // Voice mute + player.VoiceFlags = VoiceFlags.Muted; + + if (duration.Minutes >= 0 && duration.Minutes <= 30) + { + AddTimer(durationInSeconds, () => + { + if (player == null || !player.IsValid || player.AuthorizedSteamID == null) return; + + player.VoiceFlags = VoiceFlags.Normal; + + MuteManager _muteManager = new(dbConnectionString); + _ = _muteManager.UnmutePlayer(player.AuthorizedSteamID.SteamId64.ToString(), 1); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + } } } } }); }); - } private void OnClientDisconnect(int playerSlot) diff --git a/Helper.cs b/Helper.cs index fc5d2ba..08b6bfa 100644 --- a/Helper.cs +++ b/Helper.cs @@ -45,6 +45,7 @@ namespace CS2_SimpleAdmin return Regex.IsMatch(input, pattern); } + /* public static TargetResult GetTarget(string target, out CCSPlayerController? player) { player = null; @@ -64,6 +65,7 @@ namespace CS2_SimpleAdmin return player?.IsValid == true ? TargetResult.Single : TargetResult.None; } + */ public static void KickPlayer(ushort userId, string? reason = null) { diff --git a/MuteManager.cs b/MuteManager.cs index 4600a5d..50f6267 100644 --- a/MuteManager.cs +++ b/MuteManager.cs @@ -1,4 +1,5 @@ using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Entities; using Dapper; using MySqlConnector; using System.Data; @@ -88,6 +89,19 @@ namespace CS2_SimpleAdmin return activeMutes; } + public async Task GetPlayerMutes(string steamId) + { + await using var connection = _dbConnection; + await connection.OpenAsync(); + + int muteCount; + string sql = "SELECT COUNT(*) FROM sa_mutes WHERE player_steamid = @PlayerSteamID"; + + muteCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = steamId }); + + return muteCount; + } + public async Task UnmutePlayer(string playerPattern, int type = 0) { if (playerPattern == null || playerPattern.Length <= 1) diff --git a/PlayerUtils.cs b/PlayerUtils.cs index 0156b0c..0ffaaf8 100644 --- a/PlayerUtils.cs +++ b/PlayerUtils.cs @@ -1,6 +1,7 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Utils; +using System.Text; namespace CS2_SimpleAdmin; @@ -10,9 +11,16 @@ public static class PlayerUtils { PerformSlap(pawn, damage); } + public static void Print(this CCSPlayerController controller, string message = "") + { + StringBuilder _message = new(CS2_SimpleAdmin._localizer!["sa_prefix"]); + _message.Append(message); + controller.PrintToChat(_message.ToString()); + } public static bool CanTarget(this CCSPlayerController controller, CCSPlayerController target) { + if (target.IsBot) return true; return AdminManager.CanPlayerTarget(controller, target); } diff --git a/README.md b/README.md index 083d7d1..20fbc1f 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ Manage your Counter-Strike 2 server by simple commands :) ### Info -It's only plugin base, I don't have much time for more extensive development, so if you want to help, do it :) +~~It's only plugin base~~, I don't have much time for more extensive development, so if you want to help, do it :) +**The plugin will be developed as much as possible**, so it is no longer just a base for other plugins ### Commands ```js @@ -16,7 +17,11 @@ It's only plugin base, I don't have much time for more extensive development, so - css_kick <#userid or name> [reason] - Kick player / @css/kick - css_gag <#userid or name> [time in minutes/0 perm] [reason] - Gag player // @css/chat - css_addgag [time in minutes/0 perm] [reason] - Gag player via steamid64 // @css/chat -- css_unmute - Ungag player // @css/chat +- css_mute <#userid or name> [time in minutes/0 perm] [reason] - Mute player // @css/chat +- css_addmute [time in minutes/0 perm] [reason] - Mute player via steamid64 // @css/chat +- css_unmute - Unmute player // @css/chat +- css_give <#userid or name> - Give weapon to player // @css/cheats - css_slay <#userid or name> - Kill player // @css/slay - css_slap <#userid or name> [damage] - Slap player // @css/slay - css_team <#userid or name> [] - Change player team // @css/kick @@ -34,7 +39,7 @@ It's only plugin base, I don't have much time for more extensive development, so - css_cvar - Change cvar value // @css/cvar - css_rcon - Run command as server // @css/rcon -- @Message - Say message to all admins // @css/chat +- team_chat @Message - Say message to all admins // @css/chat ``` ### Requirments diff --git a/TargetResult.cs b/TargetResult.cs deleted file mode 100644 index 39ed99e..0000000 --- a/TargetResult.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace CS2_SimpleAdmin; - -internal enum TargetResult -{ - None, - Multiple, - Single -} diff --git a/lang/en.json b/lang/en.json new file mode 100644 index 0000000..0c08f72 --- /dev/null +++ b/lang/en.json @@ -0,0 +1,29 @@ +{ + "sa_prefix": "{lightred}[SA] {default}", + "sa_adminhelp": "{GREEN}[ CS2-SimpleAdmin HELP ]{DEFAULT}\n- css_ban <#userid or name> [time in minutes/0 perm] [reason] - Ban player\n- css_addban [time in minutes/0 perm] [reason] - Ban player via steamid64\n- css_banip [time in minutes/0 perm] [reason] - Ban player via IP address\n- css_unban - Unban player\n- css_kick <#userid or name> [reason] - Kick player\n- css_gag <#userid or name> [time in minutes/0 perm] [reason] - Gag player\n- css_addgag [time in minutes/0 perm] [reason] - Gag player via steamid64\n- css_unmute - Ungag player\n- css_mute <#userid or name> [time in minutes/0 perm] [reason] - Mute player\n- css_addmute [time in minutes/0 perm] [reason] - Mute player via steamid64\n- css_give <#userid or name> - Give player a weapon\n- css_slay <#userid or name> - Kill player\n- css_slap <#userid or name> [damage] - Slap player\n- css_map - Change map\n- css_wsmap - Change workshop map\n- css_asay - Say message to all admins\n- css_say - Say message as admin in chat\n- css_psay <#userid or name> - Sends private message to player\n- css_csay - Say message as admin in center\n- css_hsay - Say message as admin in hud\n- css_noclip <#userid or name> - Toggle noclip for player\n- css_freeze <#userid or name> [duration] - Freeze player\n- css_unfreeze <#userid or name> - Unfreeze player\n- css_respawn <#userid or name> - Respawn player\n- css_cvar - Change cvar value\n- css_rcon - Run command as server", + "sa_player_ban_message_time": "You have been banned for {lightred}{0}{default} for {lightred}{1}{default} minutes by {lightred}{2}{default}!", + "sa_player_ban_message_perm": "You have been banned permanently for {lightred}{0}{default} by {lightred}{1}{default}!", + "sa_player_kick_message": "You have been kicked for {lightred}{0}{default} by {lightred}{1}{default}!", + "sa_player_gag_message_time": "You have been gagged for {lightred}{0}{default} for {lightred}{1}{default} minutes by {lightred}{2}{default}!", + "sa_player_gag_message_perm": "You have been gagged permanently for {lightred}{0}{default} by {lightred}{1}{default}!", + "sa_player_mute_message_time": "You have been muted for {lightred}{0}{default} for {lightred}{1}{default} minutes by {lightred}{2}{default}!", + "sa_player_mute_message_perm": "You have been muted permanently for {lightred}{0}{default} by {lightred}{1}{default}!", + "sa_admin_ban_message_time": "Admin {lightred}{0}{default} banned {lightred}{1}{default} for {lightred}{2}{default} for {lightred}{3}{default} minutes!", + "sa_admin_ban_message_perm": "Admin {lightred}{0}{default} banned {lightred}{1}{default} permanently for {lightred}{2}{default}!", + "sa_admin_kick_message": "Admin {lightred}{0}{default} kicked {lightred}{1}{default} for {lightred}{2}{default}!", + "sa_admin_gag_message_time": "Admin {lightred}{0}{default} gagged {lightred}{1}{default} for {lightred}{2}{default} for {lightred}{3}{default} minutes!", + "sa_admin_gag_message_perm": "Admin {lightred}{0}{default} gagged {lightred}{1}{default} permanently for {lightred}{2}{default}!", + "sa_admin_mute_message_time": "Admin {lightred}{0}{default} muted {lightred}{1}{default} for {lightred}{2}{default} for {lightred}{3}{default} minutes!", + "sa_admin_mute_message_perm": "Admin {lightred}{0}{default} muted {lightred}{1}{default} permanently for {lightred}{2}{default}!", + "sa_admin_give_message": "Admin {lightred}{0}{default} gave {lightred}{1}{default} a {lightred}{WE{default}APON}!", + "sa_admin_slay_message": "Admin {lightred}{0}{default} slayed {lightred}{1}{default}!", + "sa_admin_slap_message": "Admin {lightred}{0}{default} slapped {lightred}{1}{default}!", + "sa_admin_changemap_message": "Admin {lightred}{0}{default} changed map to {lightred}{1}{default}!", + "sa_admin_noclip_message": "Admin {lightred}{0}{default} toggled noclip for {lightred}{1}{default}!", + "sa_admin_freeze_message": "Admin {lightred}{0}{default} freezed {lightred}{1}{default}!", + "sa_admin_umfreeze_message": "Admin {lightred}{0}{default} umfreezed {lightred}{1}{default}!", + "sa_admin_respawn_message": "Admin {lightred}{0}{default} respawned {lightred}{1}{default}!", + "sa_adminsay_prefix": "{RED}ADMIN: {lightred}{0}{default}", + "sa_adminchat_template_admin": "{LIME}(ADMIN) {lightred}{0}{default}: {lightred}{1}{default}", + "sa_adminchat_template_player": "{SILVER}(PLAYER) {lightred}{0}{default}: {lightred}{1}{default}" +} \ No newline at end of file diff --git a/lang/pl.json b/lang/pl.json new file mode 100644 index 0000000..d496dc6 --- /dev/null +++ b/lang/pl.json @@ -0,0 +1,29 @@ +{ + "sa_prefix": "{lightred}[SA] {default}", + "sa_adminhelp": "{GREEN}[ CS2-SimpleAdmin HELP ]{DEFAULT}\n- css_ban <#userid or name> [time in minutes/0 perm] [reason] - Ban player\n- css_addban [time in minutes/0 perm] [reason] - Ban player via steamid64\n- css_banip [time in minutes/0 perm] [reason] - Ban player via IP address\n- css_unban - Unban player\n- css_kick <#userid or name> [reason] - Kick player\n- css_gag <#userid or name> [time in minutes/0 perm] [reason] - Gag player\n- css_addgag [time in minutes/0 perm] [reason] - Gag player via steamid64\n- css_unmute - Ungag player\n- css_mute <#userid or name> [time in minutes/0 perm] [reason] - Mute player\n- css_addmute [time in minutes/0 perm] [reason] - Mute player via steamid64\n- css_give <#userid or name> - Give player a weapon\n- css_slay <#userid or name> - Kill player\n- css_slap <#userid or name> [damage] - Slap player\n- css_map - Change map\n- css_wsmap - Change workshop map\n- css_asay - Say message to all admins\n- css_say - Say message as admin in chat\n- css_psay <#userid or name> - Sends private message to player\n- css_csay - Say message as admin in center\n- css_hsay - Say message as admin in hud\n- css_noclip <#userid or name> - Toggle noclip for player\n- css_freeze <#userid or name> [duration] - Freeze player\n- css_unfreeze <#userid or name> - Unfreeze player\n- css_respawn <#userid or name> - Respawn player\n- css_cvar - Change cvar value\n- css_rcon - Run command as server", + "sa_player_ban_message_time": "Zostałeś zbanowany za {lightred}{0}{default} na {lightred}{1}{default} minut przez {lightred}{2}{default}!", + "sa_player_ban_message_perm": "Zostałeś zbanowany na zawsze za {lightred}{0}{default} przez {lightred}{1}{default}!", + "sa_player_kick_message": "Zostałeś wyrzucony za {lightred}{0}{default} przez {lightred}{1}{default}!", + "sa_player_gag_message_time": "Zostałeś zakneblowany za {lightred}{0}{default} na {lightred}{1}{default} minut przez {lightred}{2}{default}!", + "sa_player_gag_message_perm": "Zostałeś zakneblowany na zawsze za {lightred}{0}{default} przez {lightred}{1}{default}!", + "sa_player_mute_message_time": "Zostałeś uciszony za {lightred}{0}{default} na {lightred}{1}{default} minute przez {lightred}{2}{default}!", + "sa_player_mute_message_perm": "Zostałeś uciszony na zawsze za {lightred}{0}{default} przez {lightred}{1}{default}!", + "sa_admin_ban_message_time": "Admin {lightred}{0}{default} zbanował {lightred}{1}{default} za {lightred}{2}{default} na {lightred}{3}{default} minut!", + "sa_admin_ban_message_perm": "Admin {lightred}{0}{default} zbanował {lightred}{1}{default} na zawsze za {lightred}{2}{default}!", + "sa_admin_kick_message": "Admin {lightred}{0}{default} wyrzucił {lightred}{1}{default} za {lightred}{2}{default}!", + "sa_admin_gag_message_time": "Admin {lightred}{0}{default} zakneblował {lightred}{1}{default} za {lightred}{2}{default} na {lightred}{3}{default} minut!", + "sa_admin_gag_message_perm": "Admin {lightred}{0}{default} zakneblował {lightred}{1}{default} na zawsze za {lightred}{2}{default}!", + "sa_admin_mute_message_time": "Admin {lightred}{0}{default} uciszył {lightred}{1}{default} za {lightred}{2}{default} na {lightred}{3}{default} minut!", + "sa_admin_mute_message_perm": "Admin {lightred}{0}{default} uciszył {lightred}{1}{default} na zawsze za {lightred}{2}{default}!", + "sa_admin_give_message": "Admin {lightred}{0}{default} dał {lightred}{1}{default} przedmiot {lightred}{WE{default}APON}!", + "sa_admin_slay_message": "Admin {lightred}{0}{default} zgładził {lightred}{1}{default}!", + "sa_admin_slap_message": "Admin {lightred}{0}{default} uderzył {lightred}{1}{default}!", + "sa_admin_changemap_message": "Admin {lightred}{0}{default} zmienił mapę na {lightred}{1}{default}!", + "sa_admin_noclip_message": "Admin {lightred}{0}{default} ustawił latanie dla {lightred}{1}{default}!", + "sa_admin_freeze_message": "Admin {lightred}{0}{default} zamroził {lightred}{1}{default}!", + "sa_admin_umfreeze_message": "Admin {lightred}{0}{default} odmroził {lightred}{1}{default}!", + "sa_admin_respawn_message": "Admin {lightred}{0}{default} odrodził {lightred}{1}{default}!", + "sa_adminsay_prefix": "{RED}ADMIN: {lightred}{0}{default}", + "sa_adminchat_template_admin": "{LIME}(ADMIN) {lightred}{0}{default}: {lightred}{1}{default}", + "sa_adminchat_template_player": "{SILVER}(GRACZ) {lightred}{0}{default}: {lightred}{1}{default}" +} \ No newline at end of file