mirror of
https://github.com/daffyyyy/CS2-SimpleAdmin.git
synced 2026-09-27 20:17:04 +02:00
1.6.0a
```diff
+ `Refactored Code`: Improved code structure for better maintainability.
+ `Player Penalties Command`: Introduced the `css_penalties` command to display player penalties.
+ `Admin Penalties Information`: Added functionality to provide information for admins regarding penalties of connecting players.
+ `Disconnected Players Command`: Added the `css_disconnected` command to show a list of disconnected players.
+ `Colorful Messages`: Implemented the `css_cssay` command to send colorful messages, e.g., `css_cssay {lightgreen}Test`.
+ `Respawn Functionality`: Updated the `css_respawn` command to respawn players at their death location.
+ `Menu Type Management`: Introduced the `css_menus` command to change the menu type via `MenuManagerCS2`.
+ `Dynamic Menu Control`: Enhanced menu interaction with dynamic controls using WASD + ER keys.
+ `Language File Updates`: Updated language files for better localization.
+ `API Integration`: Added a simple API for external interaction.
+ `Configurable Timezone`: Introduced timezone settings in the configuration.
+ `Admin Activity Display Options`: Added configurable settings for displaying admin activity:
+ `0`: Do not show
+ `1`: Hide admin name
+ `2`: Show admin name
+ `Discord Notification Customization`: Made Discord duration notifications customizable with `{relative}` and `{normal}` placeholders.
+ Improved command logging
+
`Configuration Options:`
+ `Timezone`
+ `Other Settings`
+ `Disconnected Players History Count`
+ `Show Activity Type`
```
This commit is contained in:
parent
a3b8d8cfa7
commit
05893a90d3
69 changed files with 10879 additions and 0 deletions
908
CS2-SimpleAdmin/Commands/basecommands.cs
Normal file
908
CS2-SimpleAdmin/Commands/basecommands.cs
Normal file
|
|
@ -0,0 +1,908 @@
|
|||
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 CS2_SimpleAdminApi;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using System.Globalization;
|
||||
|
||||
namespace CS2_SimpleAdmin;
|
||||
|
||||
public partial class CS2_SimpleAdmin
|
||||
{
|
||||
[ConsoleCommand("css_penalties")]
|
||||
[ConsoleCommand("css_mypenalties")]
|
||||
[ConsoleCommand("css_comms")]
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
public void OnPenaltiesCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (caller == null || caller.IsValid == false || !caller.UserId.HasValue || Database == null)
|
||||
return;
|
||||
|
||||
var userId = caller.UserId.Value;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
// Initialize managers
|
||||
MuteManager muteManager = new(Database);
|
||||
WarnManager warnManager = new(Database);
|
||||
|
||||
try
|
||||
{
|
||||
var warns = await warnManager.GetPlayerWarns(PlayersInfo[userId], false);
|
||||
|
||||
// Check if the player is muted
|
||||
var activeMutes = await muteManager.IsPlayerMuted(PlayersInfo[userId].SteamId.SteamId64.ToString());
|
||||
|
||||
Dictionary<PenaltyType, List<string>> mutesList = new()
|
||||
{
|
||||
{ PenaltyType.Gag, [] },
|
||||
{ PenaltyType.Mute, [] },
|
||||
{ PenaltyType.Silence, [] }
|
||||
};
|
||||
|
||||
List<string> warnsList = [];
|
||||
|
||||
bool found = false;
|
||||
foreach (var warn in warns.TakeWhile(warn => (string)warn.status == "ACTIVE"))
|
||||
{
|
||||
DateTime ends = warn.ends;
|
||||
if (_localizer == null) continue;
|
||||
using (new WithTemporaryCulture(caller.GetLanguage()))
|
||||
warnsList.Add(_localizer["sa_player_penalty_info_active_warn", ends.ToLocalTime().ToString(CultureInfo.CurrentCulture), (string)warn.reason]);
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
if (_localizer != null)
|
||||
warnsList.Add(_localizer["sa_player_penalty_info_no_active_warn"]);
|
||||
}
|
||||
|
||||
if (activeMutes.Count > 0)
|
||||
{
|
||||
foreach (var mute in activeMutes)
|
||||
{
|
||||
string muteType = mute.type;
|
||||
DateTime ends = mute.ends;
|
||||
using (new WithTemporaryCulture(caller.GetLanguage()))
|
||||
{
|
||||
switch (muteType)
|
||||
{
|
||||
// Apply mute penalty based on mute type
|
||||
case "GAG":
|
||||
if (_localizer != null)
|
||||
mutesList[PenaltyType.Gag].Add(_localizer["sa_player_penalty_info_active_gag", ends.ToLocalTime().ToString(CultureInfo.CurrentCulture)]);
|
||||
break;
|
||||
case "MUTE":
|
||||
if (_localizer != null)
|
||||
mutesList[PenaltyType.Mute].Add(_localizer["sa_player_penalty_info_active_mute", ends.ToLocalTime().ToString(CultureInfo.CurrentCulture)]);
|
||||
break;
|
||||
default:
|
||||
if (_localizer != null)
|
||||
mutesList[PenaltyType.Silence].Add(_localizer["sa_player_penalty_info_active_silence", ends.ToLocalTime().ToString(CultureInfo.CurrentCulture)]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_localizer != null)
|
||||
{
|
||||
if (mutesList[PenaltyType.Gag].Count == 0)
|
||||
mutesList[PenaltyType.Gag].Add(_localizer["sa_player_penalty_info_no_active_gag"]);
|
||||
if (mutesList[PenaltyType.Mute].Count == 0)
|
||||
mutesList[PenaltyType.Mute].Add(_localizer["sa_player_penalty_info_no_active_mute"]);
|
||||
if (mutesList[PenaltyType.Silence].Count == 0)
|
||||
mutesList[PenaltyType.Silence].Add(_localizer["sa_player_penalty_info_no_active_silence"]);
|
||||
}
|
||||
|
||||
await Server.NextFrameAsync(() =>
|
||||
{
|
||||
caller.SendLocalizedMessage(_localizer, "sa_player_penalty_info",
|
||||
[
|
||||
caller.PlayerName,
|
||||
PlayersInfo[userId].TotalBans,
|
||||
PlayersInfo[userId].TotalGags,
|
||||
PlayersInfo[userId].TotalMutes,
|
||||
PlayersInfo[userId].TotalSilences,
|
||||
PlayersInfo[userId].TotalWarns,
|
||||
string.Join("\n", mutesList.SelectMany(kvp => kvp.Value)),
|
||||
string.Join("\n", warnsList)
|
||||
]);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger?.LogError($"Error processing player information: {ex}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_admin")]
|
||||
[RequiresPermissions("@css/generic")]
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
public void OnAdminCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (caller == null || caller.IsValid == false)
|
||||
return;
|
||||
|
||||
AdminMenu.OpenMenu(caller);
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_adminhelp")]
|
||||
[RequiresPermissions("@css/generic")]
|
||||
public void OnAdminHelpCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var lines = File.ReadAllLines(ModuleDirectory + "/admin_help.txt");
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
command.ReplyToCommand(string.IsNullOrWhiteSpace(line) ? " " : line.ReplaceColorTags());
|
||||
}
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_addadmin")]
|
||||
[CommandHelper(minArgs: 4, usage: "<steamid> <name> <flags/groups> <immunity> <duration>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
[RequiresPermissions("@css/root")]
|
||||
public void OnAddAdminCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
|
||||
|
||||
if (!Helper.ValidateSteamId(command.GetArg(1), out var steamId) || steamId == null)
|
||||
{
|
||||
command.ReplyToCommand($"Invalid SteamID64.");
|
||||
return;
|
||||
}
|
||||
|
||||
var steamid = steamId.SteamId64.ToString();
|
||||
|
||||
if (command.GetArg(2).Length <= 0)
|
||||
{
|
||||
command.ReplyToCommand($"Invalid player name.");
|
||||
return;
|
||||
}
|
||||
if (!command.GetArg(3).Contains('@') && !command.GetArg(3).Contains('#'))
|
||||
{
|
||||
command.ReplyToCommand($"Invalid flag or group.");
|
||||
return;
|
||||
}
|
||||
|
||||
var name = command.GetArg(2);
|
||||
var flags = command.GetArg(3);
|
||||
var globalAdmin = command.GetArg(4).ToLower().Equals("-g") || command.GetArg(5).ToLower().Equals("-g") ||
|
||||
command.GetArg(6).ToLower().Equals("-g");
|
||||
int.TryParse(command.GetArg(4), out var immunity);
|
||||
int.TryParse(command.GetArg(5), out var time);
|
||||
|
||||
AddAdmin(caller, steamid, name, flags, immunity, time, globalAdmin, command);
|
||||
}
|
||||
|
||||
public static void AddAdmin(CCSPlayerController? caller, string steamid, string name, string flags, int immunity, int time = 0, bool globalAdmin = false, CommandInfo? command = null)
|
||||
{
|
||||
if (Database == null) return;
|
||||
PermissionManager adminManager = new(Database);
|
||||
|
||||
var flagsList = flags.Split(',').Select(flag => flag.Trim()).ToList();
|
||||
_ = adminManager.AddAdminBySteamId(steamid, name, flagsList, immunity, time, globalAdmin);
|
||||
|
||||
Helper.LogCommand(caller, $"css_addadmin {steamid} {name} {flags} {immunity} {time}");
|
||||
|
||||
var msg = $"Added '{flags}' flags to '{name}' ({steamid})";
|
||||
if (command != null)
|
||||
command.ReplyToCommand(msg);
|
||||
else if (caller != null && caller.IsValid)
|
||||
caller.PrintToChat(msg);
|
||||
else
|
||||
Server.PrintToConsole(msg);
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_deladmin")]
|
||||
[CommandHelper(minArgs: 1, usage: "<steamid>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
[RequiresPermissions("@css/root")]
|
||||
public void OnDelAdminCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
|
||||
if (!Helper.ValidateSteamId(command.GetArg(1), out var steamId) || steamId == null)
|
||||
{
|
||||
command.ReplyToCommand($"Invalid SteamID64.");
|
||||
return;
|
||||
}
|
||||
|
||||
var globalDelete = command.GetArg(2).ToLower().Equals("-g");
|
||||
|
||||
RemoveAdmin(caller, steamId.SteamId64.ToString(), globalDelete, command);
|
||||
}
|
||||
|
||||
public void RemoveAdmin(CCSPlayerController? caller, string steamid, bool globalDelete = false, CommandInfo? command = null)
|
||||
{
|
||||
if (Database == null) return;
|
||||
PermissionManager adminManager = new(Database);
|
||||
_ = adminManager.DeleteAdminBySteamId(steamid, globalDelete);
|
||||
|
||||
AddTimer(2, () =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(steamid) || !SteamID.TryParse(steamid, out var steamId) ||
|
||||
steamId == null) return;
|
||||
if (PermissionManager.AdminCache.ContainsKey(steamId))
|
||||
{
|
||||
PermissionManager.AdminCache.TryRemove(steamId, out _);
|
||||
}
|
||||
|
||||
AdminManager.ClearPlayerPermissions(steamId);
|
||||
AdminManager.RemovePlayerAdminData(steamId);
|
||||
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
|
||||
Helper.LogCommand(caller, $"css_deladmin {steamid}");
|
||||
|
||||
var msg = $"Removed flags from '{steamid}'";
|
||||
if (command != null)
|
||||
command.ReplyToCommand(msg);
|
||||
else if (caller != null && caller.IsValid)
|
||||
caller.PrintToChat(msg);
|
||||
else
|
||||
Server.PrintToConsole(msg);
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_addgroup")]
|
||||
[CommandHelper(minArgs: 3, usage: "<group_name> <flags> <immunity>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
[RequiresPermissions("@css/root")]
|
||||
public void OnAddGroup(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
|
||||
if (!command.GetArg(1).StartsWith("#"))
|
||||
{
|
||||
command.ReplyToCommand($"Group name must start with #.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!command.GetArg(2).StartsWith($"@") && !command.GetArg(2).StartsWith($"#"))
|
||||
{
|
||||
command.ReplyToCommand($"Invalid flag or group.");
|
||||
return;
|
||||
}
|
||||
|
||||
var groupName = command.GetArg(1);
|
||||
var flags = command.GetArg(2);
|
||||
int.TryParse(command.GetArg(3), out var immunity);
|
||||
var globalGroup = command.GetArg(4).ToLower().Equals("-g");
|
||||
|
||||
AddGroup(caller, groupName, flags, immunity, globalGroup, command);
|
||||
}
|
||||
|
||||
private static void AddGroup(CCSPlayerController? caller, string name, string flags, int immunity, bool globalGroup, CommandInfo? command = null)
|
||||
{
|
||||
if (Database == null) return;
|
||||
PermissionManager adminManager = new(Database);
|
||||
|
||||
var flagsList = flags.Split(',').Select(flag => flag.Trim()).ToList();
|
||||
_ = adminManager.AddGroup(name, flagsList, immunity, globalGroup);
|
||||
|
||||
Helper.LogCommand(caller, $"css_addgroup {name} {flags} {immunity}");
|
||||
|
||||
var msg = $"Created group '{name}' with flags '{flags}'";
|
||||
if (command != null)
|
||||
command.ReplyToCommand(msg);
|
||||
else if (caller != null && caller.IsValid)
|
||||
caller.PrintToChat(msg);
|
||||
else
|
||||
Server.PrintToConsole(msg);
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_delgroup")]
|
||||
[CommandHelper(minArgs: 1, usage: "<group_name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
[RequiresPermissions("@css/root")]
|
||||
public void OnDelGroupCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
|
||||
if (!command.GetArg(1).StartsWith($"#"))
|
||||
{
|
||||
command.ReplyToCommand($"Group name must start with #.");
|
||||
return;
|
||||
}
|
||||
|
||||
var groupName = command.GetArg(1);
|
||||
|
||||
RemoveGroup(caller, groupName, command);
|
||||
}
|
||||
|
||||
private void RemoveGroup(CCSPlayerController? caller, string name, CommandInfo? command = null)
|
||||
{
|
||||
if (Database == null) return;
|
||||
PermissionManager adminManager = new(Database);
|
||||
_ = adminManager.DeleteGroup(name);
|
||||
|
||||
AddTimer(2, () =>
|
||||
{
|
||||
ReloadAdmins(caller);
|
||||
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
|
||||
Helper.LogCommand(caller, $"css_delgroup {name}");
|
||||
|
||||
var msg = $"Removed group '{name}'";
|
||||
if (command != null)
|
||||
command.ReplyToCommand(msg);
|
||||
else if (caller != null && caller.IsValid)
|
||||
caller.PrintToChat(msg);
|
||||
else
|
||||
Server.PrintToConsole(msg);
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_reloadadmins")]
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
[RequiresPermissions("@css/root")]
|
||||
public void OnRelAdminCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
|
||||
ReloadAdmins(caller);
|
||||
|
||||
command.ReplyToCommand("Reloaded sql admins and groups");
|
||||
}
|
||||
|
||||
public void ReloadAdmins(CCSPlayerController? caller)
|
||||
{
|
||||
if (Database == null) return;
|
||||
|
||||
for (var index = 0; index < PermissionManager.AdminCache.Keys.ToList().Count; index++)
|
||||
{
|
||||
var steamId = PermissionManager.AdminCache.Keys.ToList()[index];
|
||||
if (!PermissionManager.AdminCache.TryRemove(steamId, out _)) continue;
|
||||
|
||||
AdminManager.ClearPlayerPermissions(steamId);
|
||||
AdminManager.RemovePlayerAdminData(steamId);
|
||||
}
|
||||
|
||||
PermissionManager adminManager = new(Database);
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await adminManager.CrateGroupsJsonFile();
|
||||
await adminManager.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))
|
||||
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"));
|
||||
});
|
||||
});
|
||||
|
||||
//_ = _adminManager.GiveAllGroupsFlags();
|
||||
//_ = _adminManager.GiveAllFlags();
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_stealth")]
|
||||
[ConsoleCommand("css_hide")]
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
[RequiresPermissions("@css/kick")]
|
||||
public void OnHideCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (caller == null) return;
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
|
||||
if (!SilentPlayers.Add(caller.Slot))
|
||||
{
|
||||
SilentPlayers.Remove(caller.Slot);
|
||||
caller.PrintToChat($"You aren't hidden now!");
|
||||
caller.ChangeTeam(CsTeam.Spectator);
|
||||
}
|
||||
else
|
||||
{
|
||||
Server.ExecuteCommand("sv_disable_teamselect_menu 1");
|
||||
|
||||
if (caller.PlayerPawn.Value != null && caller.PawnIsAlive)
|
||||
caller.PlayerPawn.Value.CommitSuicide(true, false);
|
||||
|
||||
AddTimer(1.0f, () => { Server.NextFrame(() => caller.ChangeTeam(CsTeam.Spectator)); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
AddTimer(1.4f, () => { Server.NextFrame(() => caller.ChangeTeam(CsTeam.None)); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
caller.PrintToChat($"You are hidden now!");
|
||||
AddTimer(2.0f, () => { Server.NextFrame(() => Server.ExecuteCommand("sv_disable_teamselect_menu 0")); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_who")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
[RequiresPermissions("@css/generic")]
|
||||
public void OnWhoCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
|
||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (!player.UserId.HasValue) return;
|
||||
if (!caller!.CanTarget(player)) return;
|
||||
|
||||
var playerInfo = PlayersInfo[player.UserId.Value];
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Server.NextFrameAsync(() =>
|
||||
{
|
||||
Action<string> printMethod = caller == null ? Server.PrintToConsole : caller.PrintToConsole;
|
||||
|
||||
printMethod($"--------- INFO ABOUT \"{playerInfo.Name}\" ---------");
|
||||
|
||||
printMethod($"• Clan: \"{player.Clan}\" Name: \"{playerInfo.Name}\"");
|
||||
printMethod($"• UserID: \"{playerInfo.UserId}\"");
|
||||
printMethod($"• SteamID64: \"{playerInfo.SteamId.SteamId64}\"");
|
||||
if (player.Connected == PlayerConnectedState.PlayerConnected)
|
||||
{
|
||||
printMethod($"• SteamID2: \"{playerInfo.SteamId.SteamId2}\"");
|
||||
printMethod($"• Community link: \"{playerInfo.SteamId.ToCommunityUrl()}\"");
|
||||
}
|
||||
if (playerInfo.IpAddress != null && AdminManager.PlayerHasPermissions(caller, "@css/showip"))
|
||||
printMethod($"• IP Address: \"{playerInfo.IpAddress}\"");
|
||||
printMethod($"• Ping: \"{player.Ping}\"");
|
||||
if (player.Connected == PlayerConnectedState.PlayerConnected)
|
||||
{
|
||||
printMethod($"• Total Bans: \"{playerInfo.TotalBans}\"");
|
||||
printMethod($"• Total Gags: \"{playerInfo.TotalGags}\"");
|
||||
printMethod($"• Total Mutes: \"{playerInfo.TotalMutes}\"");
|
||||
printMethod($"• Total Silences: \"{playerInfo.TotalSilences}\"");
|
||||
printMethod($"• Total Warns: \"{playerInfo.TotalWarns}\"");
|
||||
}
|
||||
|
||||
printMethod($"--------- END INFO ABOUT \"{player.PlayerName}\" ---------");
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_disconnected")]
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
[RequiresPermissions("@css/kick")]
|
||||
public void OnDisconnectedCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (_localizer == null || caller == null) return;
|
||||
|
||||
var disconnectedMenu = MenuApi?.NewMenu(_localizer["sa_menu_disconnected_title"]);
|
||||
|
||||
DisconnectedPlayers.ForEach(player =>
|
||||
{
|
||||
disconnectedMenu?.AddMenuOption(player.Name, (_, _) =>
|
||||
{
|
||||
var disconnectedMenuAction = MenuApi?.NewMenu(_localizer["sa_menu_disconnected_action_title"]);
|
||||
disconnectedMenuAction?.AddMenuOption(_localizer["sa_ban"], (_, _) =>
|
||||
{
|
||||
DurationMenu.OpenMenu(caller, _localizer["sa_ban"], player, (_, _, duration) =>
|
||||
ReasonMenu.OpenMenu(caller, PenaltyType.Ban, "Powód", player, (_, _, reason) =>
|
||||
{
|
||||
caller.ExecuteClientCommandFromServer($"css_addban {player.SteamId.SteamId64} {duration} \"{reason}\"");
|
||||
}));
|
||||
});
|
||||
disconnectedMenuAction?.AddMenuOption(_localizer["sa_mute"], (_, _) =>
|
||||
{
|
||||
DurationMenu.OpenMenu(caller, _localizer["sa_mute"], player, (_, _, duration) =>
|
||||
ReasonMenu.OpenMenu(caller, PenaltyType.Mute, "Powód", player, (_, _, reason) =>
|
||||
{
|
||||
caller.ExecuteClientCommandFromServer($"css_addmute {player.SteamId.SteamId64} {duration} \"{reason}\"");
|
||||
}));
|
||||
});
|
||||
disconnectedMenuAction?.AddMenuOption(_localizer["sa_gag"], (_, _) =>
|
||||
{
|
||||
DurationMenu.OpenMenu(caller, _localizer["sa_gag"], player, (_, _, duration) =>
|
||||
ReasonMenu.OpenMenu(caller, PenaltyType.Mute, "Powód", player, (_, _, reason) =>
|
||||
{
|
||||
caller.ExecuteClientCommandFromServer($"css_addgag {player.SteamId.SteamId64} {duration} \"{reason}\"");
|
||||
}));
|
||||
});
|
||||
disconnectedMenuAction?.AddMenuOption(_localizer["sa_silence"], (_, _) =>
|
||||
{
|
||||
DurationMenu.OpenMenu(caller, _localizer["sa_silence"], player, (_, _, duration) =>
|
||||
ReasonMenu.OpenMenu(caller, PenaltyType.Mute, "Powód", player, (_, _, reason) =>
|
||||
{
|
||||
caller.ExecuteClientCommandFromServer($"css_addsilence {player.SteamId.SteamId64} {duration} \"{reason}\"");
|
||||
}));
|
||||
});
|
||||
|
||||
disconnectedMenuAction?.Open(caller);
|
||||
});
|
||||
});
|
||||
|
||||
disconnectedMenu?.Open(caller);
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_warns")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name>", whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
[RequiresPermissions("@css/kick")]
|
||||
public void OnWarnsCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null || _localizer == null || caller == null) return;
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
|
||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsBot: false }).ToList();
|
||||
|
||||
if (playersToTarget.Count > 1)
|
||||
return;
|
||||
|
||||
Database.Database database = new(DbConnectionString);
|
||||
WarnManager warnManager = new(database);
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (!player.UserId.HasValue) return;
|
||||
if (!caller!.CanTarget(player)) return;
|
||||
|
||||
var userId = player.UserId.Value;
|
||||
|
||||
IMenu? warnsMenu = MenuApi?.NewMenu(_localizer["sa_admin_warns_menu_title", player.PlayerName]);
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var warnsList = await warnManager.GetPlayerWarns(PlayersInfo[userId], false);
|
||||
var sortedWarns = warnsList
|
||||
.OrderBy(warn => (string)warn.status == "ACTIVE" ? 0 : 1)
|
||||
.ThenByDescending(warn => (int)warn.id)
|
||||
.ToList();
|
||||
|
||||
sortedWarns.ForEach(w =>
|
||||
{
|
||||
warnsMenu?.AddMenuOption($"[{((string)w.status == "ACTIVE" ? $"{ChatColors.LightRed}X" : $"{ChatColors.Lime}✔️")}{ChatColors.Default}] {(string)w.reason}",
|
||||
(controller, option) =>
|
||||
{
|
||||
_ = warnManager.UnwarnPlayer(PlayersInfo[userId], (int)w.id);
|
||||
player.PrintToChat(_localizer["sa_admin_warns_unwarn", player.PlayerName, (string)w.reason]);
|
||||
});
|
||||
});
|
||||
|
||||
await Server.NextFrameAsync(() =>
|
||||
{
|
||||
warnsMenu?.Open(caller);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_players")]
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
[RequiresPermissions("@css/generic")]
|
||||
public void OnPlayersCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var isJson = command.GetArg(1).ToLower().Equals("-json");
|
||||
var isDuplicate = command.GetArg(1).ToLower().Equals("-duplicate") || command.GetArg(2).ToLower().Equals("-duplicate");
|
||||
|
||||
var playersToTarget = isDuplicate
|
||||
? Helper.GetValidPlayers().GroupBy(player => player.IpAddress?.Split(":")[0] ?? "Unknown")
|
||||
.Where(group => group.Count() > 1)
|
||||
.SelectMany(group => group)
|
||||
.ToList()
|
||||
: Helper.GetValidPlayers();
|
||||
|
||||
if (!isJson)
|
||||
{
|
||||
if (caller != null)
|
||||
{
|
||||
caller.PrintToConsole($"--------- PLAYER LIST ---------");
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
caller.PrintToConsole(
|
||||
$"• [#{player.UserId}] \"{player.PlayerName}\" (IP Address: \"{(AdminManager.PlayerHasPermissions(caller, "@css/showip") ? player.IpAddress?.Split(":")[0] : "Unknown")}\" SteamID64: \"{player.SteamID}\")");
|
||||
});
|
||||
caller.PrintToConsole($"--------- END PLAYER LIST ---------");
|
||||
}
|
||||
else
|
||||
{
|
||||
Server.PrintToConsole($"--------- PLAYER LIST ---------");
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
Server.PrintToConsole($"• [#{player.UserId}] \"{player.PlayerName}\" (IP Address: \"{player.IpAddress?.Split(":")[0]}\" SteamID64: \"{player.SteamID}\")");
|
||||
});
|
||||
Server.PrintToConsole($"--------- END PLAYER LIST ---------");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var playersJson = JsonConvert.SerializeObject(playersToTarget.Select((CCSPlayerController player) =>
|
||||
{
|
||||
var matchStats = player.ActionTrackingServices?.MatchStats;
|
||||
|
||||
return new
|
||||
{
|
||||
player.UserId,
|
||||
Name = player.PlayerName,
|
||||
SteamId = player.SteamID.ToString(),
|
||||
IpAddress = AdminManager.PlayerHasPermissions(caller, "@css/showip") ? player.IpAddress?.Split(":")[0] ?? "Unknown" : "Unknown",
|
||||
player.Ping,
|
||||
IsAdmin = AdminManager.PlayerHasPermissions(player, "@css/ban") || AdminManager.PlayerHasPermissions(player, "@css/generic"),
|
||||
Stats = new
|
||||
{
|
||||
player.Score,
|
||||
Kills = matchStats?.Kills ?? 0,
|
||||
Deaths = matchStats?.Deaths ?? 0,
|
||||
player.MVPs
|
||||
}
|
||||
};
|
||||
}));
|
||||
|
||||
if (caller != null)
|
||||
caller.PrintToConsole(playersJson);
|
||||
else
|
||||
Server.PrintToConsole(playersJson);
|
||||
}
|
||||
}
|
||||
|
||||
[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)
|
||||
{
|
||||
var callerName = caller == null ? "Console" : caller.PlayerName;
|
||||
var reason = _localizer?["sa_unknown"] ?? "Unknown";
|
||||
|
||||
var targets = GetTarget(command);
|
||||
|
||||
if (targets == null) return;
|
||||
var playersToTarget = targets.Players
|
||||
.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
|
||||
|
||||
if (playersToTarget.Count > 1 && Config.OtherSettings.DisableDangerousCommands || playersToTarget.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (command.ArgCount >= 2 && command.GetArg(2).Length > 0)
|
||||
reason = command.GetArg(2);
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (!player.IsValid)
|
||||
return;
|
||||
|
||||
if (caller!.CanTarget(player))
|
||||
{
|
||||
Kick(caller, player, reason, callerName, command);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Kick(CCSPlayerController? caller, CCSPlayerController player, string? reason = "Unknown", string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!player.IsValid) return;
|
||||
if (!caller.CanTarget(player)) return;
|
||||
if (!player.UserId.HasValue) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
callerName ??= caller != null ? caller.PlayerName : "Console";
|
||||
reason ??= _localizer?["sa_unknown"] ?? "Unknown";
|
||||
|
||||
var playerInfo = PlayersInfo[player.UserId.Value];
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
|
||||
// Freeze player pawn if alive
|
||||
if (player.PawnIsAlive)
|
||||
{
|
||||
player.Pawn.Value?.Freeze();
|
||||
}
|
||||
|
||||
// Determine message keys and arguments for the kick notification
|
||||
var (messageKey, activityMessageKey, centerArgs, adminActivityArgs) =
|
||||
("sa_player_kick_message", "sa_admin_kick_message",
|
||||
new object[] { reason, "CALLER" },
|
||||
new object[] { "CALLER", player.PlayerName, reason });
|
||||
|
||||
// Display center message to the kicked player
|
||||
Helper.DisplayCenterMessage(player, messageKey, callerName, centerArgs);
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, adminActivityArgs);
|
||||
}
|
||||
|
||||
// Schedule the kick for the player
|
||||
if (player.UserId.HasValue)
|
||||
{
|
||||
AddTimer(Config.OtherSettings.KickTime, () =>
|
||||
{
|
||||
if (player.IsValid)
|
||||
{
|
||||
Helper.KickPlayer(player.UserId.Value);
|
||||
}
|
||||
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
}
|
||||
|
||||
// Log the command and send Discord notification
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_kick {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {reason}");
|
||||
else
|
||||
Helper.LogCommand(caller, command);
|
||||
|
||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Kick, reason);
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_changemap")]
|
||||
[ConsoleCommand("css_map")]
|
||||
[RequiresPermissions("@css/changemap")]
|
||||
[CommandHelper(minArgs: 1, usage: "<mapname>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnMapCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var map = command.GetCommandString.Split(" ")[1];
|
||||
ChangeMap(caller, map, command);
|
||||
}
|
||||
|
||||
public void ChangeMap(CCSPlayerController? caller, string map, CommandInfo? command = null)
|
||||
{
|
||||
var callerName = caller != null ? caller.PlayerName : "Console";
|
||||
map = map.ToLower();
|
||||
|
||||
if (map.StartsWith("ws:"))
|
||||
{
|
||||
var issuedCommand = long.TryParse(map.Replace("ws:", ""), out var mapId)
|
||||
? $"host_workshop_map {mapId}"
|
||||
: $"ds_workshop_changelevel {map.Replace("ws:", "")}";
|
||||
|
||||
AddTimer(3.0f, () =>
|
||||
{
|
||||
Server.ExecuteCommand(issuedCommand);
|
||||
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Server.IsMapValid(map))
|
||||
{
|
||||
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, () =>
|
||||
{
|
||||
Server.ExecuteCommand($"changelevel {map}");
|
||||
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
}
|
||||
|
||||
var (activityMessageKey, adminActivityArgs) =
|
||||
("sa_admin_changemap_message",
|
||||
new object[] { "CALLER", map });
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, adminActivityArgs);
|
||||
}
|
||||
|
||||
Helper.LogCommand(caller, command?.GetCommandString ?? $"css_map {map}");
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_changewsmap", "Change workshop map.")]
|
||||
[ConsoleCommand("css_wsmap", "Change workshop map.")]
|
||||
[ConsoleCommand("css_workshop", "Change workshop map.")]
|
||||
[CommandHelper(1, "<name or id>")]
|
||||
[RequiresPermissions("@css/changemap")]
|
||||
public void OnWorkshopMapCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var map = command.GetArg(1);
|
||||
ChangeWorkshopMap(caller, map, command);
|
||||
}
|
||||
|
||||
public void ChangeWorkshopMap(CCSPlayerController? caller, string map, CommandInfo? command = null)
|
||||
{
|
||||
map = map.ToLower();
|
||||
var callerName = caller != null ? caller.PlayerName : "Console";
|
||||
|
||||
// Determine the workshop command
|
||||
var issuedCommand = long.TryParse(map, out var mapId)
|
||||
? $"host_workshop_map {mapId}"
|
||||
: $"ds_workshop_changelevel {map}";
|
||||
|
||||
// Define the admin activity message and arguments
|
||||
var activityMessageKey = "sa_admin_changemap_message";
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, ["CALLER", map]);
|
||||
}
|
||||
|
||||
// Add timer to execute the map change command after a delay
|
||||
AddTimer(3.0f, () =>
|
||||
{
|
||||
Server.ExecuteCommand(issuedCommand);
|
||||
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
|
||||
// Log the command for the change
|
||||
Helper.LogCommand(caller, command?.GetCommandString ?? $"css_wsmap {map}");
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_cvar", "Change a cvar.")]
|
||||
[CommandHelper(2, "<cvar> <value>")]
|
||||
[RequiresPermissions("@css/cvar")]
|
||||
public void OnCvarCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var cvar = ConVar.Find(command.GetArg(1));
|
||||
var callerName = caller == null ? "Console" : caller.PlayerName;
|
||||
|
||||
if (cvar == null)
|
||||
{
|
||||
command.ReplyToCommand($"Cvar \"{command.GetArg(1)}\" not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cvar.Name.Equals("sv_cheats") && !AdminManager.PlayerHasPermissions(caller, "@css/cheats"))
|
||||
{
|
||||
command.ReplyToCommand($"You don't have permissions to change \"{command.GetArg(1)}\".");
|
||||
return;
|
||||
}
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
|
||||
var value = command.GetArg(2);
|
||||
|
||||
Server.ExecuteCommand($"{cvar.Name} {value}");
|
||||
|
||||
command.ReplyToCommand($"{callerName} changed cvar {cvar.Name} to {value}.");
|
||||
Logger.LogInformation($"{callerName} changed cvar {cvar.Name} to {value}.");
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_rcon", "Run a server console command.")]
|
||||
[CommandHelper(1, "<command>")]
|
||||
[RequiresPermissions("@css/rcon")]
|
||||
public void OnRconCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var callerName = caller == null ? "Console" : caller.PlayerName;
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
|
||||
Server.ExecuteCommand(command.ArgString);
|
||||
command.ReplyToCommand($"{callerName} executed command {command.ArgString}.");
|
||||
Logger.LogInformation($"{callerName} executed command ({command.ArgString}).");
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_rr")]
|
||||
[ConsoleCommand("css_rg")]
|
||||
[ConsoleCommand("css_restart")]
|
||||
[ConsoleCommand("css_restartgame")]
|
||||
[RequiresPermissions("@css/generic")]
|
||||
[CommandHelper(minArgs: 0, usage: "", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnRestartCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
RestartGame(caller);
|
||||
}
|
||||
|
||||
public static void RestartGame(CCSPlayerController? admin)
|
||||
{
|
||||
Helper.LogCommand(admin, "css_restartgame");
|
||||
|
||||
// TODO: Localize
|
||||
var name = admin == null ? "Console" : admin.PlayerName;
|
||||
Server.PrintToChatAll($"[SA] {name}: Restarting game...");
|
||||
Server.ExecuteCommand("mp_restartgame 2");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue