mirror of
https://github.com/daffyyyy/CS2-SimpleAdmin.git
synced 2026-10-18 12:57:04 +02:00
upstream to 1.7.7-alpha-10
This commit is contained in:
commit
2de2924cef
106 changed files with 5897 additions and 3306 deletions
|
|
@ -1,89 +1,99 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Commands;
|
||||
using CounterStrikeSharp.API.Modules.Commands;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CS2_SimpleAdmin;
|
||||
|
||||
public static class RegisterCommands
|
||||
{
|
||||
internal static readonly Dictionary<string, IList<CommandDefinition>> _commandDefinitions =
|
||||
new(StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
private delegate void CommandCallback(CCSPlayerController? caller, CommandInfo.CommandCallback callback);
|
||||
|
||||
private static readonly string CommandsPath = Path.Combine(CS2_SimpleAdmin.ConfigDirectory, "Commands.json");
|
||||
private static readonly List<CommandMapping> CommandMappings =
|
||||
[
|
||||
new CommandMapping("css_ban", CS2_SimpleAdmin.Instance.OnBanCommand),
|
||||
new CommandMapping("css_addban", CS2_SimpleAdmin.Instance.OnAddBanCommand),
|
||||
new CommandMapping("css_banip", CS2_SimpleAdmin.Instance.OnBanIpCommand),
|
||||
new CommandMapping("css_unban", CS2_SimpleAdmin.Instance.OnUnbanCommand),
|
||||
new CommandMapping("css_warn", CS2_SimpleAdmin.Instance.OnWarnCommand),
|
||||
new CommandMapping("css_unwarn", CS2_SimpleAdmin.Instance.OnUnwarnCommand),
|
||||
new("css_ban", CS2_SimpleAdmin.Instance.OnBanCommand),
|
||||
new("css_addban", CS2_SimpleAdmin.Instance.OnAddBanCommand),
|
||||
new("css_banip", CS2_SimpleAdmin.Instance.OnBanIpCommand),
|
||||
new("css_unban", CS2_SimpleAdmin.Instance.OnUnbanCommand),
|
||||
new("css_warn", CS2_SimpleAdmin.Instance.OnWarnCommand),
|
||||
new("css_unwarn", CS2_SimpleAdmin.Instance.OnUnwarnCommand),
|
||||
|
||||
new CommandMapping("css_asay", CS2_SimpleAdmin.Instance.OnAdminToAdminSayCommand),
|
||||
new CommandMapping("css_cssay", CS2_SimpleAdmin.Instance.OnAdminCustomSayCommand),
|
||||
new CommandMapping("css_say", CS2_SimpleAdmin.Instance.OnAdminSayCommand),
|
||||
new CommandMapping("css_psay", CS2_SimpleAdmin.Instance.OnAdminPrivateSayCommand),
|
||||
new CommandMapping("css_csay", CS2_SimpleAdmin.Instance.OnAdminCenterSayCommand),
|
||||
new CommandMapping("css_hsay", CS2_SimpleAdmin.Instance.OnAdminHudSayCommand),
|
||||
new("css_asay", CS2_SimpleAdmin.Instance.OnAdminToAdminSayCommand),
|
||||
new("css_cssay", CS2_SimpleAdmin.Instance.OnAdminCustomSayCommand),
|
||||
new("css_say", CS2_SimpleAdmin.Instance.OnAdminSayCommand),
|
||||
new("css_psay", CS2_SimpleAdmin.Instance.OnAdminPrivateSayCommand),
|
||||
new("css_csay", CS2_SimpleAdmin.Instance.OnAdminCenterSayCommand),
|
||||
new("css_hsay", CS2_SimpleAdmin.Instance.OnAdminHudSayCommand),
|
||||
|
||||
new CommandMapping("css_penalties", CS2_SimpleAdmin.Instance.OnPenaltiesCommand),
|
||||
new CommandMapping("css_admin", CS2_SimpleAdmin.Instance.OnAdminCommand),
|
||||
new CommandMapping("css_adminhelp", CS2_SimpleAdmin.Instance.OnAdminHelpCommand),
|
||||
new CommandMapping("css_addadmin", CS2_SimpleAdmin.Instance.OnAddAdminCommand),
|
||||
new CommandMapping("css_deladmin", CS2_SimpleAdmin.Instance.OnDelAdminCommand),
|
||||
new CommandMapping("css_addgroup", CS2_SimpleAdmin.Instance.OnAddGroup),
|
||||
new CommandMapping("css_delgroup", CS2_SimpleAdmin.Instance.OnDelGroupCommand),
|
||||
new CommandMapping("css_reloadadmins", CS2_SimpleAdmin.Instance.OnRelAdminCommand),
|
||||
new CommandMapping("css_reloadbans", CS2_SimpleAdmin.Instance.OnRelBans),
|
||||
new CommandMapping("css_hide", CS2_SimpleAdmin.Instance.OnHideCommand),
|
||||
new CommandMapping("css_hidecomms", CS2_SimpleAdmin.Instance.OnHideCommsCommand),
|
||||
new CommandMapping("css_who", CS2_SimpleAdmin.Instance.OnWhoCommand),
|
||||
new CommandMapping("css_disconnected", CS2_SimpleAdmin.Instance.OnDisconnectedCommand),
|
||||
new CommandMapping("css_warns", CS2_SimpleAdmin.Instance.OnWarnsCommand),
|
||||
new CommandMapping("css_players", CS2_SimpleAdmin.Instance.OnPlayersCommand),
|
||||
new CommandMapping("css_kick", CS2_SimpleAdmin.Instance.OnKickCommand),
|
||||
new CommandMapping("css_map", CS2_SimpleAdmin.Instance.OnMapCommand),
|
||||
new CommandMapping("css_wsmap", CS2_SimpleAdmin.Instance.OnWorkshopMapCommand),
|
||||
new CommandMapping("css_cvar", CS2_SimpleAdmin.Instance.OnCvarCommand),
|
||||
new CommandMapping("css_rcon", CS2_SimpleAdmin.Instance.OnRconCommand),
|
||||
new CommandMapping("css_rr", CS2_SimpleAdmin.Instance.OnRestartCommand),
|
||||
new("css_penalties", CS2_SimpleAdmin.Instance.OnPenaltiesCommand),
|
||||
new("css_admin", CS2_SimpleAdmin.Instance.OnAdminCommand),
|
||||
new("css_adminhelp", CS2_SimpleAdmin.Instance.OnAdminHelpCommand),
|
||||
new("css_addadmin", CS2_SimpleAdmin.Instance.OnAddAdminCommand),
|
||||
new("css_deladmin", CS2_SimpleAdmin.Instance.OnDelAdminCommand),
|
||||
new("css_addgroup", CS2_SimpleAdmin.Instance.OnAddGroup),
|
||||
new("css_delgroup", CS2_SimpleAdmin.Instance.OnDelGroupCommand),
|
||||
new("css_reloadadmins", CS2_SimpleAdmin.Instance.OnRelAdminCommand),
|
||||
new("css_reloadbans", CS2_SimpleAdmin.Instance.OnRelBans),
|
||||
new("css_hide", CS2_SimpleAdmin.Instance.OnHideCommand),
|
||||
new("css_hidecomms", CS2_SimpleAdmin.Instance.OnHideCommsCommand),
|
||||
new("css_who", CS2_SimpleAdmin.Instance.OnWhoCommand),
|
||||
new("css_disconnected", CS2_SimpleAdmin.Instance.OnDisconnectedCommand),
|
||||
new("css_warns", CS2_SimpleAdmin.Instance.OnWarnsCommand),
|
||||
new("css_players", CS2_SimpleAdmin.Instance.OnPlayersCommand),
|
||||
new("css_kick", CS2_SimpleAdmin.Instance.OnKickCommand),
|
||||
new("css_map", CS2_SimpleAdmin.Instance.OnMapCommand),
|
||||
new("css_wsmap", CS2_SimpleAdmin.Instance.OnWorkshopMapCommand),
|
||||
new("css_cvar", CS2_SimpleAdmin.Instance.OnCvarCommand),
|
||||
new("css_rcon", CS2_SimpleAdmin.Instance.OnRconCommand),
|
||||
new("css_rr", CS2_SimpleAdmin.Instance.OnRestartCommand),
|
||||
|
||||
new CommandMapping("css_gag", CS2_SimpleAdmin.Instance.OnGagCommand),
|
||||
new CommandMapping("css_addgag", CS2_SimpleAdmin.Instance.OnAddGagCommand),
|
||||
new CommandMapping("css_ungag", CS2_SimpleAdmin.Instance.OnUngagCommand),
|
||||
new CommandMapping("css_mute", CS2_SimpleAdmin.Instance.OnMuteCommand),
|
||||
new CommandMapping("css_addmute", CS2_SimpleAdmin.Instance.OnAddMuteCommand),
|
||||
new CommandMapping("css_unmute", CS2_SimpleAdmin.Instance.OnUnmuteCommand),
|
||||
new CommandMapping("css_silence", CS2_SimpleAdmin.Instance.OnSilenceCommand),
|
||||
new CommandMapping("css_addsilence", CS2_SimpleAdmin.Instance.OnAddSilenceCommand),
|
||||
new CommandMapping("css_unsilence", CS2_SimpleAdmin.Instance.OnUnsilenceCommand),
|
||||
new("css_gag", CS2_SimpleAdmin.Instance.OnGagCommand),
|
||||
new("css_addgag", CS2_SimpleAdmin.Instance.OnAddGagCommand),
|
||||
new("css_ungag", CS2_SimpleAdmin.Instance.OnUngagCommand),
|
||||
new("css_mute", CS2_SimpleAdmin.Instance.OnMuteCommand),
|
||||
new("css_addmute", CS2_SimpleAdmin.Instance.OnAddMuteCommand),
|
||||
new("css_unmute", CS2_SimpleAdmin.Instance.OnUnmuteCommand),
|
||||
new("css_silence", CS2_SimpleAdmin.Instance.OnSilenceCommand),
|
||||
new("css_addsilence", CS2_SimpleAdmin.Instance.OnAddSilenceCommand),
|
||||
new("css_unsilence", CS2_SimpleAdmin.Instance.OnUnsilenceCommand),
|
||||
|
||||
new CommandMapping("css_vote", CS2_SimpleAdmin.Instance.OnVoteCommand),
|
||||
new("css_vote", CS2_SimpleAdmin.Instance.OnVoteCommand),
|
||||
|
||||
new CommandMapping("css_noclip", CS2_SimpleAdmin.Instance.OnNoclipCommand),
|
||||
new CommandMapping("css_freeze", CS2_SimpleAdmin.Instance.OnFreezeCommand),
|
||||
new CommandMapping("css_unfreeze", CS2_SimpleAdmin.Instance.OnUnfreezeCommand),
|
||||
new CommandMapping("css_godmode", CS2_SimpleAdmin.Instance.OnGodCommand),
|
||||
new("css_noclip", CS2_SimpleAdmin.Instance.OnNoclipCommand),
|
||||
new("css_freeze", CS2_SimpleAdmin.Instance.OnFreezeCommand),
|
||||
new("css_unfreeze", CS2_SimpleAdmin.Instance.OnUnfreezeCommand),
|
||||
new("css_godmode", CS2_SimpleAdmin.Instance.OnGodCommand),
|
||||
|
||||
new CommandMapping("css_slay", CS2_SimpleAdmin.Instance.OnSlayCommand),
|
||||
new CommandMapping("css_slap", CS2_SimpleAdmin.Instance.OnSlapCommand),
|
||||
new CommandMapping("css_give", CS2_SimpleAdmin.Instance.OnGiveCommand),
|
||||
new CommandMapping("css_strip", CS2_SimpleAdmin.Instance.OnStripCommand),
|
||||
new CommandMapping("css_hp", CS2_SimpleAdmin.Instance.OnHpCommand),
|
||||
new CommandMapping("css_speed", CS2_SimpleAdmin.Instance.OnSpeedCommand),
|
||||
new CommandMapping("css_gravity", CS2_SimpleAdmin.Instance.OnGravityCommand),
|
||||
new CommandMapping("css_resize", CS2_SimpleAdmin.Instance.OnResizeCommand),
|
||||
new CommandMapping("css_money", CS2_SimpleAdmin.Instance.OnMoneyCommand),
|
||||
new CommandMapping("css_team", CS2_SimpleAdmin.Instance.OnTeamCommand),
|
||||
new CommandMapping("css_rename", CS2_SimpleAdmin.Instance.OnRenameCommand),
|
||||
new CommandMapping("css_prename", CS2_SimpleAdmin.Instance.OnPrenameCommand),
|
||||
new CommandMapping("css_respawn", CS2_SimpleAdmin.Instance.OnRespawnCommand),
|
||||
new CommandMapping("css_tp", CS2_SimpleAdmin.Instance.OnGotoCommand),
|
||||
new CommandMapping("css_bring", CS2_SimpleAdmin.Instance.OnBringCommand),
|
||||
new CommandMapping("css_pluginsmanager", CS2_SimpleAdmin.Instance.OnPluginManagerCommand),
|
||||
new CommandMapping("css_adminvoice", CS2_SimpleAdmin.Instance.OnAdminVoiceCommand)
|
||||
new("css_slay", CS2_SimpleAdmin.Instance.OnSlayCommand),
|
||||
new("css_slap", CS2_SimpleAdmin.Instance.OnSlapCommand),
|
||||
new("css_give", CS2_SimpleAdmin.Instance.OnGiveCommand),
|
||||
new("css_strip", CS2_SimpleAdmin.Instance.OnStripCommand),
|
||||
new("css_hp", CS2_SimpleAdmin.Instance.OnHpCommand),
|
||||
new("css_speed", CS2_SimpleAdmin.Instance.OnSpeedCommand),
|
||||
new("css_gravity", CS2_SimpleAdmin.Instance.OnGravityCommand),
|
||||
new("css_resize", CS2_SimpleAdmin.Instance.OnResizeCommand),
|
||||
new("css_money", CS2_SimpleAdmin.Instance.OnMoneyCommand),
|
||||
new("css_team", CS2_SimpleAdmin.Instance.OnTeamCommand),
|
||||
new("css_rename", CS2_SimpleAdmin.Instance.OnRenameCommand),
|
||||
new("css_prename", CS2_SimpleAdmin.Instance.OnPrenameCommand),
|
||||
new("css_respawn", CS2_SimpleAdmin.Instance.OnRespawnCommand),
|
||||
new("css_tp", CS2_SimpleAdmin.Instance.OnGotoCommand),
|
||||
new("css_bring", CS2_SimpleAdmin.Instance.OnBringCommand),
|
||||
new("css_pluginsmanager", CS2_SimpleAdmin.Instance.OnPluginManagerCommand),
|
||||
new("css_adminvoice", CS2_SimpleAdmin.Instance.OnAdminVoiceCommand)
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Initializes command registration.
|
||||
/// If the commands config file does not exist, creates it and then recurses to register commands.
|
||||
/// Otherwise, directly registers commands from the configuration.
|
||||
/// </summary>
|
||||
public static void InitializeCommands()
|
||||
{
|
||||
if (!File.Exists(CommandsPath))
|
||||
|
|
@ -97,6 +107,10 @@ public static class RegisterCommands
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the default commands configuration JSON file with built-in commands and aliases.
|
||||
/// </summary>
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
|
||||
private static void CreateConfig()
|
||||
{
|
||||
var commands = new CommandsConfig
|
||||
|
|
@ -170,14 +184,26 @@ public static class RegisterCommands
|
|||
}
|
||||
};
|
||||
|
||||
var json = JsonConvert.SerializeObject(commands, Formatting.Indented);
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(commands, options);
|
||||
File.WriteAllText(CommandsPath, json);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads the command configuration JSON file and registers all commands and their aliases with their callbacks.
|
||||
/// Also registers any custom commands previously stored.
|
||||
/// </summary>
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
|
||||
private static void Register()
|
||||
{
|
||||
var json = File.ReadAllText(CommandsPath);
|
||||
var commandsConfig = JsonConvert.DeserializeObject<CommandsConfig>(json);
|
||||
var commandsConfig = JsonSerializer.Deserialize<CommandsConfig>(json,
|
||||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
|
||||
if (commandsConfig?.Commands == null) return;
|
||||
|
||||
|
|
@ -195,19 +221,37 @@ public static class RegisterCommands
|
|||
{
|
||||
CS2_SimpleAdmin.Instance.AddCommand(alias, "", mapping.Callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var (name, definitions) in RegisterCommands._commandDefinitions)
|
||||
{
|
||||
foreach (var definition in definitions)
|
||||
{
|
||||
CS2_SimpleAdmin._logger?.LogInformation($"Registering custom command: `{name}`");
|
||||
CS2_SimpleAdmin.Instance.AddCommand(name, definition.Description, definition.Callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the JSON configuration structure for commands.
|
||||
/// </summary>
|
||||
private class CommandsConfig
|
||||
{
|
||||
public Dictionary<string, Command>? Commands { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a command definition containing a list of aliases.
|
||||
/// </summary>
|
||||
private class Command
|
||||
{
|
||||
public string[]? Aliases { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps a command key to its respective command callback handler.
|
||||
/// </summary>
|
||||
private class CommandMapping(string commandKey, CommandInfo.CommandCallback callback)
|
||||
{
|
||||
public string CommandKey { get; } = commandKey;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ namespace CS2_SimpleAdmin;
|
|||
|
||||
public partial class CS2_SimpleAdmin
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles the 'ban' command, allowing admins to ban one or more valid connected players.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the ban command, or null for console.</param>
|
||||
/// <param name="command">The command information including arguments.</param>
|
||||
[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)
|
||||
|
|
@ -19,7 +24,7 @@ public partial class CS2_SimpleAdmin
|
|||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
if (command.ArgCount < 2)
|
||||
return;
|
||||
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, Connected: PlayerConnectedState.PlayerConnected, IsHLTV: false }).ToList();
|
||||
|
|
@ -28,7 +33,7 @@ public partial class CS2_SimpleAdmin
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var reason = command.ArgCount >= 3
|
||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
||||
|
|
@ -39,7 +44,7 @@ public partial class CS2_SimpleAdmin
|
|||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
|
||||
if (time < 0 && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
|
||||
{
|
||||
DurationMenu.OpenMenu(caller, $"{_localizer?["sa_ban"] ?? "Ban"}: {player.PlayerName}", player,
|
||||
|
|
@ -51,26 +56,40 @@ public partial class CS2_SimpleAdmin
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Core logic to ban a specific player, scheduling database updates, notifications, and kicks.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the ban, or null for console.</param>
|
||||
/// <param name="player">The player to be banned.</param>
|
||||
/// <param name="time">Ban duration in minutes; 0 means permanent.</param>
|
||||
/// <param name="reason">Reason for the ban.</param>
|
||||
/// <param name="callerName">Optional caller name string. If null, defaults to player name or console.</param>
|
||||
/// <param name="banManager">Optional BanManager to handle ban persistence.</param>
|
||||
/// <param name="command">Optional command info object for logging.</param>
|
||||
/// <param name="silent">If true, suppresses command logging.</param>
|
||||
internal void Ban(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, BanManager? banManager = null, CommandInfo? command = null, bool silent = false)
|
||||
{
|
||||
if (Database == null || !player.IsValid || !player.UserId.HasValue) return;
|
||||
if (DatabaseProvider == null || !player.IsValid || !player.UserId.HasValue) return;
|
||||
if (!caller.CanTarget(player)) return;
|
||||
if (!CheckValidBan(caller, time)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
||||
? caller.PlayerName
|
||||
callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
||||
? caller.PlayerName
|
||||
: (_localizer?["sa_console"] ?? "Console");
|
||||
|
||||
|
||||
// Get player and admin information
|
||||
var playerInfo = PlayersInfo[player.UserId.Value];
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
var playerInfo = PlayersInfo[player.SteamID];
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
|
||||
|
||||
// Asynchronously handle banning logic
|
||||
Task.Run(async () =>
|
||||
{
|
||||
int? penaltyId = await BanManager.BanPlayer(playerInfo, adminInfo, reason, time);
|
||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Ban, reason, time, penaltyId);
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Ban, reason, time, penaltyId);
|
||||
});
|
||||
});
|
||||
|
||||
// Determine message keys and arguments based on ban time
|
||||
|
|
@ -110,26 +129,31 @@ public partial class CS2_SimpleAdmin
|
|||
else
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
|
||||
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Ban, _localizer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a ban for a player by their SteamID, including offline bans.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the ban command.</param>
|
||||
/// <param name="steamid">SteamID of the player to ban.</param>
|
||||
/// <param name="time">Ban duration in minutes (0 means permanent).</param>
|
||||
/// <param name="reason">Reason for banning.</param>
|
||||
/// <param name="banManager">Optional ban manager for database operations.</param>
|
||||
internal void AddBan(CCSPlayerController? caller, SteamID steamid, int time, string reason, BanManager? banManager = null)
|
||||
{
|
||||
// Set default caller name if not provided
|
||||
var callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
||||
? caller.PlayerName
|
||||
var callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
||||
? caller.PlayerName
|
||||
: (_localizer?["sa_console"] ?? "Console");
|
||||
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
|
||||
var player = Helper.GetPlayerFromSteamid64(steamid.SteamId64.ToString());
|
||||
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
|
||||
var player = Helper.GetPlayerFromSteamid64(steamid.SteamId64);
|
||||
if (player != null && player.IsValid)
|
||||
{
|
||||
if (!caller.CanTarget(player))
|
||||
return;
|
||||
|
||||
Ban(caller, player, time, reason, callerName, silent: true);
|
||||
//command.ReplyToCommand($"Banned player {player.PlayerName}.");
|
||||
}
|
||||
|
|
@ -137,23 +161,31 @@ public partial class CS2_SimpleAdmin
|
|||
{
|
||||
if (!caller.CanTarget(steamid))
|
||||
return;
|
||||
|
||||
// Asynchronous ban operation if player is not online or not found
|
||||
Task.Run(async () =>
|
||||
{
|
||||
int? penaltyId = await BanManager.AddBanBySteamid(steamid.SteamId64.ToString(), adminInfo, reason, time);
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Ban, reason, time, penaltyId);
|
||||
int? penaltyId = await BanManager.AddBanBySteamid(steamid.SteamId64, adminInfo, reason, time);
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Ban, reason, time,
|
||||
penaltyId);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Helper.SendDiscordPenaltyMessage(caller, steamid.SteamId64.ToString(), reason, time, PenaltyType.Ban, _localizer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles banning a player by specifying their SteamID via command.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command, or null if console.</param>
|
||||
/// <param name="command">Command information including arguments (SteamID, time, reason).</param>
|
||||
[RequiresPermissions("@css/ban")]
|
||||
[CommandHelper(minArgs: 1, usage: "<steamid> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnAddBanCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
var callerName = caller?.PlayerName ?? _localizer?["sa_console"] ?? "Console";
|
||||
if (command.ArgCount < 2 || string.IsNullOrEmpty(command.GetArg(1))) return;
|
||||
if (!Helper.ValidateSteamId(command.GetArg(1), out var steamId) || steamId == null)
|
||||
|
|
@ -162,23 +194,21 @@ public partial class CS2_SimpleAdmin
|
|||
return;
|
||||
}
|
||||
|
||||
var steamid = steamId.SteamId64.ToString();
|
||||
var steamid = steamId.SteamId64;
|
||||
var reason = command.ArgCount >= 3
|
||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
||||
|
||||
|
||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
||||
|
||||
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
|
||||
|
||||
if (!CheckValidBan(caller, time)) return;
|
||||
|
||||
var adminInfo = caller != null && caller.UserId.HasValue
|
||||
? PlayersInfo[caller.UserId.Value]
|
||||
? PlayersInfo[caller.SteamID]
|
||||
: null;
|
||||
|
||||
var player = Helper.GetPlayerFromSteamid64(steamid);
|
||||
|
||||
if (player != null && player.IsValid)
|
||||
{
|
||||
if (!caller.CanTarget(player))
|
||||
|
|
@ -191,15 +221,19 @@ public partial class CS2_SimpleAdmin
|
|||
{
|
||||
if (!caller.CanTarget(new SteamID(steamId.SteamId64)))
|
||||
return;
|
||||
|
||||
|
||||
// Asynchronous ban operation if player is not online or not found
|
||||
Task.Run(async () =>
|
||||
{
|
||||
int? penaltyId = await BanManager.AddBanBySteamid(steamid, adminInfo, reason, time);
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Ban, reason, time, penaltyId);
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Ban, reason, time,
|
||||
penaltyId);
|
||||
});
|
||||
});
|
||||
|
||||
Helper.SendDiscordPenaltyMessage(caller, steamid, reason, time, PenaltyType.Ban, _localizer);
|
||||
|
||||
Helper.SendDiscordPenaltyMessage(caller, steamid.ToString(), reason, time, PenaltyType.Ban, _localizer);
|
||||
|
||||
command.ReplyToCommand($"Player with steamid {steamid} is not online. Ban has been added offline.");
|
||||
}
|
||||
|
|
@ -210,11 +244,16 @@ public partial class CS2_SimpleAdmin
|
|||
Server.ExecuteCommand($"banid 1 {steamId.SteamId3}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles banning a player by their IP address, supporting offline banning if player is not online.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the ban command.</param>
|
||||
/// <param name="command">The command containing the IP, time, and reason arguments.</param>
|
||||
[RequiresPermissions("@css/ban")]
|
||||
[CommandHelper(minArgs: 1, usage: "<ip> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnBanIpCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
var callerName = caller?.PlayerName ?? _localizer?["sa_console"] ?? "Console";
|
||||
if (command.ArgCount < 2 || string.IsNullOrEmpty(command.GetArg(1))) return;
|
||||
var ipAddress = command.GetArg(1);
|
||||
|
|
@ -228,7 +267,7 @@ public partial class CS2_SimpleAdmin
|
|||
var reason = command.ArgCount >= 3
|
||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
||||
|
||||
|
||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
||||
|
||||
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
|
||||
|
|
@ -236,17 +275,20 @@ public partial class CS2_SimpleAdmin
|
|||
if (!CheckValidBan(caller, time)) return;
|
||||
|
||||
var adminInfo = caller != null && caller.UserId.HasValue
|
||||
? PlayersInfo[caller.UserId.Value]
|
||||
? PlayersInfo[caller.SteamID]
|
||||
: null;
|
||||
|
||||
var player = Helper.GetPlayerFromIp(ipAddress);
|
||||
|
||||
if (player != null && player.IsValid)
|
||||
var players = Helper.GetPlayerFromIp(ipAddress);
|
||||
if (players.Count >= 1)
|
||||
{
|
||||
if (!caller.CanTarget(player))
|
||||
return;
|
||||
foreach (var player in players)
|
||||
{
|
||||
if (player == null || !player.IsValid) continue;
|
||||
if (!caller.CanTarget(player))
|
||||
return;
|
||||
|
||||
Ban(caller, player, time, reason, callerName, silent: true);
|
||||
Ban(caller, player, time, reason, callerName, silent: true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -262,6 +304,12 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the ban duration is valid based on the caller's permissions and configured limits.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the ban command.</param>
|
||||
/// <param name="duration">Requested ban duration in minutes.</param>
|
||||
/// <returns>True if ban duration is valid; otherwise, false.</returns>
|
||||
private bool CheckValidBan(CCSPlayerController? caller, int duration)
|
||||
{
|
||||
if (caller == null) return true;
|
||||
|
|
@ -280,14 +328,17 @@ public partial class CS2_SimpleAdmin
|
|||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles unbanning players by pattern (steamid, name, or IP).
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the unban command.</param>
|
||||
/// <param name="command">Command containing target pattern and optional reason.</param>
|
||||
[RequiresPermissions("@css/unban")]
|
||||
[CommandHelper(minArgs: 1, usage: "<steamid or name or ip> [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnUnbanCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
|
||||
if (DatabaseProvider == null) return;
|
||||
var callerSteamId = caller?.SteamID.ToString() ?? _localizer?["sa_console"] ?? "Console";
|
||||
|
||||
if (command.GetArg(1).Length <= 1)
|
||||
{
|
||||
command.ReplyToCommand($"Too short pattern to search.");
|
||||
|
|
@ -298,26 +349,28 @@ public partial class CS2_SimpleAdmin
|
|||
var reason = command.ArgCount >= 2
|
||||
? string.Join(" ", Enumerable.Range(2, command.ArgCount - 2).Select(command.GetArg)).Trim()
|
||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
||||
|
||||
|
||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
||||
|
||||
Task.Run(async () => await BanManager.UnbanPlayer(pattern, callerSteamId, reason));
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
|
||||
command.ReplyToCommand($"Unbanned player with pattern {pattern}.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles warning players, supporting multiple targets and warning durations.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the warn command.</param>
|
||||
/// <param name="command">The command containing target, time, and reason parameters.</param>
|
||||
[RequiresPermissions("@css/kick")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnWarnCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null)
|
||||
if (DatabaseProvider == null)
|
||||
return;
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
if (command.ArgCount < 2)
|
||||
return;
|
||||
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player.Connected == PlayerConnectedState.PlayerConnected && !player.IsHLTV).ToList();
|
||||
|
|
@ -327,33 +380,40 @@ public partial class CS2_SimpleAdmin
|
|||
return;
|
||||
}
|
||||
|
||||
WarnManager warnManager = new(Database);
|
||||
|
||||
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
|
||||
var reason = command.ArgCount >= 3
|
||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
||||
|
||||
|
||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (caller!.CanTarget(player))
|
||||
{
|
||||
Warn(caller, player, time, reason, callerName, warnManager, command);
|
||||
Warn(caller, player, time, reason, callerName, command);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
internal void Warn(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, WarnManager? warnManager = null, CommandInfo? command = null)
|
||||
/// <summary>
|
||||
/// Issues a warning penalty to a specific player with optional duration and reason.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the warning.</param>
|
||||
/// <param name="player">The player to warn.</param>
|
||||
/// <param name="time">Duration of the warning in minutes.</param>
|
||||
/// <param name="reason">Reason for the warning.</param>
|
||||
/// <param name="callerName">Optional display name of the caller.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal void Warn(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (Database == null || !player.IsValid || !player.UserId.HasValue) return;
|
||||
if (DatabaseProvider == null || !player.IsValid || !player.UserId.HasValue) return;
|
||||
if (!caller.CanTarget(player)) return;
|
||||
if (!CheckValidBan(caller, time)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
||||
? caller.PlayerName
|
||||
callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
||||
? caller.PlayerName
|
||||
: (_localizer?["sa_console"] ?? "Console");
|
||||
|
||||
// Freeze player pawn if alive
|
||||
|
|
@ -364,19 +424,21 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
|
||||
// Get player and admin information
|
||||
var playerInfo = PlayersInfo[player.UserId.Value];
|
||||
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
var playerInfo = PlayersInfo[player.SteamID];
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
|
||||
|
||||
// Asynchronously handle warning logic
|
||||
Task.Run(async () =>
|
||||
{
|
||||
warnManager ??= new WarnManager(Database);
|
||||
int? penaltyId = await warnManager.WarnPlayer(playerInfo, adminInfo, reason, time);
|
||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Warn, reason, time, penaltyId);
|
||||
int? penaltyId = await WarnManager.WarnPlayer(playerInfo, adminInfo, reason, time);
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Warn, reason, time,
|
||||
penaltyId);
|
||||
});
|
||||
|
||||
// Check for warn thresholds and execute punish command if applicable
|
||||
var totalWarns = await warnManager.GetPlayerWarnsCount(player.SteamID.ToString());
|
||||
var totalWarns = await WarnManager.GetPlayerWarnsCount(player.SteamID);
|
||||
if (Config.WarnThreshold.Count > 0)
|
||||
{
|
||||
string? punishCommand = null;
|
||||
|
|
@ -424,17 +486,25 @@ public partial class CS2_SimpleAdmin
|
|||
// Send Discord notification for the warning
|
||||
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Warn, _localizer);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a warning to a player by their SteamID, including support for offline players.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the warn command.</param>
|
||||
/// <param name="steamid">SteamID of the player to warn.</param>
|
||||
/// <param name="time">Warning duration in minutes.</param>
|
||||
/// <param name="reason">Reason for the warning.</param>
|
||||
/// <param name="warnManager">Optional warn manager instance.</param>
|
||||
internal void AddWarn(CCSPlayerController? caller, SteamID steamid, int time, string reason, WarnManager? warnManager = null)
|
||||
{
|
||||
// Set default caller name if not provided
|
||||
var callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
||||
? caller.PlayerName
|
||||
var callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
||||
? caller.PlayerName
|
||||
: (_localizer?["sa_console"] ?? "Console");
|
||||
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
|
||||
var player = Helper.GetPlayerFromSteamid64(steamid.SteamId64.ToString());
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
|
||||
|
||||
var player = Helper.GetPlayerFromSteamid64(steamid.SteamId64);
|
||||
|
||||
if (player != null && player.IsValid)
|
||||
{
|
||||
|
|
@ -448,15 +518,19 @@ public partial class CS2_SimpleAdmin
|
|||
{
|
||||
if (!caller.CanTarget(steamid))
|
||||
return;
|
||||
|
||||
|
||||
// Asynchronous ban operation if player is not online or not found
|
||||
Task.Run(async () =>
|
||||
{
|
||||
int? penaltyId = await WarnManager.AddWarnBySteamid(steamid.SteamId64.ToString(), adminInfo, reason, time);
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Warn, reason, time, penaltyId);
|
||||
int? penaltyId = await WarnManager.AddWarnBySteamid(steamid.SteamId64, adminInfo, reason, time);
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Warn, reason, time,
|
||||
penaltyId);
|
||||
});
|
||||
|
||||
// Check for warn thresholds and execute punish command if applicable
|
||||
var totalWarns = await WarnManager.GetPlayerWarnsCount(steamid.SteamId64.ToString());
|
||||
var totalWarns = await WarnManager.GetPlayerWarnsCount(steamid.SteamId64);
|
||||
if (Config.WarnThreshold.Count > 0)
|
||||
{
|
||||
string? punishCommand = null;
|
||||
|
|
@ -476,16 +550,21 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Helper.SendDiscordPenaltyMessage(caller, steamid.SteamId64.ToString(), reason, time, PenaltyType.Warn, _localizer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handles removing a warning (unwarn) by a pattern string.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the unwarn command.</param>
|
||||
/// <param name="command">The command containing target pattern.</param>
|
||||
[RequiresPermissions("@css/kick")]
|
||||
[CommandHelper(minArgs: 1, usage: "<steamid or name or ip>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnUnwarnCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
|
||||
if (command.GetArg(1).Length <= 1)
|
||||
{
|
||||
|
|
@ -494,9 +573,7 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
|
||||
var pattern = command.GetArg(1);
|
||||
|
||||
Task.Run(async () => await WarnManager.UnwarnPlayer(pattern));
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
command.ReplyToCommand($"Unwarned player with pattern {pattern}.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@ namespace CS2_SimpleAdmin;
|
|||
|
||||
public partial class CS2_SimpleAdmin
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends a chat message only to admins that have chat permission.
|
||||
/// The message is encoded properly to handle UTF-8 characters.
|
||||
/// </summary>
|
||||
/// <param name="caller">The admin player sending the message, or null for console.</param>
|
||||
/// <param name="command">The command input containing the message.</param>
|
||||
[CommandHelper(1, "<message>")]
|
||||
[RequiresPermissions("@css/chat")]
|
||||
public void OnAdminToAdminSayCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -30,6 +36,11 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a custom chat message to all players with color tags processed.
|
||||
/// </summary>
|
||||
/// <param name="caller">The admin or console sending the message.</param>
|
||||
/// <param name="command">The command input containing the message.</param>
|
||||
[CommandHelper(1, "<message>")]
|
||||
[RequiresPermissions("@css/chat")]
|
||||
public void OnAdminCustomSayCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -47,6 +58,11 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a chat message to all players with localization prefix and color tags handled.
|
||||
/// </summary>
|
||||
/// <param name="caller">The admin or console sending the message.</param>
|
||||
/// <param name="command">The command input containing the message.</param>
|
||||
[CommandHelper(1, "<message>")]
|
||||
[RequiresPermissions("@css/chat")]
|
||||
public void OnAdminSayCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -57,7 +73,6 @@ public partial class CS2_SimpleAdmin
|
|||
var utf8String = Encoding.UTF8.GetString(utf8BytesString);
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
|
||||
foreach (var player in Helper.GetValidPlayers())
|
||||
{
|
||||
player.SendLocalizedMessage(_localizer,
|
||||
|
|
@ -66,6 +81,11 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a private chat message from the caller to the specified target player(s).
|
||||
/// </summary>
|
||||
/// <param name="caller">The admin or console sending the private message.</param>
|
||||
/// <param name="command">The command input containing target and message.</param>
|
||||
[CommandHelper(2, "<#userid or name> <message>")]
|
||||
[RequiresPermissions("@css/chat")]
|
||||
public void OnAdminPrivateSayCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -92,6 +112,11 @@ public partial class CS2_SimpleAdmin
|
|||
command.ReplyToCommand($" Private message sent!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcasts a center-screen message to all players.
|
||||
/// </summary>
|
||||
/// <param name="caller">The admin or console sending the message.</param>
|
||||
/// <param name="command">The command input containing the message.</param>
|
||||
[CommandHelper(1, "<message>")]
|
||||
[RequiresPermissions("@css/chat")]
|
||||
public void OnAdminCenterSayCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -103,6 +128,11 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.PrintToCenterAll(utf8String.ReplaceColorTags());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a HUD alert message to all players.
|
||||
/// </summary>
|
||||
/// <param name="caller">The admin or console sending the message.</param>
|
||||
/// <param name="command">The command input containing the message.</param>
|
||||
[CommandHelper(1, "<message>")]
|
||||
[RequiresPermissions("@css/chat")]
|
||||
public void OnAdminHudSayCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
|
|||
|
|
@ -12,25 +12,34 @@ using CS2_SimpleAdmin.Managers;
|
|||
using CS2_SimpleAdmin.Menus;
|
||||
using CS2_SimpleAdminApi;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using CounterStrikeSharp.API.ValveConstants.Protobuf;
|
||||
|
||||
using Menu;
|
||||
using Menu.Enums;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace CS2_SimpleAdmin;
|
||||
|
||||
public partial class CS2_SimpleAdmin
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles the command that shows active penalties and warns for the caller or specified player.
|
||||
/// Queries warnings and mute status, formats them locally, and sends the result to caller's chat.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing this command.</param>
|
||||
/// <param name="command">Command input parameters.</param>
|
||||
[CommandHelper(usage: "[#userid or name]", whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
public void OnPenaltiesCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (caller == null || caller.IsValid == false || !caller.UserId.HasValue || Database == null)
|
||||
if (caller == null || caller.IsValid == false || !caller.UserId.HasValue || DatabaseProvider == null)
|
||||
return;
|
||||
|
||||
var userId = caller.UserId.Value;
|
||||
var steamId = caller.SteamID;
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(command.GetArg(1)) && AdminManager.PlayerHasPermissions(new SteamID(caller.SteamID), "@css/kick"))
|
||||
{
|
||||
|
|
@ -53,10 +62,10 @@ public partial class CS2_SimpleAdmin
|
|||
{
|
||||
try
|
||||
{
|
||||
var warns = await WarnManager.GetPlayerWarns(PlayersInfo[userId], false);
|
||||
var warns = await WarnManager.GetPlayerWarns(PlayersInfo[steamId], false);
|
||||
|
||||
// Check if the player is muted
|
||||
var activeMutes = await MuteManager.IsPlayerMuted(PlayersInfo[userId].SteamId.SteamId64.ToString());
|
||||
var activeMutes = await MuteManager.IsPlayerMuted(PlayersInfo[steamId].SteamId.SteamId64.ToString());
|
||||
|
||||
Dictionary<PenaltyType, List<string>> mutesList = new()
|
||||
{
|
||||
|
|
@ -121,16 +130,16 @@ public partial class CS2_SimpleAdmin
|
|||
mutesList[PenaltyType.Silence].Add(_localizer["sa_player_penalty_info_no_active_silence"]);
|
||||
}
|
||||
|
||||
await Server.NextFrameAsync(() =>
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
caller.SendLocalizedMessage(_localizer, "sa_player_penalty_info",
|
||||
[
|
||||
PlayersInfo[userId].Name,
|
||||
PlayersInfo[userId].TotalBans,
|
||||
PlayersInfo[userId].TotalGags,
|
||||
PlayersInfo[userId].TotalMutes,
|
||||
PlayersInfo[userId].TotalSilences,
|
||||
PlayersInfo[userId].TotalWarns,
|
||||
PlayersInfo[steamId].Name,
|
||||
PlayersInfo[steamId].TotalBans,
|
||||
PlayersInfo[steamId].TotalGags,
|
||||
PlayersInfo[steamId].TotalMutes,
|
||||
PlayersInfo[steamId].TotalSilences,
|
||||
PlayersInfo[steamId].TotalWarns,
|
||||
string.Join("\n", mutesList.SelectMany(kvp => kvp.Value)),
|
||||
string.Join("\n", warnsList)
|
||||
]);
|
||||
|
|
@ -143,6 +152,12 @@ public partial class CS2_SimpleAdmin
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles the admin voice listening mode or mutes/unmutes all players' voice.
|
||||
/// Sends confirmation messages accordingly.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing this command.</param>
|
||||
/// <param name="command">Command input parameters.</param>
|
||||
[RequiresPermissions("@css/chat")]
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
public void OnAdminVoiceCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -154,6 +169,7 @@ public partial class CS2_SimpleAdmin
|
|||
{
|
||||
if (command.GetArg(2).ToLower().Equals("muteAll"))
|
||||
{
|
||||
caller.SendLocalizedMessage(_localizer, "sa_admin_voice_mute_all");
|
||||
foreach (var player in Helper.GetValidPlayers().Where(p => p != caller && !AdminManager.PlayerHasPermissions(new SteamID(p.SteamID), "@css/chat")))
|
||||
{
|
||||
player.VoiceFlags = VoiceFlags.Muted;
|
||||
|
|
@ -162,9 +178,10 @@ public partial class CS2_SimpleAdmin
|
|||
|
||||
if (command.GetArg(2).ToLower().Equals("unmuteAll"))
|
||||
{
|
||||
caller.SendLocalizedMessage(_localizer, "sa_admin_voice_unmute_all");
|
||||
foreach (var player in Helper.GetValidPlayers().Where(p => p != caller))
|
||||
{
|
||||
if (PlayerPenaltyManager.GetPlayerPenalties(player.Slot, PenaltyType.Mute).Count == 0)
|
||||
if (PlayerPenaltyManager.GetPlayerPenalties(player.Slot, [PenaltyType.Silence, PenaltyType.Mute]).Count == 0)
|
||||
player.VoiceFlags = VoiceFlags.Normal;
|
||||
}
|
||||
}
|
||||
|
|
@ -172,9 +189,23 @@ public partial class CS2_SimpleAdmin
|
|||
return;
|
||||
}
|
||||
|
||||
var enabled = caller.VoiceFlags.HasFlag(VoiceFlags.ListenAll);
|
||||
var messageKey = enabled
|
||||
? "sa_admin_voice_unlisten_all"
|
||||
: "sa_admin_voice_listen_all";
|
||||
|
||||
caller.SendLocalizedMessage(_localizer, messageKey);
|
||||
caller.VoiceFlags ^= VoiceFlags.ListenAll;
|
||||
|
||||
caller.VoiceFlags = caller.VoiceFlags == VoiceFlags.All ? VoiceFlags.Normal : VoiceFlags.All;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the admin menu for the caller.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">Command input parameters.</param>
|
||||
|
||||
[RequiresPermissions("@css/generic")]
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
public void OnAdminCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -185,6 +216,12 @@ public partial class CS2_SimpleAdmin
|
|||
AdminMenu.OpenMenu(caller);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays admin help text read from a file.
|
||||
/// Outputs lines one at a time as replies to the command.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">Command input parameters.</param>
|
||||
[RequiresPermissions("@css/generic")]
|
||||
public void OnAdminHelpCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
|
|
@ -196,12 +233,16 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles adding a new admin with specified SteamID, name, flags, immunity, and duration.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">Command input parameters.</param>
|
||||
[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 (DatabaseProvider == null) return;
|
||||
|
||||
if (!Helper.ValidateSteamId(command.GetArg(1), out var steamId) || steamId == null)
|
||||
{
|
||||
|
|
@ -232,9 +273,20 @@ public partial class CS2_SimpleAdmin
|
|||
AddAdmin(caller, steamid, name, flags, immunity, time, globalAdmin, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds admin permissions and groups for a player.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="steamid">SteamID as string identifying the player.</param>
|
||||
/// <param name="name">Player's name.</param>
|
||||
/// <param name="flags">Comma-separated admin flags/groups.</param>
|
||||
/// <param name="immunity">Admin immunity level.</param>
|
||||
/// <param name="time">Duration of permission (default 0 = permanent).</param>
|
||||
/// <param name="globalAdmin">Whether admin is global.</param>
|
||||
/// <param name="command">Optional command info for confirmation messages.</param>
|
||||
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;
|
||||
if (DatabaseProvider == null) return;
|
||||
|
||||
var flagsList = flags.Split(',').Select(flag => flag.Trim()).ToList();
|
||||
_ = Instance.PermissionManager.AddAdminBySteamId(steamid, name, flagsList, immunity, time, globalAdmin);
|
||||
|
|
@ -250,11 +302,16 @@ public partial class CS2_SimpleAdmin
|
|||
Server.PrintToConsole(msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles removing an admin's flags and groups by SteamID.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">Command input parameters.</param>
|
||||
[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 (DatabaseProvider == null) return;
|
||||
|
||||
if (!Helper.ValidateSteamId(command.GetArg(1), out var steamId) || steamId == null)
|
||||
{
|
||||
|
|
@ -267,9 +324,16 @@ public partial class CS2_SimpleAdmin
|
|||
RemoveAdmin(caller, steamId.SteamId64.ToString(), globalDelete, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes admin permissions and groups for a player.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="steamid">SteamID as string identifying the player.</param>
|
||||
/// <param name="globalDelete">Whether to delete globally.</param>
|
||||
/// <param name="command">Optional command info.</param>
|
||||
public void RemoveAdmin(CCSPlayerController? caller, string steamid, bool globalDelete = false, CommandInfo? command = null)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
_ = PermissionManager.DeleteAdminBySteamId(steamid, globalDelete);
|
||||
|
||||
AddTimer(2, () =>
|
||||
|
|
@ -296,11 +360,16 @@ public partial class CS2_SimpleAdmin
|
|||
Server.PrintToConsole(msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new admin group with specified flags and immunity settings.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">Command input parameters.</param>
|
||||
[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 (DatabaseProvider == null) return;
|
||||
|
||||
if (!command.GetArg(1).StartsWith("#"))
|
||||
{
|
||||
|
|
@ -322,9 +391,18 @@ public partial class CS2_SimpleAdmin
|
|||
AddGroup(caller, groupName, flags, immunity, globalGroup, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new admin group with specified flags and immunity level.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="name">Group name (prefix with #).</param>
|
||||
/// <param name="flags">Comma-separated flags/groups string.</param>
|
||||
/// <param name="immunity">Immunity level.</param>
|
||||
/// <param name="globalGroup">Whether group is global.</param>
|
||||
/// <param name="command">Optional command info.</param>
|
||||
private static void AddGroup(CCSPlayerController? caller, string name, string flags, int immunity, bool globalGroup, CommandInfo? command = null)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
|
||||
var flagsList = flags.Split(',').Select(flag => flag.Trim()).ToList();
|
||||
_ = Instance.PermissionManager.AddGroup(name, flagsList, immunity, globalGroup);
|
||||
|
|
@ -340,11 +418,16 @@ public partial class CS2_SimpleAdmin
|
|||
Server.PrintToConsole(msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles removing a group by name.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">Command input parameters.</param>
|
||||
[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 (DatabaseProvider == null) return;
|
||||
|
||||
if (!command.GetArg(1).StartsWith($"#"))
|
||||
{
|
||||
|
|
@ -357,9 +440,15 @@ public partial class CS2_SimpleAdmin
|
|||
RemoveGroup(caller, groupName, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a group.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="name">The group name to remove.</param>
|
||||
/// <param name="command">Optional command info for confirmation.</param>
|
||||
private void RemoveGroup(CCSPlayerController? caller, string name, CommandInfo? command = null)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
_ = PermissionManager.DeleteGroup(name);
|
||||
|
||||
AddTimer(2, () =>
|
||||
|
|
@ -378,58 +467,74 @@ public partial class CS2_SimpleAdmin
|
|||
Server.PrintToConsole(msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reloads admin and group data from database and json files.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the reload command.</param>
|
||||
/// <param name="command">Command input parameters.</param>
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
[RequiresPermissions("@css/root")]
|
||||
public void OnRelAdminCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
|
||||
if (DatabaseProvider == null) return;
|
||||
ReloadAdmins(caller);
|
||||
|
||||
command.ReplyToCommand("Reloaded sql admins and groups");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reloads bans cache.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the reload command.</param>
|
||||
/// <param name="command">Command input parameters.</param>
|
||||
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
[RequiresPermissions("@css/root")]
|
||||
public void OnRelBans(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
|
||||
_ = Instance.CacheManager?.ForceReInitializeCacheAsync();
|
||||
command.ReplyToCommand("Reloaded bans");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reloads admin data asynchronously and updates admin caches.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the reload command.</param>
|
||||
public void ReloadAdmins(CCSPlayerController? caller)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
|
||||
if (!Config.IsCSSPanel)
|
||||
Task.Run(async () =>
|
||||
{
|
||||
Task.Run(async () =>
|
||||
await PermissionManager.CreateGroupsJsonFile();
|
||||
await PermissionManager.CreateAdminsJsonFile();
|
||||
|
||||
var adminsFile = await File.ReadAllTextAsync(Instance.ModuleDirectory + "/data/admins.json");
|
||||
var groupsFile = await File.ReadAllTextAsync(Instance.ModuleDirectory + "/data/groups.json");
|
||||
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
await PermissionManager.CreateGroupsJsonFile();
|
||||
await PermissionManager.CreateAdminsJsonFile();
|
||||
|
||||
var adminsFile = await File.ReadAllTextAsync(Instance.ModuleDirectory + "/data/admins.json");
|
||||
var groupsFile = await File.ReadAllTextAsync(Instance.ModuleDirectory + "/data/groups.json");
|
||||
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
AddTimer(1, () =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(adminsFile))
|
||||
AddTimer(1.3f, () => AdminManager.LoadAdminData(ModuleDirectory + "/data/admins.json"));
|
||||
AddTimer(2.0f, () => AdminManager.LoadAdminData(ModuleDirectory + "/data/admins.json"));
|
||||
if (!string.IsNullOrEmpty(groupsFile))
|
||||
AddTimer(2.5f, () => AdminManager.LoadAdminGroups(ModuleDirectory + "/data/groups.json"));
|
||||
AddTimer(3.0f, () => AdminManager.LoadAdminGroups(ModuleDirectory + "/data/groups.json"));
|
||||
if (!string.IsNullOrEmpty(adminsFile))
|
||||
AddTimer(3.5f, () => AdminManager.LoadAdminData(ModuleDirectory + "/data/admins.json"));
|
||||
AddTimer(4.0f, () => AdminManager.LoadAdminData(ModuleDirectory + "/data/admins.json"));
|
||||
|
||||
_logger?.LogInformation("Loaded admins!");
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
_ = PermissionManager.GiveAllFlags();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles player visibility on the server, hiding or revealing them.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the hide command.</param>
|
||||
/// <param name="command">Command input parameters.</param>
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
[RequiresPermissions("@css/kick")]
|
||||
public void OnHideCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -442,6 +547,9 @@ public partial class CS2_SimpleAdmin
|
|||
{
|
||||
SilentPlayers.Remove(caller.Slot);
|
||||
caller.PrintToChat($"You aren't hidden now!");
|
||||
if (caller.TeamNum <= 1)
|
||||
caller.ChangeTeam(CsTeam.Spectator);
|
||||
SimpleAdminApi?.OnAdminToggleSilentEvent(caller.Slot, false);
|
||||
caller.ChangeTeam(CsTeam.Spectator);
|
||||
Server.ExecuteCommand($"mm_removeexcludeslot {caller.Slot}");
|
||||
}
|
||||
|
|
@ -456,10 +564,20 @@ public partial class CS2_SimpleAdmin
|
|||
AddTimer(1.0f, () => { Server.NextWorldUpdateAsync(() => caller.ChangeTeam(CsTeam.Spectator)); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
AddTimer(1.4f, () => { Server.NextWorldUpdateAsync(() => caller.ChangeTeam(CsTeam.None)); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
caller.PrintToChat($"You are hidden now!");
|
||||
if (caller.TeamNum > 1)
|
||||
AddTimer(0.15f, () => { Server.NextWorldUpdate(() => caller.ChangeTeam(CsTeam.Spectator)); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
AddTimer(0.26f, () => { Server.NextWorldUpdate(() => caller.ChangeTeam(CsTeam.None)); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
AddTimer(0.50f, () => { Server.NextWorldUpdate(() => Server.ExecuteCommand("sv_disable_teamselect_menu 0")); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
SimpleAdminApi?.OnAdminToggleSilentEvent(caller.Slot, true);
|
||||
AddTimer(2.0f, () => { Server.NextWorldUpdateAsync(() => Server.ExecuteCommand("sv_disable_teamselect_menu 0")); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles penalty notification visibility to admins.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player toggling notification visibility.</param>
|
||||
/// <param name="command">Command input parameters.</param>
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
[RequiresPermissions("@css/kick")]
|
||||
public void OnHideCommsCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -479,11 +597,16 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays detailed information about target players, including admin groups, permissions, and penalties.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">Command input parameters including targets.</param>
|
||||
[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;
|
||||
if (DatabaseProvider == null) return;
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
|
|
@ -497,39 +620,41 @@ public partial class CS2_SimpleAdmin
|
|||
if (!player.UserId.HasValue) return;
|
||||
if (!caller!.CanTarget(player)) return;
|
||||
|
||||
var playerInfo = PlayersInfo[player.UserId.Value];
|
||||
var playerInfo = PlayersInfo[player.SteamID];
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Server.NextFrameAsync(() =>
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
Action<string> printMethod = caller == null ? Server.PrintToConsole : caller.PrintToConsole;
|
||||
|
||||
printMethod($"--------- INFO ABOUT \"{playerInfo.Name}\" ---------");
|
||||
var adminData = AdminManager.GetPlayerAdminData(new SteamID(player.SteamID));
|
||||
|
||||
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)
|
||||
if (adminData != null)
|
||||
{
|
||||
printMethod($"• SteamID2: \"{playerInfo.SteamId.SteamId2}\"");
|
||||
printMethod($"• Community link: \"{playerInfo.SteamId.ToCommunityUrl()}\"");
|
||||
var flags = string.Join(",", adminData._flags);
|
||||
var groups = string.Join(",", adminData.Groups);
|
||||
|
||||
printMethod($"• Groups/Flags: \"{groups}{flags}\"");
|
||||
}
|
||||
printMethod($"• SteamID2: \"{playerInfo.SteamId.SteamId2}\"");
|
||||
printMethod($"• Community link: \"{playerInfo.SteamId.ToCommunityUrl()}\"");
|
||||
if (playerInfo.IpAddress != null && AdminManager.PlayerHasPermissions(new SteamID(caller!.SteamID), "@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($"• Total Bans: \"{playerInfo.TotalBans}\"");
|
||||
printMethod($"• Total Gags: \"{playerInfo.TotalGags}\"");
|
||||
printMethod($"• Total Mutes: \"{playerInfo.TotalMutes}\"");
|
||||
printMethod($"• Total Silences: \"{playerInfo.TotalSilences}\"");
|
||||
printMethod($"• Total Warns: \"{playerInfo.TotalWarns}\"");
|
||||
|
||||
var chunkedAccounts = playerInfo.AccountsAssociated.ChunkBy(3).ToList();
|
||||
foreach (var chunk in chunkedAccounts)
|
||||
printMethod($"• Associated Accounts: \"{string.Join(", ", chunk.Select(a => $"{a.PlayerName} ({a.SteamId})"))}\"");
|
||||
}
|
||||
var chunkedAccounts = playerInfo.AccountsAssociated.ChunkBy(3).ToList();
|
||||
foreach (var chunk in chunkedAccounts)
|
||||
printMethod($"• Associated Accounts: \"{string.Join(", ", chunk.Select(a => $"{a.PlayerName} ({a.SteamId})"))}\"");
|
||||
|
||||
printMethod($"--------- END INFO ABOUT \"{player.PlayerName}\" ---------");
|
||||
});
|
||||
|
|
@ -537,6 +662,11 @@ public partial class CS2_SimpleAdmin
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays a menu with disconnected players, allowing the caller to apply penalties like ban, mute, gag, or silence.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">The command containing parameters.</param>
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
[RequiresPermissions("@css/kick")]
|
||||
public void OnDisconnectedCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -639,11 +769,17 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays the warning menu for a player specified by a command argument,
|
||||
/// showing active and past warns with options to remove them.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">The command containing target player identifier.</param>
|
||||
[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;
|
||||
if (DatabaseProvider == null || _localizer == null || caller == null) return;
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
|
|
@ -656,14 +792,13 @@ public partial class CS2_SimpleAdmin
|
|||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (!player.UserId.HasValue) return;
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
var userId = player.UserId.Value;
|
||||
var steamId = player.SteamID;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var warnsList = await WarnManager.GetPlayerWarns(PlayersInfo[userId], false);
|
||||
var warnsList = await WarnManager.GetPlayerWarns(PlayersInfo[steamId], false);
|
||||
var sortedWarns = warnsList
|
||||
.OrderBy(warn => (string)warn.status == "ACTIVE" ? 0 : 1)
|
||||
.ThenByDescending(warn => (int)warn.id)
|
||||
|
|
@ -685,7 +820,7 @@ public partial class CS2_SimpleAdmin
|
|||
|
||||
optionMap[i++] = () =>
|
||||
{
|
||||
_ = WarnManager.UnwarnPlayer(PlayersInfo[userId], (int)w.id);
|
||||
_ = WarnManager.UnwarnPlayer(PlayersInfo[steamId], (int)w.id);
|
||||
player.PrintToChat(_localizer["sa_admin_warns_unwarn", player.PlayerName, (string)w.reason]);
|
||||
};
|
||||
}
|
||||
|
|
@ -718,8 +853,14 @@ public partial class CS2_SimpleAdmin
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lists players currently connected to the server with options to output JSON or filter duplicate IPs.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command or null for console.</param>
|
||||
/// <param name="command">The command containing output options.</param>
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
[RequiresPermissions("@css/generic")]
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
|
||||
public void OnPlayersCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var isJson = command.GetArg(1).ToLower().Equals("-json");
|
||||
|
|
@ -758,7 +899,7 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
else
|
||||
{
|
||||
var playersJson = JsonConvert.SerializeObject(playersToTarget.Select(player =>
|
||||
var playersJson = JsonSerializer.Serialize(playersToTarget.Select(player =>
|
||||
{
|
||||
var matchStats = player.ActionTrackingServices?.MatchStats;
|
||||
|
||||
|
|
@ -787,6 +928,11 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Issues a kick to one or multiple players specified in the command arguments.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the kick command.</param>
|
||||
/// <param name="command">The command with target player(s) and optional reason.</param>
|
||||
[RequiresPermissions("@css/kick")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnKickCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -824,6 +970,15 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Kicks a specified player immediately with reason, notifying the server and logging the action.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the kick.</param>
|
||||
/// <param name="player">The player to be kicked.</param>
|
||||
/// <param name="reason">The reason for the kick.</param>
|
||||
/// <param name="callerName">Optional name of the kick issuer for notifications.</param>
|
||||
/// <param name="command">Optional command for logging.</param>
|
||||
public void Kick(CCSPlayerController? caller, CCSPlayerController player, string? reason = "Unknown", string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!player.IsValid) return;
|
||||
|
|
@ -834,8 +989,9 @@ public partial class CS2_SimpleAdmin
|
|||
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
reason ??= _localizer?["sa_unknown"] ?? "Unknown";
|
||||
|
||||
var playerInfo = PlayersInfo[player.UserId.Value];
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
|
||||
var playerInfo = PlayersInfo[player.SteamID];
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
|
||||
|
||||
// Determine message keys and arguments for the kick notification
|
||||
var (messageKey, activityMessageKey, centerArgs, adminActivityArgs) =
|
||||
|
|
@ -865,6 +1021,11 @@ public partial class CS2_SimpleAdmin
|
|||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Kick, reason, -1, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the current map to the specified map name or workshop map ID.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the map change.</param>
|
||||
/// <param name="command">The command containing the map name or ID.</param>
|
||||
[RequiresPermissions("@css/changemap")]
|
||||
[CommandHelper(minArgs: 1, usage: "<mapname>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnMapCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -873,6 +1034,12 @@ public partial class CS2_SimpleAdmin
|
|||
ChangeMap(caller, map, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes to a specified map, validating it or handling workshop maps, and notifying the server and admins.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the change.</param>
|
||||
/// <param name="map">The map name or identifier.</param>
|
||||
/// <param name="command">Optional command object for logging and replies.</param>
|
||||
public void ChangeMap(CCSPlayerController? caller, string map, CommandInfo? command = null)
|
||||
{
|
||||
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
|
|
@ -931,6 +1098,11 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, command?.GetCommandString ?? $"css_map {map}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the current map to a workshop map specified by name or ID.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">The command containing the workshop map identifier.</param>
|
||||
[CommandHelper(1, "<name or id>")]
|
||||
[RequiresPermissions("@css/changemap")]
|
||||
public void OnWorkshopMapCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -939,6 +1111,12 @@ public partial class CS2_SimpleAdmin
|
|||
ChangeWorkshopMap(caller, map, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes to a specified workshop map by name or ID and notifies admins.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="map">The workshop map identifier.</param>
|
||||
/// <param name="command">Optional command for logging.</param>
|
||||
public void ChangeWorkshopMap(CCSPlayerController? caller, string map, CommandInfo? command = null)
|
||||
{
|
||||
map = map.ToLower();
|
||||
|
|
@ -968,6 +1146,11 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, command?.GetCommandString ?? $"css_wsmap {map}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows changing a console variable's value.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">The command with cvar name and value.</param>
|
||||
[CommandHelper(2, "<cvar> <value>")]
|
||||
[RequiresPermissions("@css/cvar")]
|
||||
public void OnCvarCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -988,28 +1171,33 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
|
||||
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}.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes an RCON command on the server.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">The command string to execute via RCON.</param>
|
||||
[CommandHelper(1, "<command>")]
|
||||
[RequiresPermissions("@css/rcon")]
|
||||
public void OnRconCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "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}).");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restarts the game.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player or console initiating the restart.</param>
|
||||
/// <param name="command">The restart command info.</param>
|
||||
[RequiresPermissions("@css/generic")]
|
||||
[CommandHelper(minArgs: 0, usage: "", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnRestartCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -1017,6 +1205,11 @@ public partial class CS2_SimpleAdmin
|
|||
RestartGame(caller);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens plugin manager menu for the caller with options to load or unload plugins.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player opening the plugin manager.</param>
|
||||
/// <param name="commandInfo">The command parameters.</param>
|
||||
[RequiresPermissions("@css/root")]
|
||||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
public void OnPluginManagerCommand(CCSPlayerController? caller, CommandInfo commandInfo)
|
||||
|
|
@ -1108,6 +1301,10 @@ public partial class CS2_SimpleAdmin
|
|||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restarts the game process by issuing the restart game command to the server and logging the action.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin or console requesting the restart.</param>
|
||||
public static void RestartGame(CCSPlayerController? admin)
|
||||
{
|
||||
Helper.LogCommand(admin, "css_restartgame");
|
||||
|
|
|
|||
|
|
@ -11,11 +11,16 @@ namespace CS2_SimpleAdmin;
|
|||
|
||||
public partial class CS2_SimpleAdmin
|
||||
{
|
||||
/// <summary>
|
||||
/// Processes the 'gag' command, applying a muted penalty to target players with optional time and reason.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the gag command or null for console.</param>
|
||||
/// <param name="command">The command input containing targets, time, and reason.</param>
|
||||
[RequiresPermissions("@css/chat")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnGagCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
|
||||
var targets = GetTarget(command);
|
||||
|
|
@ -49,9 +54,19 @@ public partial class CS2_SimpleAdmin
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the gag penalty logic to an individual player, performing permission checks, notification, and logging.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the gag.</param>
|
||||
/// <param name="player">The player to gag.</param>
|
||||
/// <param name="time">Duration of the gag in minutes, 0 is permanent.</param>
|
||||
/// <param name="reason">Reason for the gag.</param>
|
||||
/// <param name="callerName">Optional caller name for notifications.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
/// <param name="silent">If true, suppresses logging notifications.</param>
|
||||
internal void Gag(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, CommandInfo? command = null, bool silent = false)
|
||||
{
|
||||
if (Database == null || !player.IsValid || !player.UserId.HasValue) return;
|
||||
if (DatabaseProvider == null || !player.IsValid || !player.UserId.HasValue) return;
|
||||
if (!caller.CanTarget(player)) return;
|
||||
if (!CheckValidMute(caller, time)) return;
|
||||
|
||||
|
|
@ -59,14 +74,18 @@ public partial class CS2_SimpleAdmin
|
|||
callerName ??= caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
|
||||
// Get player and admin information
|
||||
var playerInfo = PlayersInfo[player.UserId.Value];
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
var playerInfo = PlayersInfo[player.SteamID];
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
|
||||
|
||||
// Asynchronously handle gag logic
|
||||
Task.Run(async () =>
|
||||
{
|
||||
int? penaltyId = await MuteManager.MutePlayer(playerInfo, adminInfo, reason, time);
|
||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Gag, reason, time, penaltyId);
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Gag, reason, time,
|
||||
penaltyId);
|
||||
});
|
||||
});
|
||||
|
||||
// Add penalty to the player's penalty manager
|
||||
|
|
@ -91,7 +110,7 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
|
||||
// Increment the player's total gags count
|
||||
PlayersInfo[player.UserId.Value].TotalGags++;
|
||||
PlayersInfo[player.SteamID].TotalGags++;
|
||||
|
||||
// Log the gag command and send Discord notification
|
||||
if (!silent)
|
||||
|
|
@ -105,16 +124,23 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Gag, _localizer);
|
||||
}
|
||||
|
||||
internal void AddGag(CCSPlayerController? caller, SteamID steamid, int time, string reason, MuteManager? muteManager = null)
|
||||
/// <summary>
|
||||
/// Adds a gag penalty to a player identified by SteamID, supporting offline players.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command or null for console.</param>
|
||||
/// <param name="steamid">SteamID of the target player.</param>
|
||||
/// <param name="time">Duration in minutes (0 for permanent).</param>
|
||||
/// <param name="reason">Reason for the gag.</param>
|
||||
internal void AddGag(CCSPlayerController? caller, SteamID steamid, int time, string reason)
|
||||
{
|
||||
// Set default caller name if not provided
|
||||
var callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
||||
? caller.PlayerName
|
||||
: (_localizer?["sa_console"] ?? "Console");
|
||||
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
|
||||
|
||||
var player = Helper.GetPlayerFromSteamid64(steamid.SteamId64.ToString());
|
||||
var player = Helper.GetPlayerFromSteamid64(steamid.SteamId64);
|
||||
|
||||
if (player != null && player.IsValid)
|
||||
{
|
||||
|
|
@ -131,19 +157,28 @@ public partial class CS2_SimpleAdmin
|
|||
// Asynchronous ban operation if player is not online or not found
|
||||
Task.Run(async () =>
|
||||
{
|
||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid.SteamId64.ToString(), adminInfo, reason, time, 3);
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Gag, reason, time, penaltyId);
|
||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid.SteamId64, adminInfo, reason, time, 3);
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Gag, reason, time,
|
||||
penaltyId);
|
||||
});
|
||||
});
|
||||
|
||||
Helper.SendDiscordPenaltyMessage(caller, steamid.SteamId64.ToString(), reason, time, PenaltyType.Gag, _localizer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the 'addgag' command, which adds a gag penalty to a player specified by SteamID.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command or null for console.</param>
|
||||
/// <param name="command">Command input that includes SteamID, optional time, and reason.</param>
|
||||
[RequiresPermissions("@css/chat")]
|
||||
[CommandHelper(minArgs: 1, usage: "<steamid> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnAddGagCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
|
||||
// Set caller name
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
|
|
@ -158,7 +193,7 @@ public partial class CS2_SimpleAdmin
|
|||
return;
|
||||
}
|
||||
|
||||
var steamid = steamId.SteamId64.ToString();
|
||||
var steamid = steamId.SteamId64;
|
||||
var reason = command.ArgCount >= 3
|
||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
||||
|
|
@ -169,7 +204,7 @@ public partial class CS2_SimpleAdmin
|
|||
if (!CheckValidMute(caller, time)) return;
|
||||
|
||||
// Get player and admin info
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
|
||||
|
||||
// Attempt to match player based on SteamID
|
||||
var player = Helper.GetPlayerFromSteamid64(steamid);
|
||||
|
|
@ -191,10 +226,14 @@ public partial class CS2_SimpleAdmin
|
|||
Task.Run(async () =>
|
||||
{
|
||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid, adminInfo, reason, time);
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Gag, reason, time, penaltyId);
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Gag, reason, time,
|
||||
penaltyId);
|
||||
});
|
||||
});
|
||||
|
||||
Helper.SendDiscordPenaltyMessage(caller, steamid, reason, time, PenaltyType.Gag, _localizer);
|
||||
Helper.SendDiscordPenaltyMessage(caller, steamid.ToString(), reason, time, PenaltyType.Gag, _localizer);
|
||||
|
||||
command.ReplyToCommand($"Player with steamid {steamid} is not online. Gag has been added offline.");
|
||||
}
|
||||
|
|
@ -203,11 +242,16 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles removing a gag penalty ('ungag') of a player, either by SteamID or pattern match.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the ungag command or null for console.</param>
|
||||
/// <param name="command">Command input containing SteamID or player name and optional reason.</param>
|
||||
[RequiresPermissions("@css/chat")]
|
||||
[CommandHelper(minArgs: 1, usage: "<steamid or name> [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnUngagCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
|
||||
var callerSteamId = caller?.SteamID.ToString() ?? _localizer?["sa_console"] ?? "Console";
|
||||
var pattern = command.GetArg(1);
|
||||
|
|
@ -228,7 +272,7 @@ public partial class CS2_SimpleAdmin
|
|||
// Check if pattern is a valid SteamID64
|
||||
if (Helper.ValidateSteamId(pattern, out var steamId) && steamId != null)
|
||||
{
|
||||
var player = Helper.GetPlayerFromSteamid64(steamId.SteamId64.ToString());
|
||||
var player = Helper.GetPlayerFromSteamid64(steamId.SteamId64);
|
||||
|
||||
if (player != null && player.IsValid)
|
||||
{
|
||||
|
|
@ -252,8 +296,8 @@ public partial class CS2_SimpleAdmin
|
|||
{
|
||||
PlayerPenaltyManager.RemovePenaltiesByType(namePlayer.Slot, PenaltyType.Gag);
|
||||
|
||||
if (namePlayer.UserId.HasValue && PlayersInfo[namePlayer.UserId.Value].TotalGags > 0)
|
||||
PlayersInfo[namePlayer.UserId.Value].TotalGags--;
|
||||
if (namePlayer.UserId.HasValue && PlayersInfo[namePlayer.SteamID].TotalGags > 0)
|
||||
PlayersInfo[namePlayer.SteamID].TotalGags--;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
|
|
@ -273,11 +317,16 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the 'mute' command, applying a voice mute penalty to target players with optional time and reason.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the mute command or null for console.</param>
|
||||
/// <param name="command">The command input containing targets, time, and reason.</param>
|
||||
[RequiresPermissions("@css/chat")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnMuteCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
|
||||
var targets = GetTarget(command);
|
||||
|
|
@ -311,9 +360,19 @@ public partial class CS2_SimpleAdmin
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the mute penalty logic to an individual player, handling permissions, notifications, logging, and countdown timers.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the mute.</param>
|
||||
/// <param name="player">The player to mute.</param>
|
||||
/// <param name="time">Duration in minutes, 0 indicates permanent mute.</param>
|
||||
/// <param name="reason">Reason for the mute.</param>
|
||||
/// <param name="callerName">Optional caller name for notification messages.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
/// <param name="silent">If true, suppresses some logging.</param>
|
||||
internal void Mute(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, CommandInfo? command = null, bool silent = false)
|
||||
{
|
||||
if (Database == null || !player.IsValid || !player.UserId.HasValue) return;
|
||||
if (DatabaseProvider == null || !player.IsValid || !player.UserId.HasValue) return;
|
||||
if (!caller.CanTarget(player)) return;
|
||||
if (!CheckValidMute(caller, time)) return;
|
||||
|
||||
|
|
@ -321,8 +380,8 @@ public partial class CS2_SimpleAdmin
|
|||
callerName ??= caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
|
||||
// Get player and admin information
|
||||
var playerInfo = PlayersInfo[player.UserId.Value];
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
var playerInfo = PlayersInfo[player.SteamID];
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
|
||||
|
||||
// Set player's voice flags to muted
|
||||
if (!player.VoiceFlags.HasFlag(VoiceFlags.Muted))
|
||||
|
|
@ -332,7 +391,11 @@ public partial class CS2_SimpleAdmin
|
|||
Task.Run(async () =>
|
||||
{
|
||||
int? penaltyId = await MuteManager.MutePlayer(playerInfo, adminInfo, reason, time, 1);
|
||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Mute, reason, time, penaltyId);
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Mute, reason, time,
|
||||
penaltyId);
|
||||
});
|
||||
});
|
||||
|
||||
// Add penalty to the player's penalty manager
|
||||
|
|
@ -357,7 +420,7 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
|
||||
// Increment the player's total mutes count
|
||||
PlayersInfo[player.UserId.Value].TotalMutes++;
|
||||
PlayersInfo[player.SteamID].TotalMutes++;
|
||||
|
||||
// Log the mute command and send Discord notification
|
||||
if (!silent)
|
||||
|
|
@ -371,11 +434,16 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Mute, _localizer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the 'addmute' command that adds a mute penalty to a player specified by SteamID.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command or null for console.</param>
|
||||
/// <param name="command">Command input includes SteamID, optional time, and reason.</param>
|
||||
[RequiresPermissions("@css/chat")]
|
||||
[CommandHelper(minArgs: 1, usage: "<steamid> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnAddMuteCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
|
||||
// Set caller name
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
|
|
@ -390,7 +458,7 @@ public partial class CS2_SimpleAdmin
|
|||
return;
|
||||
}
|
||||
|
||||
var steamid = steamId.SteamId64.ToString();
|
||||
var steamid = steamId.SteamId64;
|
||||
var reason = command.ArgCount >= 3
|
||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
||||
|
|
@ -401,7 +469,7 @@ public partial class CS2_SimpleAdmin
|
|||
if (!CheckValidMute(caller, time)) return;
|
||||
|
||||
// Get player and admin info
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
|
||||
|
||||
// Attempt to match player based on SteamID
|
||||
var player = Helper.GetPlayerFromSteamid64(steamid);
|
||||
|
|
@ -423,10 +491,14 @@ public partial class CS2_SimpleAdmin
|
|||
Task.Run(async () =>
|
||||
{
|
||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 1);
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Mute, reason, time, penaltyId);
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Mute, reason, time,
|
||||
penaltyId);
|
||||
});
|
||||
});
|
||||
|
||||
Helper.SendDiscordPenaltyMessage(caller, steamid, reason, time, PenaltyType.Mute, _localizer);
|
||||
Helper.SendDiscordPenaltyMessage(caller, steamid.ToString(), reason, time, PenaltyType.Mute, _localizer);
|
||||
|
||||
command.ReplyToCommand($"Player with steamid {steamid} is not online. Mute has been added offline.");
|
||||
}
|
||||
|
|
@ -435,6 +507,14 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously adds a mute penalty to a player by Steam ID. Handles both online and offline players.
|
||||
/// </summary>
|
||||
/// <param name="caller">The admin/player issuing the mute.</param>
|
||||
/// <param name="steamid">The Steam ID of the player to mute.</param>
|
||||
/// <param name="time">Duration of the mute in minutes.</param>
|
||||
/// <param name="reason">Reason for the mute.</param>
|
||||
/// <param name="muteManager">Optional mute manager instance for handling database ops.</param>
|
||||
internal void AddMute(CCSPlayerController? caller, SteamID steamid, int time, string reason, MuteManager? muteManager = null)
|
||||
{
|
||||
// Set default caller name if not provided
|
||||
|
|
@ -442,9 +522,9 @@ public partial class CS2_SimpleAdmin
|
|||
? caller.PlayerName
|
||||
: (_localizer?["sa_console"] ?? "Console");
|
||||
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
|
||||
|
||||
var player = Helper.GetPlayerFromSteamid64(steamid.SteamId64.ToString());
|
||||
var player = Helper.GetPlayerFromSteamid64(steamid.SteamId64);
|
||||
|
||||
if (player != null && player.IsValid)
|
||||
{
|
||||
|
|
@ -461,19 +541,29 @@ public partial class CS2_SimpleAdmin
|
|||
// Asynchronous ban operation if player is not online or not found
|
||||
Task.Run(async () =>
|
||||
{
|
||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid.SteamId64.ToString(), adminInfo, reason, time, 1);
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Mute, reason, time, penaltyId);
|
||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid.SteamId64, adminInfo, reason, time, 1);
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Mute, reason, time,
|
||||
penaltyId);
|
||||
});
|
||||
});
|
||||
|
||||
Helper.SendDiscordPenaltyMessage(caller, steamid.SteamId64.ToString(), reason, time, PenaltyType.Mute, _localizer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the unmute command - removes mute penalty from player identified by SteamID or name.
|
||||
/// Can target both online and offline players.
|
||||
/// </summary>
|
||||
/// <param name="caller">The admin/player issuing the unmute.</param>
|
||||
/// <param name="command">The command arguments including target identifier and optional reason.</param>
|
||||
[RequiresPermissions("@css/chat")]
|
||||
[CommandHelper(minArgs: 1, usage: "<steamid or name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnUnmuteCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
|
||||
var callerSteamId = caller?.SteamID.ToString() ?? _localizer?["sa_console"] ?? "Console";
|
||||
var pattern = command.GetArg(1);
|
||||
|
|
@ -494,7 +584,7 @@ public partial class CS2_SimpleAdmin
|
|||
// Check if pattern is a valid SteamID64
|
||||
if (Helper.ValidateSteamId(pattern, out var steamId) && steamId != null)
|
||||
{
|
||||
var player = Helper.GetPlayerFromSteamid64(steamId.SteamId64.ToString());
|
||||
var player = Helper.GetPlayerFromSteamid64(steamId.SteamId64);
|
||||
|
||||
if (player != null && player.IsValid)
|
||||
{
|
||||
|
|
@ -522,8 +612,8 @@ public partial class CS2_SimpleAdmin
|
|||
if (namePlayer.VoiceFlags.HasFlag(VoiceFlags.Muted))
|
||||
namePlayer.VoiceFlags &= ~VoiceFlags.Muted;
|
||||
|
||||
if (namePlayer.UserId.HasValue && PlayersInfo[namePlayer.UserId.Value].TotalMutes > 0)
|
||||
PlayersInfo[namePlayer.UserId.Value].TotalMutes--;
|
||||
if (namePlayer.UserId.HasValue && PlayersInfo[namePlayer.SteamID].TotalMutes > 0)
|
||||
PlayersInfo[namePlayer.SteamID].TotalMutes--;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
|
|
@ -543,11 +633,17 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Issue a 'silence' penalty to a player - disables voice communication.
|
||||
/// Handles online and offline players, with duration and reason specified.
|
||||
/// </summary>
|
||||
/// <param name="caller">The admin/player issuing the silence.</param>
|
||||
/// <param name="command">Command containing target, duration, and optional reason.</param>
|
||||
[RequiresPermissions("@css/chat")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnSilenceCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
|
||||
var targets = GetTarget(command);
|
||||
|
|
@ -581,9 +677,19 @@ public partial class CS2_SimpleAdmin
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies silence logical processing for a player - updates database and notifies.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin/player applying the silence.</param>
|
||||
/// <param name="player">Target player.</param>
|
||||
/// <param name="time">Duration of silence.</param>
|
||||
/// <param name="reason">Reason for silence.</param>
|
||||
/// <param name="callerName">Optional name of silent admin or console.</param>
|
||||
/// <param name="command">Optional command details for logging.</param>
|
||||
/// <param name="silent">If true, suppresses logging notifications.</param>
|
||||
internal void Silence(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, CommandInfo? command = null, bool silent = false)
|
||||
{
|
||||
if (Database == null || !player.IsValid || !player.UserId.HasValue) return;
|
||||
if (DatabaseProvider == null || !player.IsValid || !player.UserId.HasValue) return;
|
||||
if (!caller.CanTarget(player)) return;
|
||||
if (!CheckValidMute(caller, time)) return;
|
||||
|
||||
|
|
@ -591,8 +697,8 @@ public partial class CS2_SimpleAdmin
|
|||
callerName ??= caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
|
||||
// Get player and admin information
|
||||
var playerInfo = PlayersInfo[player.UserId.Value];
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
var playerInfo = PlayersInfo[player.SteamID];
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
|
||||
|
||||
// Set player's voice flags to muted
|
||||
if (!player.VoiceFlags.HasFlag(VoiceFlags.Muted))
|
||||
|
|
@ -601,8 +707,12 @@ public partial class CS2_SimpleAdmin
|
|||
// Asynchronously handle silence logic
|
||||
Task.Run(async () =>
|
||||
{
|
||||
int? penaltyId = await MuteManager.MutePlayer(playerInfo, adminInfo, reason, time, 2); // Assuming 2 is the type for silence
|
||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Silence, reason, time, penaltyId);
|
||||
int? penaltyId = await MuteManager.MutePlayer(playerInfo, adminInfo, reason, time, 2);
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Silence, reason, time,
|
||||
penaltyId);
|
||||
});
|
||||
});
|
||||
|
||||
// Add penalty to the player's penalty manager
|
||||
|
|
@ -628,7 +738,7 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
|
||||
// Increment the player's total silences count
|
||||
PlayersInfo[player.UserId.Value].TotalSilences++;
|
||||
PlayersInfo[player.SteamID].TotalSilences++;
|
||||
|
||||
// Log the silence command and send Discord notification
|
||||
if (!silent)
|
||||
|
|
@ -642,11 +752,17 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Silence, _localizer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the 'AddSilence' command, applying a silence penalty to a player specified by SteamID,
|
||||
/// with support for offline player penalties.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin issuing the command.</param>
|
||||
/// <param name="command">The command input containing SteamID, optional time, and reason.</param>
|
||||
[RequiresPermissions("@css/chat")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnAddSilenceCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
|
||||
// Set caller name
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
|
|
@ -661,7 +777,7 @@ public partial class CS2_SimpleAdmin
|
|||
return;
|
||||
}
|
||||
|
||||
var steamid = steamId.SteamId64.ToString();
|
||||
var steamid = steamId.SteamId64;
|
||||
var reason = command.ArgCount >= 3
|
||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
||||
|
|
@ -672,7 +788,7 @@ public partial class CS2_SimpleAdmin
|
|||
if (!CheckValidMute(caller, time)) return;
|
||||
|
||||
// Get player and admin info
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
|
||||
|
||||
// Attempt to match player based on SteamID
|
||||
var player = Helper.GetPlayerFromSteamid64(steamid);
|
||||
|
|
@ -694,10 +810,14 @@ public partial class CS2_SimpleAdmin
|
|||
Task.Run(async () =>
|
||||
{
|
||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 2);
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Silence, reason, time, penaltyId);
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Silence, reason,
|
||||
time, penaltyId);
|
||||
});
|
||||
});
|
||||
|
||||
Helper.SendDiscordPenaltyMessage(caller, steamid, reason, time, PenaltyType.Silence, _localizer);
|
||||
Helper.SendDiscordPenaltyMessage(caller, steamid.ToString(), reason, time, PenaltyType.Silence, _localizer);
|
||||
|
||||
command.ReplyToCommand($"Player with steamid {steamid} is not online. Silence has been added offline.");
|
||||
}
|
||||
|
|
@ -706,6 +826,14 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a silence penalty to a player by Steam ID. Manages both online and offline player cases.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin/player initiating the silence.</param>
|
||||
/// <param name="steamid">Steam ID of player.</param>
|
||||
/// <param name="time">Duration of silence.</param>
|
||||
/// <param name="reason">Reason for the penalty.</param>
|
||||
/// <param name="muteManager">Optional mute manager for DB operations.</param>
|
||||
internal void AddSilence(CCSPlayerController? caller, SteamID steamid, int time, string reason, MuteManager? muteManager = null)
|
||||
{
|
||||
// Set default caller name if not provided
|
||||
|
|
@ -713,9 +841,9 @@ public partial class CS2_SimpleAdmin
|
|||
? caller.PlayerName
|
||||
: (_localizer?["sa_console"] ?? "Console");
|
||||
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
|
||||
|
||||
var player = Helper.GetPlayerFromSteamid64(steamid.SteamId64.ToString());
|
||||
var player = Helper.GetPlayerFromSteamid64(steamid.SteamId64);
|
||||
|
||||
if (player != null && player.IsValid)
|
||||
{
|
||||
|
|
@ -732,19 +860,29 @@ public partial class CS2_SimpleAdmin
|
|||
// Asynchronous ban operation if player is not online or not found
|
||||
Task.Run(async () =>
|
||||
{
|
||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid.SteamId64.ToString(), adminInfo, reason, time, 2);
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Silence, reason, time, penaltyId);
|
||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid.SteamId64, adminInfo, reason, time, 2);
|
||||
await Server.NextWorldUpdateAsync(() =>
|
||||
{
|
||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Silence, reason,
|
||||
time, penaltyId);
|
||||
});
|
||||
});
|
||||
|
||||
Helper.SendDiscordPenaltyMessage(caller, steamid.SteamId64.ToString(), reason, time, PenaltyType.Silence, _localizer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the silence penalty from a player, either by SteamID, name, or offline pattern.
|
||||
/// Resets voice settings and updates notices accordingly.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin/player issuing the unsilence.</param>
|
||||
/// <param name="command">Command arguments with target pattern and optional reason.</param>
|
||||
[RequiresPermissions("@css/chat")]
|
||||
[CommandHelper(minArgs: 1, usage: "<steamid or name> [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnUnsilenceCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (Database == null) return;
|
||||
if (DatabaseProvider == null) return;
|
||||
|
||||
var callerSteamId = caller?.SteamID.ToString() ?? _localizer?["sa_console"] ?? "Console";
|
||||
var pattern = command.GetArg(1);
|
||||
|
|
@ -765,7 +903,7 @@ public partial class CS2_SimpleAdmin
|
|||
// Check if pattern is a valid SteamID64
|
||||
if (Helper.ValidateSteamId(pattern, out var steamId) && steamId != null)
|
||||
{
|
||||
var player = Helper.GetPlayerFromSteamid64(steamId.SteamId64.ToString());
|
||||
var player = Helper.GetPlayerFromSteamid64(steamId.SteamId64);
|
||||
|
||||
if (player != null && player.IsValid)
|
||||
{
|
||||
|
|
@ -797,8 +935,8 @@ public partial class CS2_SimpleAdmin
|
|||
if (namePlayer.VoiceFlags.HasFlag(VoiceFlags.Muted))
|
||||
namePlayer.VoiceFlags &= ~VoiceFlags.Muted;
|
||||
|
||||
if (namePlayer.UserId.HasValue && PlayersInfo[namePlayer.UserId.Value].TotalSilences > 0)
|
||||
PlayersInfo[namePlayer.UserId.Value].TotalSilences--;
|
||||
if (namePlayer.UserId.HasValue && PlayersInfo[namePlayer.SteamID].TotalSilences > 0)
|
||||
PlayersInfo[namePlayer.SteamID].TotalSilences--;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
|
|
@ -818,6 +956,12 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates mute penalty duration based on admin privileges and configured max duration.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin/player issuing the mute.</param>
|
||||
/// <param name="duration">Requested duration in minutes.</param>
|
||||
/// <returns>True if mute penalty duration is allowed; false otherwise.</returns>
|
||||
private bool CheckValidMute(CCSPlayerController? caller, int duration)
|
||||
{
|
||||
if (caller == null) return true;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,12 @@ namespace CS2_SimpleAdmin;
|
|||
|
||||
public partial class CS2_SimpleAdmin
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles the vote command, creates voting menu for players, and collects answers.
|
||||
/// Displays results after timeout and resets voting state.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin who initiated the vote, or null for console.</param>
|
||||
/// <param name="command">Command object containing question and options.</param>
|
||||
[RequiresPermissions("@css/generic")]
|
||||
[CommandHelper(minArgs: 2, usage: "<question> [... options ...]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnVoteCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,11 @@ namespace CS2_SimpleAdmin;
|
|||
|
||||
public partial class CS2_SimpleAdmin
|
||||
{
|
||||
/// <summary>
|
||||
/// Enables or disables no-clip mode for specified player(s).
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">The command input containing targets.</param>
|
||||
[CommandHelper(1, "<#userid or name>")]
|
||||
[RequiresPermissions("@css/cheats")]
|
||||
public void OnNoclipCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -31,6 +36,13 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles no-clip mode for a player and shows admin activity messages.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin toggling no-clip.</param>
|
||||
/// <param name="player">The target player whose no-clip state changes.</param>
|
||||
/// <param name="callerName">Optional caller name for messages.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void NoClip(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!player.IsValid) return;
|
||||
|
|
@ -58,6 +70,12 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, $"css_noclip {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables god mode for specified player(s).
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">The command input containing targets.</param>
|
||||
|
||||
[RequiresPermissions("@css/cheats")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnGodCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -82,6 +100,12 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles god mode for a player and notifies admins.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin toggling god mode.</param>
|
||||
/// <param name="player">The target player whose god mode changes.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void God(CCSPlayerController? caller, CCSPlayerController player, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
|
@ -111,6 +135,11 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Freezes target player(s) for an optional specified duration.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the freeze command.</param>
|
||||
/// <param name="command">The command input containing targets and duration.</param>
|
||||
[CommandHelper(1, "<#userid or name> [duration]")]
|
||||
[RequiresPermissions("@css/slay")]
|
||||
public void OnFreezeCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -133,6 +162,11 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resizes the target player(s) models to a specified scale.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the resize command.</param>
|
||||
/// <param name="command">The command input containing targets and scale factor.</param>
|
||||
[CommandHelper(1, "<#userid or name> [size]")]
|
||||
[RequiresPermissions("@css/slay")]
|
||||
public void OnResizeCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -153,8 +187,8 @@ public partial class CS2_SimpleAdmin
|
|||
|
||||
sceneNode.GetSkeletonInstance().Scale = size;
|
||||
player.PlayerPawn.Value.AcceptInput("SetScale", null, null, size.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
Server.NextFrame(() =>
|
||||
|
||||
Server.NextWorldUpdate(() =>
|
||||
{
|
||||
Utilities.SetStateChanged(player.PlayerPawn.Value, "CBaseEntity", "m_CBodyComponent");
|
||||
});
|
||||
|
|
@ -173,6 +207,14 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Freezes a single player and optionally schedules automatic unfreeze after a duration.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin freezing the player.</param>
|
||||
/// <param name="player">The player to freeze.</param>
|
||||
/// <param name="time">Duration of freeze in seconds.</param>
|
||||
/// <param name="callerName">Optional name for notifications.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void Freeze(CCSPlayerController? caller, CCSPlayerController player, int time, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!player.IsValid) return;
|
||||
|
|
@ -206,6 +248,11 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, $"css_freeze {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {time}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unfreezes target player(s).
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the unfreeze command.</param>
|
||||
/// <param name="command">The command input with targets.</param>
|
||||
[CommandHelper(1, "<#userid or name>")]
|
||||
[RequiresPermissions("@css/slay")]
|
||||
public void OnUnfreezeCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -224,6 +271,13 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unfreezes a single player and notifies admins.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin unfreezing the player.</param>
|
||||
/// <param name="player">The player to unfreeze.</param>
|
||||
/// <param name="callerName">Optional name for notifications.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void Unfreeze(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!player.IsValid) return;
|
||||
|
|
|
|||
|
|
@ -13,8 +13,14 @@ namespace CS2_SimpleAdmin;
|
|||
public partial class CS2_SimpleAdmin
|
||||
{
|
||||
internal static readonly Dictionary<int, float> SpeedPlayers = [];
|
||||
internal static readonly Dictionary<CCSPlayerController, float> GravityPlayers = [];
|
||||
|
||||
internal static readonly Dictionary<int, float> GravityPlayers = [];
|
||||
|
||||
/// <summary>
|
||||
/// Executes the 'slay' command, forcing the targeted players to commit suicide.
|
||||
/// Checks player validity and permissions.
|
||||
/// </summary>
|
||||
/// <param name="caller">Player or console issuing the command.</param>
|
||||
/// <param name="command">Command details, including targets.</param>
|
||||
[RequiresPermissions("@css/slay")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnSlayCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -23,16 +29,23 @@ public partial class CS2_SimpleAdmin
|
|||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
|
||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is {IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
Slay(caller, player, callerName, command);
|
||||
});
|
||||
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the actual slay action on a player, with notification and logging.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console issuing the slay.</param>
|
||||
/// <param name="player">Target player to slay.</param>
|
||||
/// <param name="callerName">Optional name to display as the slayer.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void Slay(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected) return;
|
||||
|
|
@ -60,6 +73,12 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, $"css_slay {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the 'give' command to provide a specified weapon to targeted players.
|
||||
/// Enforces server rules for prohibited weapons.
|
||||
/// </summary>
|
||||
/// <param name="caller">Player or console issuing the command.</param>
|
||||
/// <param name="command">Command details, including targets and weapon name.</param>
|
||||
[RequiresPermissions("@css/cheats")]
|
||||
[CommandHelper(minArgs: 2, usage: "<#userid or name> <weapon>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnGiveCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -71,13 +90,6 @@ public partial class CS2_SimpleAdmin
|
|||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
var weaponName = command.GetArg(2);
|
||||
|
||||
// check if item is typed
|
||||
// if (weaponName.Length < 2)
|
||||
// {
|
||||
// command.ReplyToCommand($"No weapon typed.");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// check if weapon is knife
|
||||
if (weaponName.Contains("_knife") || weaponName.Contains("bayonet"))
|
||||
{
|
||||
|
|
@ -95,10 +107,19 @@ public partial class CS2_SimpleAdmin
|
|||
|
||||
GiveWeapon(caller, player, weaponName, callerName, command);
|
||||
});
|
||||
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gives a weapon identified by name to a player, handling ambiguous matches and logging.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin issuing the command.</param>
|
||||
/// <param name="player">Target player to receive the weapon.</param>
|
||||
/// <param name="weaponName">Weapon name or partial name.</param>
|
||||
/// <param name="callerName">Optional name to display in notifications.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
private static void GiveWeapon(CCSPlayerController? caller, CCSPlayerController player, string weaponName, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
|
@ -112,11 +133,11 @@ public partial class CS2_SimpleAdmin
|
|||
case 0:
|
||||
return;
|
||||
case > 1:
|
||||
{
|
||||
var weaponList = string.Join(", ", weapons.Select(w => w.EnumMemberValue));
|
||||
command?.ReplyToCommand($"Found weapons with a similar name: {weaponList}");
|
||||
return;
|
||||
}
|
||||
{
|
||||
var weaponList = string.Join(", ", weapons.Select(w => w.EnumMemberValue));
|
||||
command?.ReplyToCommand($"Found weapons with a similar name: {weaponList}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Give weapon to the player
|
||||
|
|
@ -138,6 +159,14 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gives a specific weapon to a player, with notifications and logging.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin issuing the command.</param>
|
||||
/// <param name="player">Target player.</param>
|
||||
/// <param name="weapon">Weapon item object.</param>
|
||||
/// <param name="callerName">Optional caller name for notifications.</param>
|
||||
/// <param name="command">Optional command info.</param>
|
||||
internal static void GiveWeapon(CCSPlayerController? caller, CCSPlayerController player, CsItem weapon, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
|
@ -164,6 +193,12 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the 'strip' command, removing all weapons from targeted players.
|
||||
/// Checks player validity and permissions.
|
||||
/// </summary>
|
||||
/// <param name="caller">Player or console issuing the command.</param>
|
||||
/// <param name="command">Command details including targets.</param>
|
||||
[RequiresPermissions("@css/slay")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnStripCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -181,10 +216,17 @@ public partial class CS2_SimpleAdmin
|
|||
StripWeapons(caller, player, callerName, command);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all weapons from a player, with notifications and logging.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console issuing the strip command.</param>
|
||||
/// <param name="player">Target player.</param>
|
||||
/// <param name="callerName">Optional caller name.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void StripWeapons(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
|
@ -215,6 +257,11 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets health value on targeted players.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console issuing the command.</param>
|
||||
/// <param name="command">Command details including targets and health value.</param>
|
||||
[RequiresPermissions("@css/slay")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> <health>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnHpCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -233,10 +280,17 @@ public partial class CS2_SimpleAdmin
|
|||
SetHp(caller, player, health, command);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes health of a player and logs the action.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console calling the method.</param>
|
||||
/// <param name="player">Target player.</param>
|
||||
/// <param name="health">Health value to set.</param>
|
||||
/// <param name="command">Optional command info.</param>
|
||||
internal static void SetHp(CCSPlayerController? caller, CCSPlayerController player, int health, CommandInfo? command = null)
|
||||
{
|
||||
if (!player.IsValid || player.IsHLTV) return;
|
||||
|
|
@ -264,6 +318,11 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets movement speed on targeted players.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console issuing the command.</param>
|
||||
/// <param name="command">Command details including targets and speed.</param>
|
||||
[RequiresPermissions("@css/slay")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> <speed>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnSpeedCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -285,10 +344,17 @@ public partial class CS2_SimpleAdmin
|
|||
SetSpeed(caller, player, speed, command);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes speed of a player and logs the action.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console calling the method.</param>
|
||||
/// <param name="player">Target player.</param>
|
||||
/// <param name="speed">Speed value to set.</param>
|
||||
/// <param name="command">Optional command info.</param>
|
||||
internal static void SetSpeed(CCSPlayerController? caller, CCSPlayerController player, float speed, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
|
@ -298,7 +364,7 @@ public partial class CS2_SimpleAdmin
|
|||
|
||||
// Set player's speed
|
||||
player.SetSpeed(speed);
|
||||
|
||||
|
||||
if (speed == 1f)
|
||||
SpeedPlayers.Remove(player.Slot);
|
||||
else
|
||||
|
|
@ -320,12 +386,17 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets gravity on targeted players.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console issuing the command.</param>
|
||||
/// <param name="command">Command details including targets and gravity value.</param>
|
||||
[RequiresPermissions("@css/slay")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> <gravity>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnGravityCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
float.TryParse(command.GetArg(2), NumberStyles.Float, CultureInfo.InvariantCulture, out var gravity);
|
||||
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
|
||||
|
|
@ -341,10 +412,17 @@ public partial class CS2_SimpleAdmin
|
|||
SetGravity(caller, player, gravity, command);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes gravity of a player and logs the action.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console calling the method.</param>
|
||||
/// <param name="player">Target player.</param>
|
||||
/// <param name="gravity">Gravity value to set.</param>
|
||||
/// <param name="command">Optional command info.</param>
|
||||
internal static void SetGravity(CCSPlayerController? caller, CCSPlayerController player, float gravity, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
|
@ -354,12 +432,12 @@ public partial class CS2_SimpleAdmin
|
|||
|
||||
// Set player's gravity
|
||||
player.SetGravity(gravity);
|
||||
|
||||
|
||||
if (gravity == 1f)
|
||||
GravityPlayers.Remove(player);
|
||||
GravityPlayers.Remove(player.Slot);
|
||||
else
|
||||
GravityPlayers[player] = gravity;
|
||||
|
||||
GravityPlayers[player.Slot] = gravity;
|
||||
|
||||
// Log the command
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_gravity {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {gravity}");
|
||||
|
|
@ -376,6 +454,11 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the money amount for the targeted players.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin executing the command.</param>
|
||||
/// <param name="command">The command containing target player and money value.</param>
|
||||
[RequiresPermissions("@css/slay")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> <money>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnMoneyCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -398,10 +481,17 @@ public partial class CS2_SimpleAdmin
|
|||
SetMoney(caller, player, money, command);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies money value to a single targeted player and logs the operation.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin setting the money.</param>
|
||||
/// <param name="player">The player whose money will be set.</param>
|
||||
/// <param name="money">The value of money to set.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void SetMoney(CCSPlayerController? caller, CCSPlayerController player, int money, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
|
@ -428,6 +518,11 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies damage as a slap effect to the targeted players.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin executing the slap command.</param>
|
||||
/// <param name="command">The command including targets and optional damage value.</param>
|
||||
[RequiresPermissions("@css/slay")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> [damage]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnSlapCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -454,24 +549,31 @@ public partial class CS2_SimpleAdmin
|
|||
Slap(caller, player, damage, command);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies slap damage to a specific player with notifications and logging.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin applying the slap effect.</param>
|
||||
/// <param name="player">The target player to slap.</param>
|
||||
/// <param name="damage">The damage amount to apply.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void Slap(CCSPlayerController? caller, CCSPlayerController player, int damage, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
|
||||
|
||||
// Apply slap damage to the player
|
||||
player.Pawn.Value?.Slap(damage);
|
||||
|
||||
// Log the command
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_slap {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {damage}");
|
||||
|
||||
|
||||
// Determine message key and arguments for the slap notification
|
||||
var (activityMessageKey, adminActivityArgs) =
|
||||
("sa_admin_slap_message",
|
||||
|
|
@ -486,6 +588,11 @@ public partial class CS2_SimpleAdmin
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the team of targeted players with optional kill on switch.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin issuing the command.</param>
|
||||
/// <param name="command">The command containing targets, team info, and optional kill flag.</param>
|
||||
[RequiresPermissions("@css/kick")]
|
||||
[CommandHelper(minArgs: 2, usage: "<#userid or name> [<ct/tt/spec>] [-k]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnTeamCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -531,10 +638,19 @@ public partial class CS2_SimpleAdmin
|
|||
{
|
||||
ChangeTeam(caller, player, _teamName, teamNum, kill, command);
|
||||
});
|
||||
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the team of a player with various conditions and logs the operation.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin issuing the change.</param>
|
||||
/// <param name="player">The target player.</param>
|
||||
/// <param name="teamName">Team name string.</param>
|
||||
/// <param name="teamNum">Team enumeration value.</param>
|
||||
/// <param name="kill">If true, kills player on team change.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void ChangeTeam(CCSPlayerController? caller, CCSPlayerController player, string teamName, CsTeam teamNum, bool kill, CommandInfo? command = null)
|
||||
{
|
||||
// Check if the player is valid and connected
|
||||
|
|
@ -582,6 +698,11 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renames targeted players to a new name.
|
||||
/// </summary>
|
||||
/// <param name="caller">The admin issuing the rename command.</param>
|
||||
/// <param name="command">The command including targets and new name.</param>
|
||||
[CommandHelper(1, "<#userid or name> <new name>")]
|
||||
[RequiresPermissions("@css/kick")]
|
||||
public void OnRenameCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -612,7 +733,7 @@ public partial class CS2_SimpleAdmin
|
|||
// Check if the player is connected and can be targeted
|
||||
if (player.Connected != PlayerConnectedState.PlayerConnected || !caller!.CanTarget(player))
|
||||
return;
|
||||
|
||||
|
||||
// Determine message key and arguments for the rename notification
|
||||
var activityMessageKey = "sa_admin_rename_message";
|
||||
var adminActivityArgs = new object[] { "CALLER", player.PlayerName, newName };
|
||||
|
|
@ -621,12 +742,17 @@ public partial class CS2_SimpleAdmin
|
|||
if (caller != null && SilentPlayers.Contains(caller.Slot)) return;
|
||||
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
|
||||
|
||||
// Rename the player
|
||||
player.Rename(newName);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renames permamently targeted players to a new name.
|
||||
/// </summary>
|
||||
/// <param name="caller">The admin issuing the pre-rename command.</param>
|
||||
/// <param name="command">The command containing targets and new alias.</param>
|
||||
[CommandHelper(1, "<#userid or name> <new name>")]
|
||||
[RequiresPermissions("@css/ban")]
|
||||
public void OnPrenameCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -653,7 +779,7 @@ public partial class CS2_SimpleAdmin
|
|||
// Check if the player is connected and can be targeted
|
||||
if (player.Connected != PlayerConnectedState.PlayerConnected || !caller!.CanTarget(player))
|
||||
return;
|
||||
|
||||
|
||||
// Determine message key and arguments for the rename notification
|
||||
var activityMessageKey = "sa_admin_rename_message";
|
||||
var adminActivityArgs = new object[] { "CALLER", player.PlayerName, newName };
|
||||
|
|
@ -663,7 +789,7 @@ public partial class CS2_SimpleAdmin
|
|||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
|
||||
|
||||
// Determine if the new name is valid and update the renamed players list
|
||||
if (!string.IsNullOrEmpty(newName))
|
||||
{
|
||||
|
|
@ -677,6 +803,11 @@ public partial class CS2_SimpleAdmin
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Respawns targeted players, restoring their state.
|
||||
/// </summary>
|
||||
/// <param name="caller">The admin or player issuing respawn.</param>
|
||||
/// <param name="command">The command including target players.</param>
|
||||
[CommandHelper(1, "<#userid or name>")]
|
||||
[RequiresPermissions("@css/cheats")]
|
||||
public void OnRespawnCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
|
|
@ -701,6 +832,13 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Respawns a specified player and updates admin notifications.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or player executing respawn.</param>
|
||||
/// <param name="player">Player to respawn.</param>
|
||||
/// <param name="callerName">Optional admin name.</param>
|
||||
/// <param name="command">Optional command info.</param>
|
||||
internal static void Respawn(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
// Check if the caller can target the player
|
||||
|
|
@ -716,7 +854,7 @@ public partial class CS2_SimpleAdmin
|
|||
var playerPawn = player.PlayerPawn.Value;
|
||||
player.Respawn();
|
||||
|
||||
if (player.UserId.HasValue && PlayersInfo.TryGetValue(player.UserId.Value, out var value) && value.DiePosition != null)
|
||||
if (player.UserId.HasValue && PlayersInfo.TryGetValue(player.SteamID, out var value) && value.DiePosition != null)
|
||||
playerPawn.Teleport(value.DiePosition?.Position, value.DiePosition?.Angle);
|
||||
|
||||
// Log the command
|
||||
|
|
@ -733,146 +871,270 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
|
||||
[CommandHelper(1, "<#userid or name>")]
|
||||
/// <summary>
|
||||
/// Teleports targeted player(s) to another player's location.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin issuing teleport command.</param>
|
||||
/// <param name="command">Command containing teleport targets and destination.</param>
|
||||
[CommandHelper(1, "<#userid or name> [#userid or name]")]
|
||||
[RequiresPermissions("@css/kick")]
|
||||
public void OnGotoCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
// Check if the caller is valid and has a live pawn
|
||||
if (caller == null || caller.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE) return;
|
||||
IEnumerable<CCSPlayerController> playersToTeleport;
|
||||
CCSPlayerController? destinationPlayer;
|
||||
|
||||
// Get the target players
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null || targets.Count() > 1) return;
|
||||
|
||||
var playersToTarget = targets.Players
|
||||
.Where(player => player is { IsValid: true, IsHLTV: false })
|
||||
.ToList();
|
||||
if (command.ArgCount < 3)
|
||||
{
|
||||
if (caller == null || caller.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE)
|
||||
return;
|
||||
|
||||
// Log the command
|
||||
if (targets == null || targets.Count() != 1)
|
||||
return;
|
||||
|
||||
destinationPlayer = targets.Players.FirstOrDefault(p =>
|
||||
p is { IsValid: true, IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE });
|
||||
|
||||
if (destinationPlayer == null || !caller.CanTarget(destinationPlayer) || caller.PlayerPawn.Value == null)
|
||||
return;
|
||||
|
||||
playersToTeleport = [caller];
|
||||
}
|
||||
else
|
||||
{
|
||||
var destination = GetTarget(command, 2);
|
||||
if (targets == null || destination == null || destination.Count() != 1)
|
||||
return;
|
||||
|
||||
destinationPlayer = destination.Players.FirstOrDefault(p =>
|
||||
p is { IsValid: true, IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE });
|
||||
|
||||
if (destinationPlayer == null)
|
||||
return;
|
||||
|
||||
playersToTeleport = targets.Players
|
||||
.Where(p => p is { IsValid: true, IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE } && caller.CanTarget(p))
|
||||
.ToList();
|
||||
|
||||
if (!playersToTeleport.Any())
|
||||
return;
|
||||
}
|
||||
|
||||
// Log command
|
||||
Helper.LogCommand(caller, command);
|
||||
|
||||
// Process each player to teleport
|
||||
foreach (var player in playersToTarget.Where(player => player is { Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).Where(caller.CanTarget))
|
||||
foreach (var player in playersToTeleport)
|
||||
{
|
||||
if (caller.PlayerPawn.Value == null || player.PlayerPawn.Value == null)
|
||||
if (player.PlayerPawn?.Value == null || destinationPlayer?.PlayerPawn?.Value == null)
|
||||
continue;
|
||||
|
||||
// Teleport the caller to the player and toggle noclip
|
||||
caller.TeleportPlayer(player);
|
||||
// caller.PlayerPawn.Value.ToggleNoclip();
|
||||
player.TeleportPlayer(destinationPlayer);
|
||||
|
||||
caller.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
caller.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
|
||||
Utilities.SetStateChanged(caller, "CCollisionProperty", "m_CollisionGroup");
|
||||
Utilities.SetStateChanged(caller, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
|
||||
player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
|
||||
Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
|
||||
Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
|
||||
// Set a timer to toggle collision back after 4 seconds
|
||||
destinationPlayer.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
destinationPlayer.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
Utilities.SetStateChanged(destinationPlayer, "CCollisionProperty", "m_CollisionGroup");
|
||||
Utilities.SetStateChanged(destinationPlayer, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
|
||||
AddTimer(4, () =>
|
||||
{
|
||||
if (!caller.IsValid || caller.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE)
|
||||
return;
|
||||
|
||||
caller.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
caller.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
|
||||
Utilities.SetStateChanged(caller, "CCollisionProperty", "m_CollisionGroup");
|
||||
Utilities.SetStateChanged(caller, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
|
||||
player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
|
||||
Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
|
||||
Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
if (player is { IsValid: true, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE })
|
||||
{
|
||||
player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
|
||||
Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
}
|
||||
|
||||
if (destinationPlayer.IsValid && destinationPlayer.PlayerPawn?.Value?.LifeState == (int)LifeState_t.LIFE_ALIVE)
|
||||
{
|
||||
destinationPlayer.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
destinationPlayer.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
Utilities.SetStateChanged(destinationPlayer, "CCollisionProperty", "m_CollisionGroup");
|
||||
Utilities.SetStateChanged(destinationPlayer, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
}
|
||||
});
|
||||
|
||||
// Prepare message key and arguments for the teleport notification
|
||||
var activityMessageKey = "sa_admin_tp_message";
|
||||
var adminActivityArgs = new object[] { "CALLER", player.PlayerName };
|
||||
|
||||
// Show admin activity
|
||||
if (!SilentPlayers.Contains(caller.Slot) && _localizer != null)
|
||||
if (caller != null && !SilentPlayers.Contains(caller.Slot) && _localizer != null)
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, caller.PlayerName, false, adminActivityArgs);
|
||||
Helper.ShowAdminActivity("sa_admin_tp_message", player.PlayerName, false, "CALLER", destinationPlayer.PlayerName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[CommandHelper(1, "<#userid or name>")]
|
||||
/// <summary>
|
||||
/// Brings targeted player(s) to the caller or specified destination player's location.
|
||||
/// </summary>
|
||||
/// <param name="caller">Player issuing the bring command.</param>
|
||||
/// <param name="command">Command containing the destination and targets.</param>
|
||||
[CommandHelper(1, "<#destination or name> [#userid or name...]")]
|
||||
[RequiresPermissions("@css/kick")]
|
||||
public void OnBringCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
// Check if the caller is valid and has a live pawn
|
||||
if (caller == null || caller.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE)
|
||||
IEnumerable<CCSPlayerController> playersToTeleport;
|
||||
CCSPlayerController? destinationPlayer;
|
||||
|
||||
if (command.ArgCount < 3)
|
||||
{
|
||||
if (caller == null || caller.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE)
|
||||
return;
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null || !targets.Any())
|
||||
return;
|
||||
|
||||
destinationPlayer = caller;
|
||||
|
||||
playersToTeleport = targets.Players
|
||||
.Where(p => p is { IsValid: true, IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE } && caller.CanTarget(p))
|
||||
.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
var destination = GetTarget(command);
|
||||
if (destination == null || destination.Count() != 1)
|
||||
return;
|
||||
|
||||
destinationPlayer = destination.Players.FirstOrDefault(p =>
|
||||
p is { IsValid: true, IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE });
|
||||
|
||||
if (destinationPlayer == null)
|
||||
return;
|
||||
|
||||
// Rest args = targets to teleport
|
||||
var targets = GetTarget(command, 2);
|
||||
if (targets == null || !targets.Any())
|
||||
return;
|
||||
|
||||
playersToTeleport = targets.Players
|
||||
.Where(p => p is { IsValid: true, IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE } && caller!.CanTarget(p))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
if (destinationPlayer == null || !playersToTeleport.Any())
|
||||
return;
|
||||
|
||||
// Get the target players
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null || targets.Count() > 1) return;
|
||||
|
||||
var playersToTarget = targets.Players
|
||||
.Where(player => player is { IsValid: true, IsHLTV: false })
|
||||
.ToList();
|
||||
|
||||
// Log the command
|
||||
// Log command
|
||||
Helper.LogCommand(caller, command);
|
||||
|
||||
// Process each player to teleport
|
||||
foreach (var player in playersToTarget.Where(player => player is { Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).Where(caller.CanTarget))
|
||||
foreach (var player in playersToTeleport)
|
||||
{
|
||||
if (caller.PlayerPawn.Value == null || player.PlayerPawn.Value == null)
|
||||
if (player.PlayerPawn?.Value == null || destinationPlayer.PlayerPawn?.Value == null)
|
||||
continue;
|
||||
|
||||
// Teleport the player to the caller and toggle noclip
|
||||
player.TeleportPlayer(caller);
|
||||
// caller.PlayerPawn.Value.ToggleNoclip();
|
||||
|
||||
caller.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
caller.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
|
||||
Utilities.SetStateChanged(caller, "CCollisionProperty", "m_CollisionGroup");
|
||||
Utilities.SetStateChanged(caller, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
|
||||
// Teleport
|
||||
player.TeleportPlayer(destinationPlayer);
|
||||
|
||||
player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
|
||||
Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
|
||||
Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
|
||||
// Set a timer to toggle collision back after 4 seconds
|
||||
destinationPlayer.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
destinationPlayer.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
Utilities.SetStateChanged(destinationPlayer, "CCollisionProperty", "m_CollisionGroup");
|
||||
Utilities.SetStateChanged(destinationPlayer, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
|
||||
AddTimer(4, () =>
|
||||
{
|
||||
if (!player.IsValid || player.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE)
|
||||
return;
|
||||
|
||||
caller.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
caller.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
|
||||
Utilities.SetStateChanged(caller, "CCollisionProperty", "m_CollisionGroup");
|
||||
Utilities.SetStateChanged(caller, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
|
||||
player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
|
||||
Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
|
||||
Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
if (player is { IsValid: true, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE })
|
||||
{
|
||||
player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
|
||||
Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
}
|
||||
|
||||
if (destinationPlayer.IsValid && destinationPlayer.PlayerPawn?.Value?.LifeState == (int)LifeState_t.LIFE_ALIVE)
|
||||
{
|
||||
destinationPlayer.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
destinationPlayer.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
Utilities.SetStateChanged(destinationPlayer, "CCollisionProperty", "m_CollisionGroup");
|
||||
Utilities.SetStateChanged(destinationPlayer, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
}
|
||||
});
|
||||
|
||||
// Prepare message key and arguments for the bring notification
|
||||
var activityMessageKey = "sa_admin_bring_message";
|
||||
var adminActivityArgs = new object[] { "CALLER", player.PlayerName };
|
||||
|
||||
// Show admin activity
|
||||
if (!SilentPlayers.Contains(caller.Slot) && _localizer != null)
|
||||
if (caller != null && !SilentPlayers.Contains(caller.Slot) && _localizer != null)
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, caller.PlayerName, false, adminActivityArgs);
|
||||
Helper.ShowAdminActivity("sa_admin_bring_message", player.PlayerName, false, "CALLER", destinationPlayer.PlayerName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// [CommandHelper(1, "<#userid or name> [#userid or name]")]
|
||||
// [RequiresPermissions("@css/kick")]
|
||||
// public void OnBringCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
// {
|
||||
// // Check if the caller is valid and has a live pawn
|
||||
// if (caller == null || caller.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE)
|
||||
// return;
|
||||
//
|
||||
// // Get the target players
|
||||
// var targets = GetTarget(command);
|
||||
// if (targets == null || targets.Count() > 1) return;
|
||||
//
|
||||
// var playersToTarget = targets.Players
|
||||
// .Where(player => player is { IsValid: true, IsHLTV: false })
|
||||
// .ToList();
|
||||
//
|
||||
// // Log the command
|
||||
// Helper.LogCommand(caller, command);
|
||||
//
|
||||
// // Process each player to teleport
|
||||
// foreach (var player in playersToTarget.Where(player => player is { Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).Where(caller.CanTarget))
|
||||
// {
|
||||
// if (caller.PlayerPawn.Value == null || player.PlayerPawn.Value == null)
|
||||
// continue;
|
||||
//
|
||||
// // Teleport the player to the caller and toggle noclip
|
||||
// player.TeleportPlayer(caller);
|
||||
// // caller.PlayerPawn.Value.ToggleNoclip();
|
||||
//
|
||||
// caller.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
// caller.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
//
|
||||
// Utilities.SetStateChanged(caller, "CCollisionProperty", "m_CollisionGroup");
|
||||
// Utilities.SetStateChanged(caller, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
//
|
||||
// player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
// player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
||||
//
|
||||
// Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
|
||||
// Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
//
|
||||
// // Set a timer to toggle collision back after 4 seconds
|
||||
// AddTimer(4, () =>
|
||||
// {
|
||||
// if (!player.IsValid || player.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE)
|
||||
// return;
|
||||
//
|
||||
// caller.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
// caller.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
//
|
||||
// Utilities.SetStateChanged(caller, "CCollisionProperty", "m_CollisionGroup");
|
||||
// Utilities.SetStateChanged(caller, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
//
|
||||
// player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
// player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
||||
//
|
||||
// Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
|
||||
// Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
||||
// });
|
||||
//
|
||||
// // Prepare message key and arguments for the bring notification
|
||||
// var activityMessageKey = "sa_admin_bring_message";
|
||||
// var adminActivityArgs = new object[] { "CALLER", player.PlayerName };
|
||||
//
|
||||
// // Show admin activity
|
||||
// if (!SilentPlayers.Contains(caller.Slot) && _localizer != null)
|
||||
// {
|
||||
// Helper.ShowAdminActivity(activityMessageKey, caller.PlayerName, false, adminActivityArgs);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue