Merge upstream to 1.7.2a

This commit is contained in:
Sachin 2025-01-15 17:36:19 +05:30
commit 75b36a0a98
24 changed files with 660 additions and 280 deletions

Binary file not shown.

View file

@ -25,14 +25,14 @@ public class CS2_SimpleAdminApi : ICS2_SimpleAdminApi
return PlayerPenaltyManager.GetAllPlayerPenalties(player.Slot);
}
public event Action<PlayerInfo, PlayerInfo?, PenaltyType, string, int, int?>? OnPlayerPenaltied;
public event Action<SteamID, PlayerInfo?, PenaltyType, string, int, int?>? OnPlayerPenaltiedAdded;
public event Action<PlayerInfo, PlayerInfo?, PenaltyType, string, int, int?, int?>? OnPlayerPenaltied;
public event Action<SteamID, PlayerInfo?, PenaltyType, string, int, int?, int?>? OnPlayerPenaltiedAdded;
public void OnPlayerPenaltiedEvent(PlayerInfo player, PlayerInfo? admin, PenaltyType penaltyType, string reason,
int duration = -1) => OnPlayerPenaltied?.Invoke(player, admin, penaltyType, reason, duration, CS2_SimpleAdmin.ServerId);
int duration, int? penaltyId) => OnPlayerPenaltied?.Invoke(player, admin, penaltyType, reason, duration, penaltyId, CS2_SimpleAdmin.ServerId);
public void OnPlayerPenaltiedAddedEvent(SteamID player, PlayerInfo? admin, PenaltyType penaltyType, string reason,
int duration) => OnPlayerPenaltiedAdded?.Invoke(player, admin, penaltyType, reason, duration, CS2_SimpleAdmin.ServerId);
int duration, int? penaltyId) => OnPlayerPenaltiedAdded?.Invoke(player, admin, penaltyType, reason, duration, penaltyId, CS2_SimpleAdmin.ServerId);
public void IssuePenalty(CCSPlayerController player, CCSPlayerController? admin, PenaltyType penaltyType, string reason, int duration = -1)
{

View file

@ -19,7 +19,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdmin
public override string ModuleName => "CS2-SimpleAdmin" + (Helper.IsDebugBuild ? " (DEBUG)" : " (RELEASE)");
public override string ModuleDescription => "Simple admin plugin for Counter-Strike 2 :)";
public override string ModuleAuthor => "daffyy & Dliix66";
public override string ModuleVersion => "1.7.0a";
public override string ModuleVersion => "1.7.2a";
public override void Load(bool hotReload)
{
@ -58,6 +58,8 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdmin
public override void OnAllPluginsLoaded(bool hotReload)
{
new ServerManager().CheckHibernationStatus();
AddTimer(3.0f, () => ReloadAdmins(null));
try

View file

@ -78,7 +78,8 @@ public static class RegisterCommands
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_pluginsmanager", CS2_SimpleAdmin.Instance.OnPluginManagerCommand),
new CommandMapping("css_adminvoice", CS2_SimpleAdmin.Instance.OnAdminVoiceCommand)
];
public static void InitializeCommands()
@ -160,7 +161,8 @@ public static class RegisterCommands
{ "css_respawn", new Command { Aliases = ["css_respawn"] } },
{ "css_tp", new Command { Aliases = ["css_tp", "css_tpto", "css_goto"] } },
{ "css_bring", new Command { Aliases = ["css_bring", "css_tphere"] } },
{ "css_pluginsmanager", new Command { Aliases = ["css_pluginsmanager", "css_pluginmanager"] } }
{ "css_pluginsmanager", new Command { Aliases = ["css_pluginsmanager", "css_pluginmanager"] } },
{ "css_adminvoice", new Command { Aliases = ["css_adminvoice", "css_listenall"] } }
}
};

View file

@ -19,9 +19,7 @@ public partial class CS2_SimpleAdmin
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
if (command.ArgCount < 2)
return;
var reason = _localizer?["sa_unknown"] ?? "Unknown";
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, Connected: PlayerConnectedState.PlayerConnected, IsHLTV: false }).ToList();
@ -31,14 +29,20 @@ public partial class CS2_SimpleAdmin
return;
}
if (command.ArgCount >= 3 && command.GetArg(3).Length > 0)
reason = command.GetArg(3);
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 = Helper.ParsePenaltyTime(command.GetArg(2));
playersToTarget.ForEach(player =>
{
if (!caller.CanTarget(player)) return;
if (!int.TryParse(command.GetArg(2), out var time) && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
if (time < 0 && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
{
DurationMenu.OpenMenu(caller, $"{_localizer?["sa_ban"] ?? "Ban"}: {player.PlayerName}", player,
ManagePlayersMenu.BanMenu);
@ -59,13 +63,7 @@ public partial class CS2_SimpleAdmin
callerName = !string.IsNullOrEmpty(caller?.PlayerName)
? caller.PlayerName
: (_localizer?["sa_console"] ?? "Console");
// Freeze player pawn if alive
if (player.PawnIsAlive)
{
player.Pawn.Value?.Freeze();
}
// Get player and admin information
var playerInfo = PlayersInfo[player.UserId.Value];
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
@ -73,7 +71,8 @@ public partial class CS2_SimpleAdmin
// Asynchronously handle banning logic
Task.Run(async () =>
{
await BanManager.BanPlayer(playerInfo, adminInfo, reason, time);
int? penaltyId = await BanManager.BanPlayer(playerInfo, adminInfo, reason, time);
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Ban, reason, time, penaltyId);
});
// Update banned players list
@ -103,13 +102,7 @@ public partial class CS2_SimpleAdmin
// Schedule a kick timer
if (player.UserId.HasValue)
{
AddTimer(Config.OtherSettings.KickTime, () =>
{
if (player is { IsValid: true, UserId: not null })
{
Helper.KickPlayer(player.UserId.Value, NetworkDisconnectionReason.NETWORK_DISCONNECT_KICKBANADDED);
}
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
Helper.KickPlayer(player.UserId.Value, NetworkDisconnectionReason.NETWORK_DISCONNECT_KICKBANADDED, Config.OtherSettings.KickTime);
}
// Execute ban command if necessary
@ -127,7 +120,6 @@ public partial class CS2_SimpleAdmin
}
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Ban, _localizer);
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Ban, reason, time);
}
[RequiresPermissions("@css/ban")]
@ -144,11 +136,14 @@ public partial class CS2_SimpleAdmin
}
var steamid = steamId.SteamId64.ToString();
var reason = command.ArgCount >= 3 && !string.IsNullOrEmpty(command.GetArg(3))
? command.GetArg(3)
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;
int.TryParse(command.GetArg(2), out var time);
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
if (!CheckValidBan(caller, time)) return;
var adminInfo = caller != null && caller.UserId.HasValue
@ -168,10 +163,14 @@ public partial class CS2_SimpleAdmin
}
else
{
if (!caller.CanTarget(new SteamID(steamId.SteamId64)))
return;
// Asynchronous ban operation if player is not online or not found
Task.Run(async () =>
{
await BanManager.AddBanBySteamid(steamid, adminInfo, reason, time);
int? penaltyId = await BanManager.AddBanBySteamid(steamid, adminInfo, reason, time);
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Ban, reason, time, penaltyId);
});
Helper.SendDiscordPenaltyMessage(caller, steamid, reason, time, PenaltyType.Ban, _localizer);
@ -183,8 +182,6 @@ public partial class CS2_SimpleAdmin
if (UnlockedCommands && Config.BanIDBan)
Server.ExecuteCommand($"banid 1 {steamId.SteamId3}");
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Ban, reason, time);
}
[RequiresPermissions("@css/ban")]
@ -202,11 +199,14 @@ public partial class CS2_SimpleAdmin
return;
}
var reason = command.ArgCount >= 3 && !string.IsNullOrEmpty(command.GetArg(3))
? command.GetArg(3)
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)));
int.TryParse(command.GetArg(2), out var time);
if (!CheckValidBan(caller, time)) return;
var adminInfo = caller != null && caller.UserId.HasValue
@ -270,7 +270,11 @@ public partial class CS2_SimpleAdmin
}
var pattern = command.GetArg(1);
var reason = command.GetArg(2);
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));
@ -288,9 +292,7 @@ public partial class CS2_SimpleAdmin
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
if (command.ArgCount < 2)
return;
var reason = _localizer?["sa_unknown"] ?? "Unknown";
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player.IsValid && player.Connected == PlayerConnectedState.PlayerConnected && !player.IsHLTV).ToList();
@ -302,10 +304,12 @@ public partial class CS2_SimpleAdmin
WarnManager warnManager = new(Database);
int.TryParse(command.GetArg(2), out var time);
if (command.ArgCount >= 3 && command.GetArg(3).Length > 0)
reason = command.GetArg(3);
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 =>
{
@ -342,7 +346,8 @@ public partial class CS2_SimpleAdmin
Task.Run(async () =>
{
warnManager ??= new WarnManager(Database);
await warnManager.WarnPlayer(playerInfo, adminInfo, reason, time);
int? penaltyId = await warnManager.WarnPlayer(playerInfo, adminInfo, reason, time);
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());
@ -392,7 +397,6 @@ public partial class CS2_SimpleAdmin
// Send Discord notification for the warning
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Warn, _localizer);
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Warn, reason, time);
}
[RequiresPermissions("@css/kick")]

View file

@ -15,6 +15,7 @@ using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Globalization;
using System.Reflection;
using CounterStrikeSharp.API.ValveConstants.Protobuf;
using MenuManager;
namespace CS2_SimpleAdmin;
@ -40,7 +41,7 @@ public partial class CS2_SimpleAdmin
playersToTarget.ForEach(player =>
{
if (!player.UserId.HasValue) return;
if (!caller!.CanTarget(player)) return;
if (!caller.CanTarget(player)) return;
userId = player.UserId.Value;
});
@ -140,6 +141,38 @@ public partial class CS2_SimpleAdmin
});
}
[RequiresPermissions("@css/chat")]
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
public void OnAdminVoiceCommand(CCSPlayerController? caller, CommandInfo command)
{
if (caller == null || caller.IsValid == false)
return;
if (command.ArgCount > 1)
{
if (command.GetArg(2).ToLower().Equals("muteAll"))
{
foreach (var player in Helper.GetValidPlayers().Where(p => p != caller && !AdminManager.PlayerHasPermissions(new SteamID(p.SteamID), "@css/chat")))
{
player.VoiceFlags = VoiceFlags.Muted;
}
}
if (command.GetArg(2).ToLower().Equals("unmuteAll"))
{
foreach (var player in Helper.GetValidPlayers().Where(p => p != caller))
{
if (PlayerPenaltyManager.GetPlayerPenalties(player.Slot, PenaltyType.Mute).Count == 0)
player.VoiceFlags = VoiceFlags.Normal;
}
}
return;
}
caller.VoiceFlags = caller.VoiceFlags == VoiceFlags.All ? VoiceFlags.Normal : VoiceFlags.All;
}
[RequiresPermissions("@css/generic")]
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
public void OnAdminCommand(CCSPlayerController? caller, CommandInfo command)
@ -192,7 +225,7 @@ public partial class CS2_SimpleAdmin
var globalAdmin = command.GetArg(4).ToLower().Equals("-g") || command.GetArg(5).ToLower().Equals("-g") ||
command.GetArg(6).ToLower().Equals("-g");
int.TryParse(command.GetArg(4), out var immunity);
int.TryParse(command.GetArg(5), out var time);
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(5)));
AddAdmin(caller, steamid, name, flags, immunity, time, globalAdmin, command);
}
@ -514,6 +547,23 @@ public partial class CS2_SimpleAdmin
ReasonMenu.OpenMenu(caller, PenaltyType.Ban, _localizer["sa_reason"], player, (_, _, reason) =>
{
caller.ExecuteClientCommandFromServer($"css_addban {player.SteamId.SteamId64} {duration} \"{reason}\"");
// Determine message keys and arguments based on ban time
var (_, activityMessageKey, _, adminActivityArgs) = duration == 0
? ("sa_player_ban_message_perm", "sa_admin_ban_message_perm",
[reason, "CALLER"],
["CALLER", player.Name, reason])
: ("sa_player_ban_message_time", "sa_admin_ban_message_time",
new object[] { reason, duration, "CALLER" },
new object[] { "CALLER", player.Name, reason, duration });
// Display admin activity message if necessary
if (!SilentPlayers.Contains(caller.Slot))
{
Helper.ShowAdminActivity(activityMessageKey, caller.PlayerName, adminActivityArgs);
}
MenuApi?.CloseMenu(caller);
}));
});
disconnectedMenuAction?.AddMenuOption(_localizer["sa_mute"], (_, _) =>
@ -522,6 +572,23 @@ public partial class CS2_SimpleAdmin
ReasonMenu.OpenMenu(caller, PenaltyType.Mute, _localizer["sa_reason"], player, (_, _, reason) =>
{
caller.ExecuteClientCommandFromServer($"css_addmute {player.SteamId.SteamId64} {duration} \"{reason}\"");
// Determine message keys and arguments based on mute time (permanent or timed)
var (_, activityMessageKey, _, adminActivityArgs) = duration == 0
? ("sa_player_mute_message_perm", "sa_admin_mute_message_perm",
[reason, "CALLER"],
["CALLER", player.Name, reason])
: ("sa_player_mute_message_time", "sa_admin_mute_message_time",
new object[] { reason, duration, "CALLER" },
new object[] { "CALLER", player.Name, reason, duration });
// Display admin activity message to other players
if (!SilentPlayers.Contains(caller.Slot))
{
Helper.ShowAdminActivity(activityMessageKey, caller.PlayerName, adminActivityArgs);
}
MenuApi?.CloseMenu(caller);
}));
});
disconnectedMenuAction?.AddMenuOption(_localizer["sa_gag"], (_, _) =>
@ -530,6 +597,23 @@ public partial class CS2_SimpleAdmin
ReasonMenu.OpenMenu(caller, PenaltyType.Mute, _localizer["sa_reason"], player, (_, _, reason) =>
{
caller.ExecuteClientCommandFromServer($"css_addgag {player.SteamId.SteamId64} {duration} \"{reason}\"");
// Determine message keys and arguments based on gag time (permanent or timed)
var (_, activityMessageKey, _, adminActivityArgs) = duration == 0
? ("sa_player_gag_message_perm", "sa_admin_gag_message_perm",
[reason, "CALLER"],
["CALLER", player.Name, reason])
: ("sa_player_gag_message_time", "sa_admin_gag_message_time",
new object[] { reason, duration, "CALLER" },
new object[] { "CALLER", player.Name, reason, duration});
// Display admin activity message to other players
if (!SilentPlayers.Contains(caller.Slot))
{
Helper.ShowAdminActivity(activityMessageKey, caller.PlayerName, adminActivityArgs);
}
MenuApi?.CloseMenu(caller);
}));
});
disconnectedMenuAction?.AddMenuOption(_localizer["sa_silence"], (_, _) =>
@ -538,6 +622,23 @@ public partial class CS2_SimpleAdmin
ReasonMenu.OpenMenu(caller, PenaltyType.Mute, _localizer["sa_reason"], player, (_, _, reason) =>
{
caller.ExecuteClientCommandFromServer($"css_addsilence {player.SteamId.SteamId64} {duration} \"{reason}\"");
// Determine message keys and arguments based on silence time (permanent or timed)
var (_, activityMessageKey, _, adminActivityArgs) = duration == 0
? ("sa_player_silence_message_perm", "sa_admin_silence_message_perm",
[reason, "CALLER"],
["CALLER", player.Name, reason])
: ("sa_player_silence_message_time", "sa_admin_silence_message_time",
new object[] { reason, duration, "CALLER" },
new object[] { "CALLER", player.Name, reason, duration });
// Display admin activity message to other players
if (!SilentPlayers.Contains(caller.Slot))
{
Helper.ShowAdminActivity(activityMessageKey, caller.PlayerName, adminActivityArgs);
}
MenuApi?.CloseMenu(caller);
}));
});
@ -567,7 +668,7 @@ public partial class CS2_SimpleAdmin
playersToTarget.ForEach(player =>
{
if (!player.UserId.HasValue) return;
if (!caller!.CanTarget(player)) return;
if (!caller.CanTarget(player)) return;
var userId = player.UserId.Value;
@ -617,30 +718,30 @@ public partial class CS2_SimpleAdmin
{
if (caller != null)
{
caller.PrintToConsole($"--------- PLAYER LIST ---------");
caller.PrintToConsole("--------- PLAYER LIST ---------");
playersToTarget.ForEach(player =>
{
caller.PrintToConsole(
$"• [#{player.UserId}] \"{player.PlayerName}\" (IP Address: \"{(AdminManager.PlayerHasPermissions(caller, "@css/showip") ? player.IpAddress?.Split(":")[0] : "Unknown")}\" SteamID64: \"{player.SteamID}\")");
});
caller.PrintToConsole($"--------- END PLAYER LIST ---------");
caller.PrintToConsole("--------- END PLAYER LIST ---------");
}
else
{
Server.PrintToConsole($"--------- PLAYER LIST ---------");
Server.PrintToConsole("--------- PLAYER LIST ---------");
playersToTarget.ForEach(player =>
{
Server.PrintToConsole($"• [#{player.UserId}] \"{player.PlayerName}\" (IP Address: \"{player.IpAddress?.Split(":")[0]}\" SteamID64: \"{player.SteamID}\")");
});
Server.PrintToConsole($"--------- END PLAYER LIST ---------");
Server.PrintToConsole("--------- END PLAYER LIST ---------");
}
}
else
{
var playersJson = JsonConvert.SerializeObject(playersToTarget.Select((CCSPlayerController player) =>
var playersJson = JsonConvert.SerializeObject(playersToTarget.Select(player =>
{
var matchStats = player.ActionTrackingServices?.MatchStats;
return new
{
player.UserId,
@ -671,7 +772,6 @@ public partial class CS2_SimpleAdmin
public void OnKickCommand(CCSPlayerController? caller, CommandInfo command)
{
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
var reason = _localizer?["sa_unknown"] ?? "Unknown";
var targets = GetTarget(command);
@ -684,8 +784,11 @@ public partial class CS2_SimpleAdmin
return;
}
if (command.ArgCount >= 2 && command.GetArg(2).Length > 0)
reason = command.GetArg(2);
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;
playersToTarget.ForEach(player =>
{
@ -711,13 +814,7 @@ public partial class CS2_SimpleAdmin
var playerInfo = PlayersInfo[player.UserId.Value];
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
// Freeze player pawn if alive
if (player.PawnIsAlive)
{
player.Pawn.Value?.Freeze();
}
// Determine message keys and arguments for the kick notification
var (messageKey, activityMessageKey, centerArgs, adminActivityArgs) =
("sa_player_kick_message", "sa_admin_kick_message",
@ -736,13 +833,7 @@ public partial class CS2_SimpleAdmin
// Schedule the kick for the player
if (player.UserId.HasValue)
{
AddTimer(Config.OtherSettings.KickTime, () =>
{
if (player.IsValid)
{
Helper.KickPlayer(player.UserId.Value);
}
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
Helper.KickPlayer(player.UserId.Value, NetworkDisconnectionReason.NETWORK_DISCONNECT_KICKED, Config.OtherSettings.KickTime);
}
// Log the command and send Discord notification
@ -751,7 +842,7 @@ public partial class CS2_SimpleAdmin
else
Helper.LogCommand(caller, command);
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Kick, reason);
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Kick, reason, -1, null);
}
[RequiresPermissions("@css/changemap")]

View file

@ -2,6 +2,7 @@ using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Admin;
using CounterStrikeSharp.API.Modules.Commands;
using CounterStrikeSharp.API.Modules.Entities;
using CS2_SimpleAdmin.Managers;
using CS2_SimpleAdmin.Menus;
using CS2_SimpleAdminApi;
@ -16,9 +17,7 @@ public partial class CS2_SimpleAdmin
{
if (Database == null) return;
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
var reason = _localizer?["sa_unknown"] ?? "Unknown";
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
@ -28,13 +27,18 @@ public partial class CS2_SimpleAdmin
return;
}
if (command.ArgCount >= 3 && command.GetArg(3).Length > 0)
reason = command.GetArg(3);
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 = Helper.ParsePenaltyTime(command.GetArg(2));
playersToTarget.ForEach(player =>
{
if (!caller!.CanTarget(player)) return;
if (!int.TryParse(command.GetArg(2), out var time) && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
if (time < 0 && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
{
DurationMenu.OpenMenu(caller, $"{_localizer?["sa_gag"] ?? "Gag"}: {player.PlayerName}", player,
ManagePlayersMenu.GagMenu);
@ -61,7 +65,8 @@ public partial class CS2_SimpleAdmin
// Asynchronously handle gag logic
Task.Run(async () =>
{
await MuteManager.MutePlayer(playerInfo, adminInfo, reason, time);
int? penaltyId = await MuteManager.MutePlayer(playerInfo, adminInfo, reason, time);
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Gag, reason, time, penaltyId);
});
// Add penalty to the player's penalty manager
@ -98,7 +103,6 @@ public partial class CS2_SimpleAdmin
}
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Gag, _localizer);
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Gag, reason, time);
}
[RequiresPermissions("@css/chat")]
@ -121,11 +125,13 @@ public partial class CS2_SimpleAdmin
}
var steamid = steamId.SteamId64.ToString();
var reason = command.ArgCount >= 3 && command.GetArg(3).Length > 0
? command.GetArg(3)
: (_localizer?["sa_unknown"] ?? "Unknown");
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;
int.TryParse(command.GetArg(2), out var time);
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
if (!CheckValidMute(caller, time)) return;
// Get player and admin info
@ -145,10 +151,14 @@ public partial class CS2_SimpleAdmin
}
else
{
if (!caller.CanTarget(new SteamID(steamId.SteamId64)))
return;
// Asynchronous gag operation for offline players
Task.Run(async () =>
{
await MuteManager.AddMuteBySteamid(steamid, adminInfo, reason, time);
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid, adminInfo, reason, time);
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Gag, reason, time, penaltyId);
});
Helper.SendDiscordPenaltyMessage(caller, steamid, reason, time, PenaltyType.Gag, _localizer);
@ -158,7 +168,6 @@ public partial class CS2_SimpleAdmin
// Log the gag command and respond to the command
Helper.LogCommand(caller, command);
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Gag, reason, time);
}
[RequiresPermissions("@css/chat")]
@ -169,8 +178,12 @@ public partial class CS2_SimpleAdmin
var callerSteamId = caller?.SteamID.ToString() ?? _localizer?["sa_console"] ?? "Console";
var pattern = command.GetArg(1);
var reason = command.GetArg(2);
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;
if (pattern.Length <= 1)
{
command.ReplyToCommand($"Too short pattern to search.");
@ -235,8 +248,6 @@ public partial class CS2_SimpleAdmin
if (Database == null) return;
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
var reason = _localizer?["sa_unknown"] ?? "Unknown";
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
@ -246,13 +257,18 @@ public partial class CS2_SimpleAdmin
return;
}
if (command.ArgCount >= 3 && command.GetArg(3).Length > 0)
reason = command.GetArg(3);
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 = Helper.ParsePenaltyTime(command.GetArg(2));
playersToTarget.ForEach(player =>
{
if (!caller!.CanTarget(player)) return;
if (!int.TryParse(command.GetArg(2), out var time) && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
if (time < 0 && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
{
DurationMenu.OpenMenu(caller, $"{_localizer?["sa_mute"] ?? "Mute"}: {player.PlayerName}", player,
ManagePlayersMenu.MuteMenu);
@ -283,7 +299,8 @@ public partial class CS2_SimpleAdmin
// Asynchronously handle mute logic
Task.Run(async () =>
{
await MuteManager.MutePlayer(playerInfo, adminInfo, reason, time, 1);
int? penaltyId = await MuteManager.MutePlayer(playerInfo, adminInfo, reason, time, 1);
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Mute, reason, time, penaltyId);
});
// Add penalty to the player's penalty manager
@ -320,7 +337,6 @@ public partial class CS2_SimpleAdmin
}
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Mute, _localizer);
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Mute, reason, time);
}
[RequiresPermissions("@css/chat")]
@ -343,11 +359,13 @@ public partial class CS2_SimpleAdmin
}
var steamid = steamId.SteamId64.ToString();
var reason = command.ArgCount >= 3 && command.GetArg(3).Length > 0
? command.GetArg(3)
: (_localizer?["sa_unknown"] ?? "Unknown");
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;
int.TryParse(command.GetArg(2), out var time);
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
if (!CheckValidMute(caller, time)) return;
// Get player and admin info
@ -367,10 +385,14 @@ public partial class CS2_SimpleAdmin
}
else
{
if (!caller.CanTarget(new SteamID(steamId.SteamId64)))
return;
// Asynchronous mute operation for offline players
Task.Run(async () =>
{
await MuteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 1);
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 1);
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Mute, reason, time, penaltyId);
});
Helper.SendDiscordPenaltyMessage(caller, steamid, reason, time, PenaltyType.Mute, _localizer);
@ -380,7 +402,6 @@ public partial class CS2_SimpleAdmin
// Log the mute command and respond to the command
Helper.LogCommand(caller, command);
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Mute, reason, time);
}
[RequiresPermissions("@css/chat")]
@ -391,8 +412,12 @@ public partial class CS2_SimpleAdmin
var callerSteamId = caller?.SteamID.ToString() ?? _localizer?["sa_console"] ?? "Console";
var pattern = command.GetArg(1);
var reason = command.GetArg(2);
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;
if (pattern.Length <= 1)
{
command.ReplyToCommand("Too short pattern to search.");
@ -460,9 +485,7 @@ public partial class CS2_SimpleAdmin
{
if (Database == null) return;
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
var reason = _localizer?["sa_unknown"] ?? "Unknown";
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
@ -472,13 +495,18 @@ public partial class CS2_SimpleAdmin
return;
}
if (command.ArgCount >= 3 && command.GetArg(3).Length > 0)
reason = command.GetArg(3);
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 = Helper.ParsePenaltyTime(command.GetArg(2));
playersToTarget.ForEach(player =>
{
if (!caller!.CanTarget(player)) return;
if (!int.TryParse(command.GetArg(2), out var time) && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
if (time < 0 && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
{
DurationMenu.OpenMenu(caller, $"{_localizer?["sa_silence"] ?? "Silence"}: {player.PlayerName}", player,
ManagePlayersMenu.SilenceMenu);
@ -509,7 +537,8 @@ public partial class CS2_SimpleAdmin
// Asynchronously handle silence logic
Task.Run(async () =>
{
await MuteManager.MutePlayer(playerInfo, adminInfo, reason, time, 2); // Assuming 2 is the type for silence
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);
});
// Add penalty to the player's penalty manager
@ -547,7 +576,6 @@ public partial class CS2_SimpleAdmin
}
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Silence, _localizer);
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Silence, reason, time);
}
[RequiresPermissions("@css/chat")]
@ -570,11 +598,13 @@ public partial class CS2_SimpleAdmin
}
var steamid = steamId.SteamId64.ToString();
var reason = command.ArgCount >= 3 && command.GetArg(3).Length > 0
? command.GetArg(3)
: (_localizer?["sa_unknown"] ?? "Unknown");
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;
int.TryParse(command.GetArg(2), out var time);
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
if (!CheckValidMute(caller, time)) return;
// Get player and admin info
@ -594,10 +624,14 @@ public partial class CS2_SimpleAdmin
}
else
{
if (!caller.CanTarget(new SteamID(steamId.SteamId64)))
return;
// Asynchronous silence operation for offline players
Task.Run(async () =>
{
await MuteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 2);
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 2);
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Silence, reason, time, penaltyId);
});
Helper.SendDiscordPenaltyMessage(caller, steamid, reason, time, PenaltyType.Silence, _localizer);
@ -607,7 +641,6 @@ public partial class CS2_SimpleAdmin
// Log the silence command and respond to the command
Helper.LogCommand(caller, command);
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Silence, reason, time);
}
[RequiresPermissions("@css/chat")]
@ -618,14 +651,18 @@ public partial class CS2_SimpleAdmin
var callerSteamId = caller?.SteamID.ToString() ?? _localizer?["sa_console"] ?? "Console";
var pattern = command.GetArg(1);
var reason = command.GetArg(2);
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;
if (pattern.Length <= 1)
{
command.ReplyToCommand("Too short pattern to search.");
return;
}
Helper.LogCommand(caller, command);
// Check if pattern is a valid SteamID64

View file

@ -0,0 +1 @@
ALTER TABLE `sa_servers` ADD `rcon_password` varchar(128) NULL AFTER `hostname`;

View file

@ -59,7 +59,7 @@ public partial class CS2_SimpleAdmin
new ServerManager().LoadServerData();
}
[GameEventHandler]
[GameEventHandler(HookMode.Pre)]
public HookResult OnClientDisconnect(EventPlayerDisconnect @event, GameEventInfo info)
{
var player = @event.Userid;
@ -101,9 +101,14 @@ public partial class CS2_SimpleAdmin
GodPlayers.Remove(player.Slot);
SpeedPlayers.Remove(player.Slot);
GravityPlayers.Remove(player);
if (player.UserId.HasValue)
{
if (@event.Reason == 149)
info.DontBroadcast = true;
PlayersInfo.TryRemove(player.UserId.Value, out _);
}
var authorizedSteamId = player.AuthorizedSteamID;
if (authorizedSteamId == null || !PermissionManager.AdminCache.TryGetValue(authorizedSteamId,
@ -150,8 +155,12 @@ public partial class CS2_SimpleAdmin
if (player == null || !player.IsValid || player.IsBot)
return HookResult.Continue;
if (player.UserId.HasValue && PlayersInfo.TryGetValue(player.UserId.Value, out PlayerInfo? value) &&
value.WaitingForKick)
return HookResult.Continue;
new PlayerManager().LoadPlayerData(player);
new PlayerManager().LoadPlayerData(player, true);
return HookResult.Continue;
}

View file

@ -36,6 +36,14 @@ public static class PlayerExtensions
AdminManager.GetPlayerImmunity(controller) >= AdminManager.GetPlayerImmunity(target);
}
public static bool CanTarget(this CCSPlayerController? controller, SteamID steamId)
{
if (controller is null) return true;
return AdminManager.CanPlayerTarget(new SteamID(controller.SteamID), steamId) ||
AdminManager.GetPlayerImmunity(controller) >= AdminManager.GetPlayerImmunity(steamId);
}
public static void SetSpeed(this CCSPlayerController? controller, float speed)
{
var playerPawnValue = controller?.PlayerPawn.Value;

View file

@ -106,11 +106,11 @@ internal static class Helper
);
}
public static bool IsValidSteamId64(string input)
{
const string pattern = @"^\d{17}$";
return Regex.IsMatch(input, pattern);
}
// public static bool IsValidSteamId64(string input)
// {
// const string pattern = @"^\d{17}$";
// return Regex.IsMatch(input, pattern);
// }
public static bool ValidateSteamId(string input, out SteamID? steamId)
{
@ -120,7 +120,7 @@ internal static class Helper
{
return false;
}
if (!SteamID.TryParse(input, out var parsedSteamId)) return false;
steamId = parsedSteamId;
@ -164,14 +164,39 @@ internal static class Helper
}
}
public static void KickPlayer(int userId, NetworkDisconnectionReason reason = NetworkDisconnectionReason.NETWORK_DISCONNECT_KICKED)
public static void KickPlayer(int userId, NetworkDisconnectionReason reason = NetworkDisconnectionReason.NETWORK_DISCONNECT_KICKED, int delay = 0)
{
var player = Utilities.GetPlayerFromUserid(userId);
if (player == null || !player.IsValid || player.IsHLTV)
return;
if (player.UserId.HasValue)
CS2_SimpleAdmin.PlayersInfo[player.UserId.Value].WaitingForKick = true;
player.Disconnect(reason);
player.CommitSuicide(true, true);
if (delay > 0)
{
CS2_SimpleAdmin.Instance.AddTimer(delay, () =>
{
if (!player.IsValid || player.IsHLTV)
return;
Server.ExecuteCommand($"kickid {player.UserId}");
// player.Disconnect(reason); Broken after last update
});
}
else
{
Server.ExecuteCommand($"kickid {player.UserId}");
player.Disconnect(reason); // Broken after last update
}
if (CS2_SimpleAdmin.UnlockedCommands && reason == NetworkDisconnectionReason.NETWORK_DISCONNECT_REJECT_BANNED)
Server.ExecuteCommand($"banid 1 {new SteamID(player.SteamID).SteamId3}");
// if (!string.IsNullOrEmpty(reason))
// {
@ -186,9 +211,46 @@ internal static class Helper
// Server.ExecuteCommand($"kickid {userId} {reason}");
}
public static void KickPlayer(CCSPlayerController player, NetworkDisconnectionReason reason = NetworkDisconnectionReason.NETWORK_DISCONNECT_KICKED)
public static void KickPlayer(CCSPlayerController player, NetworkDisconnectionReason reason = NetworkDisconnectionReason.NETWORK_DISCONNECT_KICKED, int delay = 0)
{
player.Disconnect(reason);
if (!player.IsValid || player.IsHLTV)
return;
if (player.UserId.HasValue)
CS2_SimpleAdmin.PlayersInfo[player.UserId.Value].WaitingForKick = true;
player.CommitSuicide(true, true);
if (delay > 0)
{
CS2_SimpleAdmin.Instance.AddTimer(delay, () =>
{
if (!player.IsValid || player.IsHLTV)
return;
// if (!string.IsNullOrEmpty(reason))
// {
// var escapeChars = reason.IndexOfAny([';', '|']);
//
// if (escapeChars != -1)
// {
// reason = reason[..escapeChars];
// }
// }
//
Server.ExecuteCommand($"kickid {player.UserId}");
// player.Disconnect(reason); // Broken after last update
});
}
else
{
Server.ExecuteCommand($"kickid {player.UserId}");
// player.Disconnect(reason); // Broken after last update
}
if (CS2_SimpleAdmin.UnlockedCommands && reason == NetworkDisconnectionReason.NETWORK_DISCONNECT_REJECT_BANNED)
Server.ExecuteCommand($"banid 1 {new SteamID(player.SteamID).SteamId3}");
// if (!string.IsNullOrEmpty(reason))
// {
@ -203,6 +265,57 @@ internal static class Helper
// Server.ExecuteCommand($"kickid {userId} {reason}");
}
public static int ParsePenaltyTime(string time)
{
if (string.IsNullOrWhiteSpace(time) || !time.Any(char.IsDigit))
{
// CS2_SimpleAdmin._logger?.LogError("Time string cannot be null or empty.");
return -1;
}
if (time.Equals($"0"))
return 0;
var timeUnits = new Dictionary<string, int>
{
{ "m", 1 }, // Minute
{ "h", 60 }, // Hour
{ "d", 1440 }, // Day (24 * 60)
{ "w", 10080 }, // Week (7 * 24 * 60)
{ "mo", 43200 }, // Month (30 * 24 * 60)
{ "y", 525600 } // Year (365 * 24 * 60)
};
// Check if the input is purely numeric (e.g., "10" for 10 minutes)
if (int.TryParse(time, out var numericMinutes))
{
return numericMinutes;
}
int totalMinutes = 0;
var regex = new Regex(@"(\d+)([a-z]+)");
var matches = regex.Matches(time);
foreach (Match match in matches)
{
var value = int.Parse(match.Groups[1].Value); // Numeric part
var unit = match.Groups[2].Value; // Unit part
if (timeUnits.TryGetValue(unit, out var minutesPerUnit))
{
totalMinutes += value * minutesPerUnit;
}
else
{
throw new ArgumentException($"Invalid time unit '{unit}' in time string.", nameof(time));
}
}
return totalMinutes > 0 ? totalMinutes : -1;
}
public static void PrintToCenterAll(string message)
{
Utilities.GetPlayers().Where(p => p is { IsValid: true, IsBot: false, IsHLTV: false }).ToList().ForEach(controller =>
@ -659,28 +772,28 @@ internal static class Helper
commandString]));
}
public static IMenu? CreateMenu(string title)
public static IMenu? CreateMenu(string title, Action<CCSPlayerController>? backAction = null)
{
var menuType = CS2_SimpleAdmin.Instance.Config.MenuConfigs.MenuType.ToLower();
var menu = menuType switch
{
_ when menuType.Equals("selectable", StringComparison.CurrentCultureIgnoreCase) =>
CS2_SimpleAdmin.MenuApi?.NewMenu(title),
CS2_SimpleAdmin.MenuApi?.GetMenu(title),
_ when menuType.Equals("dynamic", StringComparison.CurrentCultureIgnoreCase) =>
CS2_SimpleAdmin.MenuApi?.NewMenuForcetype(title, MenuType.ButtonMenu),
CS2_SimpleAdmin.MenuApi?.GetMenuForcetype(title, MenuType.ButtonMenu),
_ when menuType.Equals("center", StringComparison.CurrentCultureIgnoreCase) =>
CS2_SimpleAdmin.MenuApi?.NewMenuForcetype(title, MenuType.CenterMenu),
CS2_SimpleAdmin.MenuApi?.GetMenuForcetype(title, MenuType.CenterMenu),
_ when menuType.Equals("chat", StringComparison.CurrentCultureIgnoreCase) =>
CS2_SimpleAdmin.MenuApi?.NewMenuForcetype(title, MenuType.ChatMenu),
CS2_SimpleAdmin.MenuApi?.GetMenuForcetype(title, MenuType.ChatMenu),
_ when menuType.Equals("console", StringComparison.CurrentCultureIgnoreCase) =>
CS2_SimpleAdmin.MenuApi?.NewMenuForcetype(title, MenuType.ConsoleMenu),
CS2_SimpleAdmin.MenuApi?.GetMenuForcetype(title, MenuType.ConsoleMenu),
_ => CS2_SimpleAdmin.MenuApi?.NewMenu(title)
_ => CS2_SimpleAdmin.MenuApi?.GetMenu(title)
};
return menu;

View file

@ -10,21 +10,26 @@ namespace CS2_SimpleAdmin.Managers;
internal class BanManager(Database.Database? database)
{
public async Task BanPlayer(PlayerInfo player, PlayerInfo? issuer, string reason, int time = 0)
public async Task<int?> BanPlayer(PlayerInfo player, PlayerInfo? issuer, string reason, int time = 0)
{
if (database == null) return;
if (database == null) return null;
DateTime now = Time.ActualDateTime();
DateTime futureTime = now.AddMinutes(time);
await using MySqlConnection connection = await database.GetConnectionAsync();
try
{
const string sql =
"INSERT INTO `sa_bans` (`player_steamid`, `player_name`, `player_ip`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " +
"VALUES (@playerSteamid, @playerName, @playerIp, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid)";
const string sql = """
INSERT INTO `sa_bans`
(`player_steamid`, `player_name`, `player_ip`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`)
VALUES
(@playerSteamid, @playerName, @playerIp, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid);
SELECT LAST_INSERT_ID();
""";
await connection.ExecuteAsync(sql, new
var banId = await connection.ExecuteScalarAsync<int?>(sql, new
{
playerSteamid = player.SteamId.SteamId64.ToString(),
playerName = player.Name,
@ -37,15 +42,19 @@ internal class BanManager(Database.Database? database)
created = now,
serverid = CS2_SimpleAdmin.ServerId
});
return banId;
}
catch
{
return null;
}
catch { }
}
public async Task AddBanBySteamid(string playerSteamId, PlayerInfo? issuer, string reason, int time = 0)
public async Task<int?> AddBanBySteamid(string playerSteamId, PlayerInfo? issuer, string reason, int time = 0)
{
if (database == null) return;
if (string.IsNullOrEmpty(playerSteamId)) return;
if (database == null) return null;
if (string.IsNullOrEmpty(playerSteamId)) return null;
DateTime now = Time.ActualDateTime();
DateTime futureTime = now.AddMinutes(time);
@ -54,10 +63,16 @@ internal class BanManager(Database.Database? database)
{
await using MySqlConnection connection = await database.GetConnectionAsync();
var sql = "INSERT INTO `sa_bans` (`player_steamid`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " +
"VALUES (@playerSteamid, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid)";
const string sql = """
INSERT INTO `sa_bans`
(`player_steamid`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`)
VALUES
(@playerSteamid, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid);
SELECT LAST_INSERT_ID();
""";
await connection.ExecuteAsync(sql, new
var banId = await connection.ExecuteScalarAsync<int?>(sql, new
{
playerSteamid = playerSteamId,
adminSteamid = issuer?.SteamId.SteamId64.ToString() ?? CS2_SimpleAdmin._localizer?["sa_console"] ?? "Console",
@ -68,8 +83,13 @@ internal class BanManager(Database.Database? database)
created = now,
serverid = CS2_SimpleAdmin.ServerId
});
return banId;
}
catch (Exception)
{
return null;
}
catch { }
}
public async Task AddBanByIp(string playerIp, PlayerInfo? issuer, string reason, int time = 0)
@ -383,7 +403,7 @@ internal class BanManager(Database.Database? database)
foreach (var player in filteredPlayers.Where(player => bannedSteamIds.Contains(player.SteamID) ||
(checkIpBans && bannedIps.Contains(player.IpAddress ?? ""))))
{
if (!player.UserId.HasValue) continue;
if (!player.UserId.HasValue || CS2_SimpleAdmin.PlayersInfo[player.UserId.Value].WaitingForKick) continue;
await Server.NextFrameAsync(() =>
{

View file

@ -6,9 +6,9 @@ namespace CS2_SimpleAdmin.Managers;
internal class MuteManager(Database.Database? database)
{
public async Task MutePlayer(PlayerInfo player, PlayerInfo? issuer, string reason, int time = 0, int type = 0)
public async Task<int?> MutePlayer(PlayerInfo player, PlayerInfo? issuer, string reason, int time = 0, int type = 0)
{
if (database == null) return;
if (database == null) return null;
var now = Time.ActualDateTime();
var futureTime = now.AddMinutes(time);
@ -23,11 +23,16 @@ internal class MuteManager(Database.Database? database)
try
{
await using var connection = await database.GetConnectionAsync();
const string sql =
"INSERT INTO `sa_mutes` (`player_steamid`, `player_name`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `type`, `server_id`) " +
"VALUES (@playerSteamid, @playerName, @adminSteamid, @adminName, @muteReason, @duration, @ends, @created, @type, @serverid)";
const string sql = """
INSERT INTO `sa_mutes`
(`player_steamid`, `player_name`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `type`, `server_id`)
VALUES
(@playerSteamid, @playerName, @adminSteamid, @adminName, @muteReason, @duration, @ends, @created, @type, @serverid);
SELECT LAST_INSERT_ID();
""";
await connection.ExecuteAsync(sql, new
var muteId = await connection.ExecuteScalarAsync<int?>(sql, new
{
playerSteamid = player.SteamId.SteamId64.ToString(),
playerName = player.Name,
@ -40,19 +45,20 @@ internal class MuteManager(Database.Database? database)
type = muteType,
serverid = CS2_SimpleAdmin.ServerId
});
return muteId;
}
catch (Exception ex)
{
CS2_SimpleAdmin._logger?.LogError(ex.Message);
};
return null;
}
}
public async Task AddMuteBySteamid(string playerSteamId, PlayerInfo? issuer, string reason, int time = 0, int type = 0)
public async Task<int?> AddMuteBySteamid(string playerSteamId, PlayerInfo? issuer, string reason, int time = 0, int type = 0)
{
if (database == null) return;
if (string.IsNullOrEmpty(playerSteamId)) return;
if (database == null) return null;
if (string.IsNullOrEmpty(playerSteamId)) return null;
var now = Time.ActualDateTime();
var futureTime = now.AddMinutes(time);
@ -67,10 +73,16 @@ internal class MuteManager(Database.Database? database)
try
{
await using var connection = await database.GetConnectionAsync();
const string sql = "INSERT INTO `sa_mutes` (`player_steamid`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `type`, `server_id`) " +
"VALUES (@playerSteamid, @adminSteamid, @adminName, @muteReason, @duration, @ends, @created, @type, @serverid)";
const string sql = """
INSERT INTO `sa_mutes`
(`player_steamid`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `type`, `server_id`)
VALUES
(@playerSteamid, @adminSteamid, @adminName, @muteReason, @duration, @ends, @created, @type, @serverid);
SELECT LAST_INSERT_ID();
""";
await connection.ExecuteAsync(sql, new
var muteId = await connection.ExecuteScalarAsync<int?>(sql, new
{
playerSteamid = playerSteamId,
adminSteamid = issuer?.SteamId.SteamId64.ToString() ?? CS2_SimpleAdmin._localizer?["sa_console"] ?? "Console",
@ -82,8 +94,13 @@ internal class MuteManager(Database.Database? database)
type = muteType,
serverid = CS2_SimpleAdmin.ServerId
});
return muteId;
}
catch
{
return null;
}
catch { };
}
public async Task<List<dynamic>> IsPlayerMuted(string steamId)

View file

@ -381,53 +381,72 @@ public class PermissionManager(Database.Database? database)
{
List<(string identity, string name, List<string> flags, int immunity, DateTime? ends)> allPlayers = await GetAllPlayersFlagsSA();
var validPlayers = allPlayers
.Where(player => SteamID.TryParse(player.identity, out _)) // Filter invalid SteamID
.Where(player => SteamID.TryParse(player.identity, out _))
.ToList();
/*
foreach (var player in allPlayers)
{
var (steamId, name, flags, immunity, ends) = player;
// Print or process each item
Console.WriteLine($"Player SteamID: {steamId}");
Console.WriteLine($"Player Name: {name}");
Console.WriteLine($"Flags: {string.Join(", ", flags)}");
Console.WriteLine($"Immunity: {immunity}");
Console.WriteLine($"Ends: {(ends.HasValue ? ends.Value.ToString("yyyy-MM-dd HH:mm:ss") : "Never")}");
Console.WriteLine(); // New line for better readability
}
*/
// foreach (var player in allPlayers)
// {
// var (steamId, name, flags, immunity, ends) = player;
//
// Console.WriteLine($"Player SteamID: {steamId}");
// Console.WriteLine($"Player Name: {name}");
// Console.WriteLine($"Flags: {string.Join(", ", flags)}");
// Console.WriteLine($"Immunity: {immunity}");
// Console.WriteLine($"Ends: {(ends.HasValue ? ends.Value.ToString("yyyy-MM-dd HH:mm:ss") : "Never")}");
// Console.WriteLine();
// }
var jsonData = validPlayers
.Select(player =>
{
SteamID.TryParse(player.identity, out var steamId);
var jsonData = validPlayers
.GroupBy(player => player.name) // Group by player name
.ToDictionary(
group => group.Key, // Use the player name as the key
group =>
{
// Consolidate data for players with the same name
var consolidatedData = group.Aggregate(
new
{
identity = string.Empty,
immunity = 0,
flags = new List<string>(),
groups = new List<string>()
},
(acc, player) =>
{
// Merge identities and use the latest or first non-null identity
if (string.IsNullOrEmpty(acc.identity) && !string.IsNullOrEmpty(player.identity))
{
acc = acc with { identity = player.identity };
}
// Update cache if SteamID is valid and not already cached
if (steamId != null && !AdminCache.ContainsKey(steamId))
{
AdminCache.TryAdd(steamId, player.ends);
}
// Combine immunities by taking the maximum value
acc = acc with { immunity = Math.Max(acc.immunity, player.immunity) };
// Create an anonymous object with player data
return new
{
playerName = player.name,
playerData = new
{
player.identity,
player.immunity,
flags = player.flags.Where(flag => flag.StartsWith("@")).ToList(),
groups = player.flags.Where(flag => flag.StartsWith("#")).ToList()
}
};
})
.ToDictionary(item => item.playerName, item => (object)item.playerData);
// Combine flags and groups, ensuring no duplicates
acc = acc with
{
flags = acc.flags.Concat(player.flags.Where(flag => flag.StartsWith($"@"))).Distinct().ToList(),
groups = acc.groups.Concat(player.flags.Where(flag => flag.StartsWith($"#"))).Distinct().ToList()
};
return acc;
});
foreach (var player in group)
{
SteamID.TryParse(player.identity, out var steamId);
if (steamId != null && !AdminCache.ContainsKey(steamId))
{
AdminCache.TryAdd(steamId, player.ends);
}
}
return (object)consolidatedData;
});
var json = JsonConvert.SerializeObject(jsonData, Formatting.Indented);
var filePath = Path.Combine(CS2_SimpleAdmin.Instance.ModuleDirectory, "data", "admins.json");
await File.WriteAllTextAsync(filePath, json);
//await File.WriteAllTextAsync(CS2_SimpleAdmin.Instance.ModuleDirectory + "/data/admins.json", json);

View file

@ -14,7 +14,7 @@ public class PlayerManager
{
private readonly CS2_SimpleAdminConfig _config = CS2_SimpleAdmin.Instance.Config;
public void LoadPlayerData(CCSPlayerController player)
public void LoadPlayerData(CCSPlayerController player, bool fullConnect = false)
{
if (player.IsBot || string.IsNullOrEmpty(player.IpAddress) || player.IpAddress.Contains("127.0.0.1"))
return;
@ -134,58 +134,61 @@ public class PlayerManager
return;
}
var warns = await CS2_SimpleAdmin.Instance.WarnManager.GetPlayerWarns(CS2_SimpleAdmin.PlayersInfo[userId], false);
var (totalMutes, totalGags, totalSilences) =
await CS2_SimpleAdmin.Instance.MuteManager.GetPlayerMutes(CS2_SimpleAdmin.PlayersInfo[userId]);
if (fullConnect)
{
var warns = await CS2_SimpleAdmin.Instance.WarnManager.GetPlayerWarns(CS2_SimpleAdmin.PlayersInfo[userId], false);
var (totalMutes, totalGags, totalSilences) =
await CS2_SimpleAdmin.Instance.MuteManager.GetPlayerMutes(CS2_SimpleAdmin.PlayersInfo[userId]);
CS2_SimpleAdmin.PlayersInfo[userId].TotalBans =
await CS2_SimpleAdmin.Instance.BanManager.GetPlayerBans(CS2_SimpleAdmin.PlayersInfo[userId]);
CS2_SimpleAdmin.PlayersInfo[userId].TotalMutes = totalMutes;
CS2_SimpleAdmin.PlayersInfo[userId].TotalGags = totalGags;
CS2_SimpleAdmin.PlayersInfo[userId].TotalSilences = totalSilences;
CS2_SimpleAdmin.PlayersInfo[userId].TotalWarns = warns.Count;
CS2_SimpleAdmin.PlayersInfo[userId].TotalBans =
await CS2_SimpleAdmin.Instance.BanManager.GetPlayerBans(CS2_SimpleAdmin.PlayersInfo[userId]);
CS2_SimpleAdmin.PlayersInfo[userId].TotalMutes = totalMutes;
CS2_SimpleAdmin.PlayersInfo[userId].TotalGags = totalGags;
CS2_SimpleAdmin.PlayersInfo[userId].TotalSilences = totalSilences;
CS2_SimpleAdmin.PlayersInfo[userId].TotalWarns = warns.Count;
// Check if the player is muted
var activeMutes = await CS2_SimpleAdmin.Instance.MuteManager.IsPlayerMuted(CS2_SimpleAdmin.PlayersInfo[userId].SteamId.SteamId64.ToString());
var activeMutes = await CS2_SimpleAdmin.Instance.MuteManager.IsPlayerMuted(CS2_SimpleAdmin.PlayersInfo[userId].SteamId.SteamId64.ToString());
if (activeMutes.Count > 0)
{
foreach (var mute in activeMutes)
if (activeMutes.Count > 0)
{
string muteType = mute.type;
DateTime ends = mute.ends;
int duration = mute.duration;
switch (muteType)
foreach (var mute in activeMutes)
{
// Apply mute penalty based on mute type
case "GAG":
PlayerPenaltyManager.AddPenalty(CS2_SimpleAdmin.PlayersInfo[userId].Slot, PenaltyType.Gag, ends, duration);
// if (CS2_SimpleAdmin._localizer != null)
// mutesList[PenaltyType.Gag].Add(CS2_SimpleAdmin._localizer["sa_player_penalty_info_active_gag", ends.ToLocalTime().ToString(CultureInfo.CurrentCulture)]);
break;
case "MUTE":
PlayerPenaltyManager.AddPenalty(CS2_SimpleAdmin.PlayersInfo[userId].Slot, PenaltyType.Mute, ends, duration);
await Server.NextFrameAsync(() =>
{
player.VoiceFlags = VoiceFlags.Muted;
});
// if (CS2_SimpleAdmin._localizer != null)
// mutesList[PenaltyType.Mute].Add(CS2_SimpleAdmin._localizer["sa_player_penalty_info_active_mute", ends.ToLocalTime().ToString(CultureInfo.InvariantCulture)]);
break;
default:
PlayerPenaltyManager.AddPenalty(CS2_SimpleAdmin.PlayersInfo[userId].Slot, PenaltyType.Silence, ends, duration);
await Server.NextFrameAsync(() =>
{
player.VoiceFlags = VoiceFlags.Muted;
});
// if (CS2_SimpleAdmin._localizer != null)
// mutesList[PenaltyType.Silence].Add(CS2_SimpleAdmin._localizer["sa_player_penalty_info_active_silence", ends.ToLocalTime().ToString(CultureInfo.CurrentCulture)]);
break;
string muteType = mute.type;
DateTime ends = mute.ends;
int duration = mute.duration;
switch (muteType)
{
// Apply mute penalty based on mute type
case "GAG":
PlayerPenaltyManager.AddPenalty(CS2_SimpleAdmin.PlayersInfo[userId].Slot, PenaltyType.Gag, ends, duration);
// if (CS2_SimpleAdmin._localizer != null)
// mutesList[PenaltyType.Gag].Add(CS2_SimpleAdmin._localizer["sa_player_penalty_info_active_gag", ends.ToLocalTime().ToString(CultureInfo.CurrentCulture)]);
break;
case "MUTE":
PlayerPenaltyManager.AddPenalty(CS2_SimpleAdmin.PlayersInfo[userId].Slot, PenaltyType.Mute, ends, duration);
await Server.NextFrameAsync(() =>
{
player.VoiceFlags = VoiceFlags.Muted;
});
// if (CS2_SimpleAdmin._localizer != null)
// mutesList[PenaltyType.Mute].Add(CS2_SimpleAdmin._localizer["sa_player_penalty_info_active_mute", ends.ToLocalTime().ToString(CultureInfo.InvariantCulture)]);
break;
default:
PlayerPenaltyManager.AddPenalty(CS2_SimpleAdmin.PlayersInfo[userId].Slot, PenaltyType.Silence, ends, duration);
await Server.NextFrameAsync(() =>
{
player.VoiceFlags = VoiceFlags.Muted;
});
// if (CS2_SimpleAdmin._localizer != null)
// mutesList[PenaltyType.Silence].Add(CS2_SimpleAdmin._localizer["sa_player_penalty_info_active_silence", ends.ToLocalTime().ToString(CultureInfo.CurrentCulture)]);
break;
}
}
}
}
if (CS2_SimpleAdmin.Instance.Config.OtherSettings.NotifyPenaltiesToAdminOnConnect)
if (CS2_SimpleAdmin.Instance.Config.OtherSettings.NotifyPenaltiesToAdminOnConnect && fullConnect)
{
await Server.NextFrameAsync(() =>
{

View file

@ -9,6 +9,16 @@ public class ServerManager
{
private int _getIpTryCount;
public void CheckHibernationStatus()
{
ConVar? convar = ConVar.Find("sv_hibernate_when_empty");
if (convar == null || !convar.GetPrimitiveValue<bool>())
return;
CS2_SimpleAdmin._logger?.LogError("Detected setting \"sv_hibernate_when_empty true\", set false to make plugin work properly");
}
public void LoadServerData()
{
CS2_SimpleAdmin.Instance.AddTimer(1.2f, () =>

View file

@ -6,9 +6,9 @@ namespace CS2_SimpleAdmin.Managers;
internal class WarnManager(Database.Database? database)
{
public async Task WarnPlayer(PlayerInfo player, PlayerInfo? issuer, string reason, int time = 0)
public async Task<int?> WarnPlayer(PlayerInfo player, PlayerInfo? issuer, string reason, int time = 0)
{
if (database == null) return;
if (database == null) return null;
var now = Time.ActualDateTime();
var futureTime = now.AddMinutes(time);
@ -16,11 +16,16 @@ internal class WarnManager(Database.Database? database)
try
{
await using var connection = await database.GetConnectionAsync();
const string sql =
"INSERT INTO `sa_warns` (`player_steamid`, `player_name`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " +
"VALUES (@playerSteamid, @playerName, @adminSteamid, @adminName, @muteReason, @duration, @ends, @created, @serverid)";
const string sql = """
INSERT INTO `sa_warns`
(`player_steamid`, `player_name`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`)
VALUES
(@playerSteamid, @playerName, @adminSteamid, @adminName, @muteReason, @duration, @ends, @created, @serverid);
SELECT LAST_INSERT_ID();
""";
await connection.ExecuteAsync(sql, new
var warnId = await connection.ExecuteScalarAsync<int?>(sql, new
{
playerSteamid = player.SteamId.SteamId64.ToString(),
playerName = player.Name,
@ -32,14 +37,19 @@ internal class WarnManager(Database.Database? database)
created = now,
serverid = CS2_SimpleAdmin.ServerId
});
return warnId;
}
catch
{
return null;
}
catch { };
}
public async Task AddWarnBySteamid(string playerSteamId, PlayerInfo? issuer, string reason, int time = 0)
public async Task<int?> AddWarnBySteamid(string playerSteamId, PlayerInfo? issuer, string reason, int time = 0)
{
if (database == null) return;
if (string.IsNullOrEmpty(playerSteamId)) return;
if (database == null) return null;
if (string.IsNullOrEmpty(playerSteamId)) return null;
var now = Time.ActualDateTime();
var futureTime = now.AddMinutes(time);
@ -47,10 +57,16 @@ internal class WarnManager(Database.Database? database)
try
{
await using var connection = await database.GetConnectionAsync();
const string sql = "INSERT INTO `sa_warns` (`player_steamid`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " +
"VALUES (@playerSteamid, @adminSteamid, @adminName, @muteReason, @duration, @ends, @created, @serverid)";
const string sql = """
INSERT INTO `sa_warns`
(`player_steamid`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`)
VALUES
(@playerSteamid, @adminSteamid, @adminName, @muteReason, @duration, @ends, @created, @serverid);
SELECT LAST_INSERT_ID();
""";
await connection.ExecuteAsync(sql, new
var warnId = await connection.ExecuteScalarAsync<int?>(sql, new
{
playerSteamid = playerSteamId,
adminSteamid = issuer?.SteamId.ToString() ?? CS2_SimpleAdmin._localizer?["sa_console"] ?? "Console",
@ -61,8 +77,13 @@ internal class WarnManager(Database.Database? database)
created = now,
serverid = CS2_SimpleAdmin.ServerId
});
return warnId;
}
catch
{
return null;
}
catch { };
}
public async Task<List<dynamic>> GetPlayerWarns(PlayerInfo player, bool active = true)
@ -153,14 +174,32 @@ internal class WarnManager(Database.Database? database)
await using var connection = await database.GetConnectionAsync();
var sql = CS2_SimpleAdmin.Instance.Config.MultiServerMode
? "UPDATE sa_warns SET status = 'EXPIRED' WHERE status = 'ACTIVE' AND player_steamid = @steamid AND id = (SELECT MAX(id) FROM sa_warns WHERE player_steamid = @steamid AND status = 'ACTIVE')"
: "UPDATE sa_warns SET status = 'EXPIRED' WHERE status = 'ACTIVE' AND player_steamid = @steamid AND id = (SELECT MAX(id) FROM sa_warns WHERE player_steamid = @steamid AND status = 'ACTIVE' AND server_id = @serverid)";
? """
UPDATE sa_warns
JOIN (
SELECT MAX(id) AS max_id
FROM sa_warns
WHERE player_steamid = @steamid AND status = 'ACTIVE'
) AS subquery ON sa_warns.id = subquery.max_id
SET sa_warns.status = 'EXPIRED'
WHERE sa_warns.status = 'ACTIVE' AND sa_warns.player_steamid = @steamid;
"""
: """
UPDATE sa_warns
JOIN (
SELECT MAX(id) AS max_id
FROM sa_warns
WHERE player_steamid = @steamid AND status = 'ACTIVE' AND server_id = @serverid
) AS subquery ON sa_warns.id = subquery.max_id
SET sa_warns.status = 'EXPIRED'
WHERE sa_warns.status = 'ACTIVE' AND sa_warns.player_steamid = @steamid AND sa_warns.server_id = @serverid;
""";
await connection.ExecuteAsync(sql, new { steamid = playerPattern, serverid = CS2_SimpleAdmin.ServerId });
}
catch (Exception ex)
{
CS2_SimpleAdmin._logger?.LogCritical($"Unable to remove last warn + {ex}");
CS2_SimpleAdmin._logger?.LogCritical("Unable to remove last warn {exception}", ex.Message);
}
}

View file

@ -6,9 +6,9 @@ namespace CS2_SimpleAdmin.Menus;
public static class AdminMenu
{
public static IMenu? CreateMenu(string title)
public static IMenu? CreateMenu(string title, Action<CCSPlayerController>? backAction = null)
{
return Helper.CreateMenu(title);
return Helper.CreateMenu(title, backAction);
// return CS2_SimpleAdmin.Instance.Config.UseChatMenu ? new ChatMenu(title) : new CenterHtmlMenu(title, CS2_SimpleAdmin.Instance);
}

View file

@ -46,7 +46,7 @@ public static class ReasonMenu
{
menu?.AddMenuOption(reason, (_, _) => onSelectAction(admin, player, reason));
}
if (menu != null) AdminMenu.OpenMenu(admin, menu);
}
}

View file

@ -1 +1 @@
1.7.0a
1.7.2a

View file

@ -17,8 +17,8 @@ public interface ICS2_SimpleAdminApi
public Dictionary<PenaltyType, List<(DateTime EndDateTime, int Duration, bool Passed)>> GetPlayerMuteStatus(CCSPlayerController player);
public event Action<PlayerInfo, PlayerInfo?, PenaltyType, string, int, int?>? OnPlayerPenaltied;
public event Action<SteamID, PlayerInfo?, PenaltyType, string, int, int?>? OnPlayerPenaltiedAdded;
public event Action<PlayerInfo, PlayerInfo?, PenaltyType, string, int, int?, int?>? OnPlayerPenaltied;
public event Action<SteamID, PlayerInfo?, PenaltyType, string, int, int?, int?>? OnPlayerPenaltiedAdded;
public void IssuePenalty(CCSPlayerController player, CCSPlayerController? admin, PenaltyType penaltyType, string reason, int duration = -1);
public void LogCommand(CCSPlayerController? caller, string command);

View file

@ -25,6 +25,7 @@ public class PlayerInfo(
public int TotalGags { get; set; } = totalGags;
public int TotalSilences { get; set; } = totalSilences;
public int TotalWarns { get; set; } = totalWarns;
public bool WaitingForKick { get; set; } = false;
public DiePosition? DiePosition { get; set; }
}

View file

@ -70,7 +70,7 @@ public class CS2_SimpleAdmin_ExampleModule: BasePlugin
}
private void OnPlayerPenaltied(PlayerInfo player, PlayerInfo? admin, PenaltyType penaltyType,
string reason, int duration, int? serverId)
string reason, int duration, int? penaltyId, int? serverId)
{
if (penaltyType == PenaltyType.Ban)
{
@ -82,6 +82,7 @@ public class CS2_SimpleAdmin_ExampleModule: BasePlugin
case PenaltyType.Ban:
{
Logger.LogInformation("Ban issued");
Logger.LogInformation($"Id = {penaltyId}");
break;
}
case PenaltyType.Kick:
@ -92,6 +93,7 @@ public class CS2_SimpleAdmin_ExampleModule: BasePlugin
case PenaltyType.Gag:
{
Logger.LogInformation("Gag issued");
Logger.LogInformation($"Id = {penaltyId}");
break;
}
case PenaltyType.Mute:
@ -120,13 +122,14 @@ public class CS2_SimpleAdmin_ExampleModule: BasePlugin
}
private void OnPlayerPenaltiedAdded(SteamID steamId, PlayerInfo? admin, PenaltyType penaltyType,
string reason, int duration, int? serverId)
string reason, int duration, int? penaltyId, int? serverId)
{
switch (penaltyType)
{
case PenaltyType.Ban:
{
Logger.LogInformation("Ban added");
Logger.LogInformation($"Id = {penaltyId}");
break;
}
case PenaltyType.Kick:
@ -137,6 +140,7 @@ public class CS2_SimpleAdmin_ExampleModule: BasePlugin
case PenaltyType.Gag:
{
Logger.LogInformation("Gag added");
Logger.LogInformation($"Id = {penaltyId}");
break;
}
case PenaltyType.Mute: